Commit c2d03227 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Mfill][Android] Recreate destroyed filling components

There are rare cases when the the Android native UI is recreated but the
native parts remain untouched (e.g. when the theme is changed).

To prevent native classes using stale providers, reset them when the
component is destroyed and recreate them lazily as needed.
(Since this touches the way the native object is created, clean that
up as well to prevent rare crashes.)

Bug: 1094397, 1051030
Change-Id: I9c5cd1e225db1b4ca61c5136571a0e552fe86940
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2403641Reviewed-by: default avatarVadym Doroshenko  <dvadym@chromium.org>
Reviewed-by: default avatarIoana Pandele <ioanap@chromium.org>
Commit-Queue: Friedrich [CET] <fhorschig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#806934}
parent 581f0c7e
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.keyboard_accessory; package org.chromium.chrome.browser.keyboard_accessory;
import android.app.Activity;
import android.util.SparseArray; import android.util.SparseArray;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
...@@ -25,25 +26,23 @@ import org.chromium.ui.base.WindowAndroid; ...@@ -25,25 +26,23 @@ import org.chromium.ui.base.WindowAndroid;
class ManualFillingComponentBridge { class ManualFillingComponentBridge {
private final SparseArray<PropertyProvider<AccessorySheetData>> mProviders = private final SparseArray<PropertyProvider<AccessorySheetData>> mProviders =
new SparseArray<>(); new SparseArray<>();
private final PropertyProvider<Action[]> mActionProvider = private PropertyProvider<Action[]> mActionProvider;
new PropertyProvider<>(AccessoryAction.GENERATE_PASSWORD_AUTOMATIC); private final WindowAndroid mWindowAndroid;
private final ManualFillingComponent mManualFillingComponent;
private final ChromeActivity mActivity;
private long mNativeView; private long mNativeView;
private final ManualFillingComponent.Observer mDestructionObserver = this::onComponentDestroyed;
private ManualFillingComponentBridge(long nativeView, WindowAndroid windowAndroid) { private ManualFillingComponentBridge(long nativeView, WindowAndroid windowAndroid) {
mNativeView = nativeView; mNativeView = nativeView;
mActivity = (ChromeActivity) windowAndroid.getActivity().get(); mWindowAndroid = windowAndroid;
mManualFillingComponent = mActivity.getManualFillingComponent();
mManualFillingComponent.registerActionProvider(mActionProvider);
} }
PropertyProvider<AccessorySheetData> getOrCreateProvider(@AccessoryTabType int tabType) { PropertyProvider<AccessorySheetData> getOrCreateProvider(@AccessoryTabType int tabType) {
PropertyProvider<AccessorySheetData> provider = mProviders.get(tabType); PropertyProvider<AccessorySheetData> provider = mProviders.get(tabType);
if (provider != null) return provider; if (provider != null) return provider;
if (getManualFillingComponent() == null) return null;
provider = new PropertyProvider<>(); provider = new PropertyProvider<>();
mProviders.put(tabType, provider); mProviders.put(tabType, provider);
mManualFillingComponent.registerSheetDataProvider(tabType, provider); getManualFillingComponent().registerSheetDataProvider(tabType, provider);
return provider; return provider;
} }
...@@ -56,20 +55,23 @@ class ManualFillingComponentBridge { ...@@ -56,20 +55,23 @@ class ManualFillingComponentBridge {
@CalledByNative @CalledByNative
private void onItemsAvailable(Object objAccessorySheetData) { private void onItemsAvailable(Object objAccessorySheetData) {
AccessorySheetData accessorySheetData = (AccessorySheetData) objAccessorySheetData; AccessorySheetData accessorySheetData = (AccessorySheetData) objAccessorySheetData;
getOrCreateProvider(accessorySheetData.getSheetType()).notifyObservers(accessorySheetData); PropertyProvider<AccessorySheetData> provider =
getOrCreateProvider(accessorySheetData.getSheetType());
if (provider != null) provider.notifyObservers(accessorySheetData);
} }
@CalledByNative @CalledByNative
private void onAutomaticGenerationStatusChanged(boolean available) { private void onAutomaticGenerationStatusChanged(boolean available) {
final Action[] generationAction; final Action[] generationAction;
if (available) { final Activity activity = mWindowAndroid.getActivity().get();
if (available && activity != null) {
// This is meant to suppress the warning that the short string is not used. // This is meant to suppress the warning that the short string is not used.
// TODO(crbug.com/855581): Switch between strings based on whether they fit on the // TODO(crbug.com/855581): Switch between strings based on whether they fit on the
// screen or not. // screen or not.
boolean useLongString = true; boolean useLongString = true;
String caption = useLongString String caption = useLongString
? mActivity.getString(R.string.password_generation_accessory_button) ? activity.getString(R.string.password_generation_accessory_button)
: mActivity.getString(R.string.password_generation_accessory_button_short); : activity.getString(R.string.password_generation_accessory_button_short);
generationAction = new Action[] { generationAction = new Action[] {
new Action(caption, AccessoryAction.GENERATE_PASSWORD_AUTOMATIC, (action) -> { new Action(caption, AccessoryAction.GENERATE_PASSWORD_AUTOMATIC, (action) -> {
assert mNativeView assert mNativeView
...@@ -84,31 +86,46 @@ class ManualFillingComponentBridge { ...@@ -84,31 +86,46 @@ class ManualFillingComponentBridge {
} else { } else {
generationAction = new Action[0]; generationAction = new Action[0];
} }
mActionProvider.notifyObservers(generationAction); if (mActionProvider == null && getManualFillingComponent() != null) {
mActionProvider = new PropertyProvider<>(AccessoryAction.GENERATE_PASSWORD_AUTOMATIC);
getManualFillingComponent().registerActionProvider(mActionProvider);
}
if (mActionProvider != null) mActionProvider.notifyObservers(generationAction);
} }
@CalledByNative @CalledByNative
void showWhenKeyboardIsVisible() { void showWhenKeyboardIsVisible() {
mManualFillingComponent.showWhenKeyboardIsVisible(); if (getManualFillingComponent() != null) {
getManualFillingComponent().showWhenKeyboardIsVisible();
}
} }
@CalledByNative @CalledByNative
void hide() { void hide() {
mManualFillingComponent.hide(); if (getManualFillingComponent() != null) {
getManualFillingComponent().hide();
}
} }
@CalledByNative @CalledByNative
private void closeAccessorySheet() { private void closeAccessorySheet() {
mManualFillingComponent.closeAccessorySheet(); if (getManualFillingComponent() != null) {
getManualFillingComponent().closeAccessorySheet();
}
} }
@CalledByNative @CalledByNative
private void swapSheetWithKeyboard() { private void swapSheetWithKeyboard() {
mManualFillingComponent.swapSheetWithKeyboard(); if (getManualFillingComponent() != null) {
getManualFillingComponent().swapSheetWithKeyboard();
}
} }
@CalledByNative @CalledByNative
private void destroy() { private void destroy() {
if (getManualFillingComponent() != null) {
getManualFillingComponent().removeObserver(mDestructionObserver);
}
for (int i = 0; i < mProviders.size(); ++i) { for (int i = 0; i < mProviders.size(); ++i) {
mProviders.valueAt(i).notifyObservers(null); mProviders.valueAt(i).notifyObservers(null);
} }
...@@ -195,6 +212,20 @@ class ManualFillingComponentBridge { ...@@ -195,6 +212,20 @@ class ManualFillingComponentBridge {
ManualFillingComponentBridgeJni.get().disableServerPredictionsForTesting(); ManualFillingComponentBridgeJni.get().disableServerPredictionsForTesting();
} }
private ManualFillingComponent getManualFillingComponent() {
ChromeActivity activity = (ChromeActivity) mWindowAndroid.getActivity().get();
if (activity == null) return null; // Has the activity died since it was last checked?
activity.getManualFillingComponent().addObserver(mDestructionObserver);
return activity.getManualFillingComponent();
}
private void onComponentDestroyed() {
if (mNativeView != 0) {
ManualFillingComponentBridgeJni.get().onViewDestroyed(
mNativeView, ManualFillingComponentBridge.this);
}
}
@NativeMethods @NativeMethods
interface Natives { interface Natives {
void onFillingTriggered(long nativeManualFillingViewAndroid, void onFillingTriggered(long nativeManualFillingViewAndroid,
...@@ -203,6 +234,8 @@ class ManualFillingComponentBridge { ...@@ -203,6 +234,8 @@ class ManualFillingComponentBridge {
ManualFillingComponentBridge caller, int accessoryAction); ManualFillingComponentBridge caller, int accessoryAction);
void onToggleChanged(long nativeManualFillingViewAndroid, void onToggleChanged(long nativeManualFillingViewAndroid,
ManualFillingComponentBridge caller, int accessoryAction, boolean enabled); ManualFillingComponentBridge caller, int accessoryAction, boolean enabled);
void onViewDestroyed(
long nativeManualFillingViewAndroid, ManualFillingComponentBridge caller);
void cachePasswordSheetDataForTesting(WebContents webContents, String[] userNames, void cachePasswordSheetDataForTesting(WebContents webContents, String[] userNames,
String[] passwords, boolean originBlacklisted); String[] passwords, boolean originBlacklisted);
void notifyFocusedFieldTypeForTesting(WebContents webContents, int focusedFieldType); void notifyFocusedFieldTypeForTesting(WebContents webContents, int focusedFieldType);
......
...@@ -9,6 +9,7 @@ import android.view.ViewStub; ...@@ -9,6 +9,7 @@ import android.view.ViewStub;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.base.ObserverList;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryCoordinator; import org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryCoordinator;
import org.chromium.chrome.browser.keyboard_accessory.data.KeyboardAccessoryData; import org.chromium.chrome.browser.keyboard_accessory.data.KeyboardAccessoryData;
...@@ -30,6 +31,7 @@ import org.chromium.ui.base.WindowAndroid; ...@@ -30,6 +31,7 @@ import org.chromium.ui.base.WindowAndroid;
*/ */
class ManualFillingCoordinator implements ManualFillingComponent { class ManualFillingCoordinator implements ManualFillingComponent {
private final ManualFillingMediator mMediator = new ManualFillingMediator(); private final ManualFillingMediator mMediator = new ManualFillingMediator();
private ObserverList<Observer> mObserverList = new ObserverList<>();
public ManualFillingCoordinator() {} public ManualFillingCoordinator() {}
...@@ -55,6 +57,7 @@ class ManualFillingCoordinator implements ManualFillingComponent { ...@@ -55,6 +57,7 @@ class ManualFillingCoordinator implements ManualFillingComponent {
@Override @Override
public void destroy() { public void destroy() {
for (Observer observer : mObserverList) observer.onDestroy();
mMediator.destroy(); mMediator.destroy();
} }
...@@ -126,6 +129,16 @@ class ManualFillingCoordinator implements ManualFillingComponent { ...@@ -126,6 +129,16 @@ class ManualFillingCoordinator implements ManualFillingComponent {
return mMediator.isFillingViewShown(view); return mMediator.isFillingViewShown(view);
} }
@Override
public boolean addObserver(Observer observer) {
return mObserverList.addObserver(observer);
}
@Override
public boolean removeObserver(Observer observer) {
return mObserverList.addObserver(observer);
}
@VisibleForTesting @VisibleForTesting
ManualFillingMediator getMediatorForTesting() { ManualFillingMediator getMediatorForTesting() {
return mMediator; return mMediator;
......
...@@ -19,6 +19,15 @@ import org.chromium.ui.base.WindowAndroid; ...@@ -19,6 +19,15 @@ import org.chromium.ui.base.WindowAndroid;
* This component handles the new, non-popup filling UI. * This component handles the new, non-popup filling UI.
*/ */
public interface ManualFillingComponent { public interface ManualFillingComponent {
/**
* Observers are added with {@link #addObserver} and removed with {@link #removeObserver}.
* They are notified when the {@link ManualFillingComponent} is destroyed.
*/
interface Observer {
/** Called if the ManualFillingComponent is destroyed. */
void onDestroy();
}
/** /**
* Initializes the manual filling component. Calls to this class are NoOps until this method * Initializes the manual filling component. Calls to this class are NoOps until this method
* is called. * is called.
...@@ -116,4 +125,16 @@ public interface ManualFillingComponent { ...@@ -116,4 +125,16 @@ public interface ManualFillingComponent {
* @param view A {@link View} that is used to find the window root. * @param view A {@link View} that is used to find the window root.
*/ */
boolean isFillingViewShown(View view); boolean isFillingViewShown(View view);
/**
* @param observer An {@link Observer} to add.
* @return True iff the observer could be added.
*/
boolean addObserver(Observer observer);
/**
* @param observer An {@link Observer} to add.
* @return True iff the observer could be remove.
*/
boolean removeObserver(Observer observer);
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "chrome/browser/password_manager/android/password_accessory_metrics_util.h" #include "chrome/browser/password_manager/android/password_accessory_metrics_util.h"
#include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "components/autofill/core/browser/ui/accessory_sheet_data.h"
#include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_util.h" #include "components/autofill/core/common/autofill_util.h"
#include "components/keyed_service/core/service_access_type.h" #include "components/keyed_service/core/service_access_type.h"
...@@ -108,6 +109,8 @@ void ManualFillingControllerImpl::OnAutomaticGenerationStatusChanged( ...@@ -108,6 +109,8 @@ void ManualFillingControllerImpl::OnAutomaticGenerationStatusChanged(
void ManualFillingControllerImpl::RefreshSuggestions( void ManualFillingControllerImpl::RefreshSuggestions(
const AccessorySheetData& accessory_sheet_data) { const AccessorySheetData& accessory_sheet_data) {
view_->OnItemsAvailable(accessory_sheet_data); view_->OnItemsAvailable(accessory_sheet_data);
available_sheets_.emplace(GetSourceForTab(accessory_sheet_data),
accessory_sheet_data);
UpdateSourceAvailability(GetSourceForTab(accessory_sheet_data), UpdateSourceAvailability(GetSourceForTab(accessory_sheet_data),
!accessory_sheet_data.user_info_list().empty()); !accessory_sheet_data.user_info_list().empty());
} }
...@@ -268,6 +271,11 @@ bool ManualFillingControllerImpl::ShouldShowAccessory() const { ...@@ -268,6 +271,11 @@ bool ManualFillingControllerImpl::ShouldShowAccessory() const {
void ManualFillingControllerImpl::UpdateVisibility() { void ManualFillingControllerImpl::UpdateVisibility() {
if (ShouldShowAccessory()) { if (ShouldShowAccessory()) {
for (const FillingSource& source : available_sources_) {
if (!available_sheets_.contains(source))
continue;
view_->OnItemsAvailable(available_sheets_.find(source)->second);
}
view_->ShowWhenKeyboardIsVisible(); view_->ShowWhenKeyboardIsVisible();
} else { } else {
view_->Hide(); view_->Hide();
......
...@@ -21,7 +21,6 @@ class AddressAccessoryController; ...@@ -21,7 +21,6 @@ class AddressAccessoryController;
class CreditCardAccessoryController; class CreditCardAccessoryController;
} // namespace autofill } // namespace autofill
class AccessoryController; class AccessoryController;
class PasswordAccessoryController; class PasswordAccessoryController;
...@@ -112,6 +111,9 @@ class ManualFillingControllerImpl ...@@ -112,6 +111,9 @@ class ManualFillingControllerImpl
// This set contains sources to be shown to the user. // This set contains sources to be shown to the user.
base::flat_set<FillingSource> available_sources_; base::flat_set<FillingSource> available_sources_;
// This map contains sheets for each sources to be shown to the user.
base::flat_map<FillingSource, autofill::AccessorySheetData> available_sheets_;
// Type of the last known selected field. Helps to determine UI visibility. // Type of the last known selected field. Helps to determine UI visibility.
autofill::mojom::FocusedFieldType focused_field_type_ = autofill::mojom::FocusedFieldType focused_field_type_ =
autofill::mojom::FocusedFieldType::kUnknown; autofill::mojom::FocusedFieldType::kUnknown;
......
...@@ -44,58 +44,61 @@ using base::android::ScopedJavaLocalRef; ...@@ -44,58 +44,61 @@ using base::android::ScopedJavaLocalRef;
ManualFillingViewAndroid::ManualFillingViewAndroid( ManualFillingViewAndroid::ManualFillingViewAndroid(
ManualFillingController* controller) ManualFillingController* controller)
: controller_(controller) { : controller_(controller) {}
ui::ViewAndroid* view_android = controller_->container_view();
DCHECK(view_android);
java_object_.Reset(Java_ManualFillingComponentBridge_create(
base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this),
view_android->GetWindowAndroid()->GetJavaObject()));
}
ManualFillingViewAndroid::~ManualFillingViewAndroid() { ManualFillingViewAndroid::~ManualFillingViewAndroid() {
DCHECK(!java_object_.is_null()); if (!java_object_internal_)
return; // No work to do.
Java_ManualFillingComponentBridge_destroy( Java_ManualFillingComponentBridge_destroy(
base::android::AttachCurrentThread(), java_object_); base::android::AttachCurrentThread(), java_object_internal_);
java_object_.Reset(nullptr); java_object_internal_.Reset(nullptr);
} }
void ManualFillingViewAndroid::OnItemsAvailable( void ManualFillingViewAndroid::OnItemsAvailable(
const AccessorySheetData& data) { const AccessorySheetData& data) {
DCHECK(!java_object_.is_null()); if (auto obj = GetOrCreateJavaObject()) {
JNIEnv* env = base::android::AttachCurrentThread();
JNIEnv* env = base::android::AttachCurrentThread(); Java_ManualFillingComponentBridge_onItemsAvailable(
Java_ManualFillingComponentBridge_onItemsAvailable( env, obj, ConvertAccessorySheetDataToJavaObject(env, data));
env, java_object_, ConvertAccessorySheetDataToJavaObject(env, data)); }
} }
void ManualFillingViewAndroid::CloseAccessorySheet() { void ManualFillingViewAndroid::CloseAccessorySheet() {
Java_ManualFillingComponentBridge_closeAccessorySheet( if (auto obj = GetOrCreateJavaObject()) {
base::android::AttachCurrentThread(), java_object_); Java_ManualFillingComponentBridge_closeAccessorySheet(
base::android::AttachCurrentThread(), obj);
}
} }
void ManualFillingViewAndroid::SwapSheetWithKeyboard() { void ManualFillingViewAndroid::SwapSheetWithKeyboard() {
Java_ManualFillingComponentBridge_swapSheetWithKeyboard( if (auto obj = GetOrCreateJavaObject()) {
base::android::AttachCurrentThread(), java_object_); Java_ManualFillingComponentBridge_swapSheetWithKeyboard(
base::android::AttachCurrentThread(), obj);
}
} }
void ManualFillingViewAndroid::ShowWhenKeyboardIsVisible() { void ManualFillingViewAndroid::ShowWhenKeyboardIsVisible() {
Java_ManualFillingComponentBridge_showWhenKeyboardIsVisible( if (auto obj = GetOrCreateJavaObject()) {
base::android::AttachCurrentThread(), java_object_); Java_ManualFillingComponentBridge_showWhenKeyboardIsVisible(
base::android::AttachCurrentThread(), obj);
}
} }
void ManualFillingViewAndroid::Hide() { void ManualFillingViewAndroid::Hide() {
Java_ManualFillingComponentBridge_hide(base::android::AttachCurrentThread(), if (auto obj = GetOrCreateJavaObject()) {
java_object_); Java_ManualFillingComponentBridge_hide(base::android::AttachCurrentThread(),
obj);
}
} }
void ManualFillingViewAndroid::OnAutomaticGenerationStatusChanged( void ManualFillingViewAndroid::OnAutomaticGenerationStatusChanged(
bool available) { bool available) {
if (!available && java_object_.is_null()) if (!available && java_object_internal_.is_null())
return; return;
if (auto obj = GetOrCreateJavaObject()) {
JNIEnv* env = base::android::AttachCurrentThread(); Java_ManualFillingComponentBridge_onAutomaticGenerationStatusChanged(
Java_ManualFillingComponentBridge_onAutomaticGenerationStatusChanged( base::android::AttachCurrentThread(), obj, available);
env, java_object_, available); }
} }
void ManualFillingViewAndroid::OnFillingTriggered( void ManualFillingViewAndroid::OnFillingTriggered(
...@@ -125,10 +128,17 @@ void ManualFillingViewAndroid::OnToggleChanged( ...@@ -125,10 +128,17 @@ void ManualFillingViewAndroid::OnToggleChanged(
static_cast<autofill::AccessoryAction>(selected_action), enabled); static_cast<autofill::AccessoryAction>(selected_action), enabled);
} }
void ManualFillingViewAndroid::OnViewDestroyed(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
java_object_internal_.Reset(nullptr);
}
ScopedJavaLocalRef<jobject> ScopedJavaLocalRef<jobject>
ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject( ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject(
JNIEnv* env, JNIEnv* env,
const AccessorySheetData& tab_data) { const AccessorySheetData& tab_data) {
DCHECK(java_object_internal_);
ScopedJavaLocalRef<jobject> j_tab_data = ScopedJavaLocalRef<jobject> j_tab_data =
Java_ManualFillingComponentBridge_createAccessorySheetData( Java_ManualFillingComponentBridge_createAccessorySheetData(
env, static_cast<int>(tab_data.get_sheet_type()), env, static_cast<int>(tab_data.get_sheet_type()),
...@@ -138,7 +148,7 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject( ...@@ -138,7 +148,7 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject(
if (tab_data.option_toggle().has_value()) { if (tab_data.option_toggle().has_value()) {
autofill::OptionToggle toggle = tab_data.option_toggle().value(); autofill::OptionToggle toggle = tab_data.option_toggle().value();
Java_ManualFillingComponentBridge_addOptionToggleToAccessorySheetData( Java_ManualFillingComponentBridge_addOptionToggleToAccessorySheetData(
env, java_object_, j_tab_data, env, java_object_internal_, j_tab_data,
ConvertUTF16ToJavaString(env, toggle.display_text()), ConvertUTF16ToJavaString(env, toggle.display_text()),
toggle.is_enabled(), static_cast<int>(toggle.accessory_action())); toggle.is_enabled(), static_cast<int>(toggle.accessory_action()));
} }
...@@ -146,12 +156,12 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject( ...@@ -146,12 +156,12 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject(
for (const UserInfo& user_info : tab_data.user_info_list()) { for (const UserInfo& user_info : tab_data.user_info_list()) {
ScopedJavaLocalRef<jobject> j_user_info = ScopedJavaLocalRef<jobject> j_user_info =
Java_ManualFillingComponentBridge_addUserInfoToAccessorySheetData( Java_ManualFillingComponentBridge_addUserInfoToAccessorySheetData(
env, java_object_, j_tab_data, env, java_object_internal_, j_tab_data,
ConvertUTF8ToJavaString(env, user_info.origin()), ConvertUTF8ToJavaString(env, user_info.origin()),
user_info.is_psl_match().value()); user_info.is_psl_match().value());
for (const UserInfo::Field& field : user_info.fields()) { for (const UserInfo::Field& field : user_info.fields()) {
Java_ManualFillingComponentBridge_addFieldToUserInfo( Java_ManualFillingComponentBridge_addFieldToUserInfo(
env, java_object_, j_user_info, env, java_object_internal_, j_user_info,
static_cast<int>(tab_data.get_sheet_type()), static_cast<int>(tab_data.get_sheet_type()),
ConvertUTF16ToJavaString(env, field.display_text()), ConvertUTF16ToJavaString(env, field.display_text()),
ConvertUTF16ToJavaString(env, field.a11y_description()), ConvertUTF16ToJavaString(env, field.a11y_description()),
...@@ -162,7 +172,7 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject( ...@@ -162,7 +172,7 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject(
for (const FooterCommand& footer_command : tab_data.footer_commands()) { for (const FooterCommand& footer_command : tab_data.footer_commands()) {
Java_ManualFillingComponentBridge_addFooterCommandToAccessorySheetData( Java_ManualFillingComponentBridge_addFooterCommandToAccessorySheetData(
env, java_object_, j_tab_data, env, java_object_internal_, j_tab_data,
ConvertUTF16ToJavaString(env, footer_command.display_text()), ConvertUTF16ToJavaString(env, footer_command.display_text()),
static_cast<int>(footer_command.accessory_action())); static_cast<int>(footer_command.accessory_action()));
} }
...@@ -184,6 +194,18 @@ UserInfo::Field ManualFillingViewAndroid::ConvertJavaUserInfoField( ...@@ -184,6 +194,18 @@ UserInfo::Field ManualFillingViewAndroid::ConvertJavaUserInfoField(
selectable); selectable);
} }
base::android::ScopedJavaGlobalRef<jobject>
ManualFillingViewAndroid::GetOrCreateJavaObject() {
if (java_object_internal_)
return java_object_internal_;
ui::ViewAndroid* view_android = controller_->container_view();
DCHECK(view_android);
java_object_internal_.Reset(Java_ManualFillingComponentBridge_create(
base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this),
view_android->GetWindowAndroid()->GetJavaObject()));
return java_object_internal_;
}
// static // static
void JNI_ManualFillingComponentBridge_CachePasswordSheetDataForTesting( void JNI_ManualFillingComponentBridge_CachePasswordSheetDataForTesting(
JNIEnv* env, JNIEnv* env,
......
...@@ -54,6 +54,8 @@ class ManualFillingViewAndroid : public ManualFillingViewInterface { ...@@ -54,6 +54,8 @@ class ManualFillingViewAndroid : public ManualFillingViewInterface {
const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& obj,
jint selected_action, jint selected_action,
jboolean enabled); jboolean enabled);
void OnViewDestroyed(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
private: private:
void OnImageFetched(base::android::ScopedJavaGlobalRef<jstring> j_origin, void OnImageFetched(base::android::ScopedJavaGlobalRef<jstring> j_origin,
...@@ -69,11 +71,13 @@ class ManualFillingViewAndroid : public ManualFillingViewInterface { ...@@ -69,11 +71,13 @@ class ManualFillingViewAndroid : public ManualFillingViewInterface {
JNIEnv* env, JNIEnv* env,
const base::android::JavaRef<jobject>& j_field_to_convert); const base::android::JavaRef<jobject>& j_field_to_convert);
base::android::ScopedJavaGlobalRef<jobject> GetOrCreateJavaObject();
// The controller provides data for this view and owns it. // The controller provides data for this view and owns it.
ManualFillingController* controller_; ManualFillingController* controller_;
// The corresponding java object. // The corresponding java object. Use `GetOrCreateJavaObject()` to access.
base::android::ScopedJavaGlobalRef<jobject> java_object_; base::android::ScopedJavaGlobalRef<jobject> java_object_internal_;
DISALLOW_COPY_AND_ASSIGN(ManualFillingViewAndroid); DISALLOW_COPY_AND_ASSIGN(ManualFillingViewAndroid);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment