Files
cromite/build/patches/Enable-native-Android-autofill.patch
T
CarlandGitHub 73886eac62 Patches for v100 (#1930)
* Patches for v100

* Remove unused patches
2022-03-29 15:58:56 +02:00

853 lines
42 KiB
Diff

From: uazo <uazo@users.noreply.github.com>
Date: Sun, 24 Oct 2021 16:54:04 +0000
Subject: Enable native Android autofill
There are 2 different types of autofill: one managed via GCM and the
native Android one that uses the provider assigned by the user
(which can be any user installed app like Bitwarden for example).
In chromium GCM is active while in the WebView the latter.
This patch uses WebView code to enable native Android autofill
along with browser-managed autofill.
A separate toggle is introduced to enable autofill in incognito mode.
See also: https://github.com/bromite/bromite/issues/547
---
android_webview/browser/aw_contents.cc | 1 +
chrome/android/BUILD.gn | 1 +
.../settings/PasswordSettings.java | 81 ++++++++++++++++++-
.../chromium/chrome/browser/tab/TabImpl.java | 50 ++++++++++++
.../browser/tab/TabViewAndroidDelegate.java | 14 ++++
chrome/browser/BUILD.gn | 8 ++
chrome/browser/android/tab_android.cc | 27 +++++++
chrome/browser/android/tab_android.h | 2 +
.../tab_web_contents_delegate_android.cc | 3 +-
.../strings/android_chrome_strings.grd | 6 ++
chrome/browser/ui/tab_helpers.cc | 8 +-
.../browser/content_autofill_driver.cc | 50 ++++++++++--
.../content/browser/content_autofill_driver.h | 8 +-
.../content_autofill_driver_factory.cc | 9 ++-
.../browser/content_autofill_driver_factory.h | 4 +
.../renderer/password_autofill_agent.cc | 5 +-
.../autofill/core/common/autofill_prefs.cc | 8 ++
.../autofill/core/common/autofill_prefs.h | 2 +
.../embedder_support/view/ContentView.java | 46 +++++++++++
.../chromium/ui/base/ViewAndroidDelegate.java | 8 ++
weblayer/browser/tab_impl.cc | 3 +-
21 files changed, 329 insertions(+), 15 deletions(-)
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -336,6 +336,7 @@ void AwContents::InitAutofillIfNecessary(bool autocomplete_enabled) {
autofill::AutofillProvider::is_download_manager_disabled_for_testing()
? autofill::AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER
: autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
+ /*enable_browser_autofill_manager*/ false,
autofill_provider
? base::BindRepeating(&autofill::AndroidAutofillManager::Create)
: autofill::AutofillManager::AutofillManagerFactoryCallback());
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -450,6 +450,7 @@ android_library("chrome_java") {
"//chrome/browser/xsurface:java",
"//components/autofill/android:autofill_java",
"//components/autofill_assistant/browser:proto_java",
+ "//components/android_autofill/browser:java",
"//components/background_task_scheduler:background_task_scheduler_java",
"//components/background_task_scheduler:background_task_scheduler_task_ids_java",
"//components/bookmarks/common/android:bookmarks_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
@@ -54,13 +54,18 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
+import org.chromium.chrome.browser.ui.messages.snackbar.INeedSnackbarManager;
+import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
+import org.chromium.chrome.browser.ApplicationLifetime;
+
/**
* The "Passwords" screen in Settings, which allows the user to enable or disable password saving,
* to view saved passwords (just the username and URL), and to delete saved passwords.
*/
public class PasswordSettings extends PreferenceFragmentCompat
implements PasswordManagerHandler.PasswordListObserver,
- Preference.OnPreferenceClickListener {
+ Preference.OnPreferenceClickListener, INeedSnackbarManager {
@IntDef({TrustedVaultBannerState.NOT_SHOWN, TrustedVaultBannerState.OFFER_OPT_IN,
TrustedVaultBannerState.OPTED_IN})
@Retention(RetentionPolicy.SOURCE)
@@ -87,6 +92,12 @@ public class PasswordSettings extends PreferenceFragmentCompat
public static final String PREF_TRUSTED_VAULT_BANNER = "trusted_vault_banner";
public static final String PREF_KEY_MANAGE_ACCOUNT_LINK = "manage_account_link";
+ public static final String PREF_ANDROID_AUTOFILL_SWITCH = "android_autofill_switch";
+ public static final String PREF_ANDROID_AUTOFILL_INCOGNITO_SWITCH = "android_autofill_incognito_switch";
+
+ private SnackbarManager mSnackbarManager;
+ private Snackbar mSnackbar;
+
private static final String PREF_KEY_CATEGORY_SAVED_PASSWORDS = "saved_passwords";
private static final String PREF_KEY_CATEGORY_EXCEPTIONS = "exceptions";
private static final String PREF_KEY_SAVED_PASSWORDS_NO_TEXT = "saved_passwords_no_text";
@@ -116,6 +127,8 @@ public class PasswordSettings extends PreferenceFragmentCompat
private String mSearchQuery;
private Preference mLinkPref;
private ChromeSwitchPreference mSavePasswordsSwitch;
+ private ChromeSwitchPreference mEnableAndroidAutofillSwitch;
+ private ChromeSwitchPreference mEnableAndroidAutofillIncognitoSwitch;
private ChromeSwitchPreference mAutoSignInSwitch;
private ChromeBasePreference mCheckPasswords;
private ChromeBasePreference mTrustedVaultBanner;
@@ -287,6 +300,7 @@ public class PasswordSettings extends PreferenceFragmentCompat
}
createSavePasswordsSwitch();
+ createEnableAndroidAutofillSwitch();
createAutoSignInCheckbox();
if (mPasswordCheck != null) {
createCheckPasswords();
@@ -522,6 +536,71 @@ public class PasswordSettings extends PreferenceFragmentCompat
getPrefService().getBoolean(Pref.CREDENTIALS_ENABLE_SERVICE));
}
+ private void createEnableAndroidAutofillSwitch() {
+ if (mSnackbar == null) {
+ mSnackbar = Snackbar.make(getActivity().getString(R.string.ui_relaunch_notice),
+ new SnackbarManager.SnackbarController() {
+ @Override
+ public void onDismissNoAction(Object actionData) { }
+
+ @Override
+ public void onAction(Object actionData) {
+ ApplicationLifetime.terminate(true);
+ }
+ }, Snackbar.TYPE_NOTIFICATION, Snackbar.UMA_UNKNOWN)
+ .setSingleLine(false)
+ .setAction(getActivity().getString(R.string.relaunch),
+ /*actionData*/null)
+ .setDuration(/*durationMs*/70000);
+ }
+
+ mEnableAndroidAutofillSwitch = new ChromeSwitchPreference(getStyledContext(), null);
+ mEnableAndroidAutofillSwitch.setKey(PREF_ANDROID_AUTOFILL_SWITCH);
+ mEnableAndroidAutofillSwitch.setTitle(R.string.enable_android_autofill);
+ mEnableAndroidAutofillSwitch.setOrder(ORDER_SWITCH);
+ mEnableAndroidAutofillSwitch.setSummaryOn(R.string.text_on);
+ mEnableAndroidAutofillSwitch.setSummaryOff(R.string.text_off);
+
+ try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
+ getPreferenceScreen().addPreference(mEnableAndroidAutofillSwitch);
+ }
+
+ mEnableAndroidAutofillSwitch.setChecked(
+ getPrefService().getBoolean(Pref.AUTOFILL_ANDROID_ENABLED));
+
+ mEnableAndroidAutofillSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
+ getPrefService().setBoolean(Pref.AUTOFILL_ANDROID_ENABLED, (boolean) newValue);
+ if (!mSnackbarManager.isShowing())
+ mSnackbarManager.showSnackbar(mSnackbar);
+ return true;
+ });
+
+ mEnableAndroidAutofillIncognitoSwitch = new ChromeSwitchPreference(getStyledContext(), null);
+ mEnableAndroidAutofillIncognitoSwitch.setKey(PREF_ANDROID_AUTOFILL_INCOGNITO_SWITCH);
+ mEnableAndroidAutofillIncognitoSwitch.setTitle(R.string.enable_android_autofill_incognito);
+ mEnableAndroidAutofillIncognitoSwitch.setOrder(ORDER_SWITCH);
+ mEnableAndroidAutofillIncognitoSwitch.setSummaryOn(R.string.text_on);
+ mEnableAndroidAutofillIncognitoSwitch.setSummaryOff(R.string.text_off);
+
+ try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
+ getPreferenceScreen().addPreference(mEnableAndroidAutofillIncognitoSwitch);
+ }
+
+ mEnableAndroidAutofillIncognitoSwitch.setChecked(
+ getPrefService().getBoolean(Pref.AUTOFILL_ANDROID_INCOGNITO_ENABLED));
+
+ mEnableAndroidAutofillIncognitoSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
+ getPrefService().setBoolean(Pref.AUTOFILL_ANDROID_INCOGNITO_ENABLED, (boolean) newValue);
+ if (!mSnackbarManager.isShowing())
+ mSnackbarManager.showSnackbar(mSnackbar);
+ return true;
+ });
+ }
+
+ public void setSnackbarManager(SnackbarManager manager) {
+ mSnackbarManager = manager;
+ }
+
private void createAutoSignInCheckbox() {
mAutoSignInSwitch = new ChromeSwitchPreference(getStyledContext(), null);
mAutoSignInSwitch.setKey(PREF_AUTOSIGNIN_SWITCH);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -74,6 +74,17 @@ import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.util.ColorUtils;
import org.chromium.url.GURL;
+import android.os.Build;
+import android.util.SparseArray;
+import org.chromium.ui.base.EventOffsetHandler;
+import android.view.ViewStructure;
+import android.view.autofill.AutofillValue;
+import org.chromium.components.autofill.AutofillProvider;
+import org.chromium.components.autofill.AutofillActionModeCallback;
+import org.chromium.content_public.browser.SelectionPopupController;
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.components.user_prefs.UserPrefs;
+
/**
* Implementation of the interface {@link Tab}. Contains and manages a {@link ContentView}.
* This class is not intended to be extended.
@@ -211,6 +222,8 @@ public class TabImpl implements Tab, TabObscuringHandler.Observer {
private int mThemeColor;
private boolean mUsedCriticalPersistedTabData;
+ AutofillProvider mAutofillProvider;
+
/**
* Creates an instance of a {@link TabImpl}.
*
@@ -765,6 +778,11 @@ public class TabImpl implements Tab, TabObscuringHandler.Observer {
for (TabObserver observer : mObservers) observer.onDestroyed(this);
mObservers.clear();
+ if (mAutofillProvider != null) {
+ mAutofillProvider.destroy();
+ mAutofillProvider = null;
+ }
+
mUserDataHost.destroy();
mTabViewManager.destroy();
hideNativePage(false, null);
@@ -1342,6 +1360,16 @@ public class TabImpl implements Tab, TabObscuringHandler.Observer {
return tabsPtrArray;
}
+ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
+ if (mAutofillProvider != null)
+ mAutofillProvider.onProvideAutoFillVirtualStructure(structure, flags);
+ }
+
+ public void autofill(final SparseArray<AutofillValue> values) {
+ if (mAutofillProvider != null)
+ mAutofillProvider.autofill(values);
+ }
+
/**
* Initializes the {@link WebContents}. Completes the browser content components initialization
* around a native WebContents pointer.
@@ -1391,6 +1419,27 @@ public class TabImpl implements Tab, TabObscuringHandler.Observer {
mDelegateFactory.createContextMenuPopulatorFactory(this), this));
mWebContents.notifyRendererPreferenceUpdate();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ boolean autofillEnabled = false;
+ if (isIncognito()) {
+ autofillEnabled = UserPrefs.get(Profile.getLastUsedRegularProfile())
+ .getBoolean(Pref.AUTOFILL_ANDROID_INCOGNITO_ENABLED);
+ } else {
+ autofillEnabled = UserPrefs.get(Profile.getLastUsedRegularProfile())
+ .getBoolean(Pref.AUTOFILL_ANDROID_ENABLED);
+ }
+
+ if (autofillEnabled) {
+ SelectionPopupController selectionController =
+ SelectionPopupController.fromWebContents(mWebContents);
+ mAutofillProvider = new AutofillProvider(getContext(), cv, webContents, "bromite");
+ TabImplJni.get().initializeAutofillIfNecessary(mNativeTabAndroid);
+ mAutofillProvider.setWebContents(webContents);
+ cv.setWebContents(webContents);
+ selectionController.setNonSelectionActionModeCallback(
+ new AutofillActionModeCallback(mThemedApplicationContext, mAutofillProvider));
+ }
+ }
TabHelpers.initWebContentsHelpers(this);
notifyContentChanged();
} finally {
@@ -1775,5 +1824,6 @@ public class TabImpl implements Tab, TabObscuringHandler.Observer {
void setActiveNavigationEntryTitleForUrl(long nativeTabAndroid, String url, String title);
void loadOriginalImage(long nativeTabAndroid);
boolean handleNonNavigationAboutURL(GURL url);
+ void initializeAutofillIfNecessary(long nativeTabAndroid);
}
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
@@ -19,6 +19,10 @@ import org.chromium.ui.base.DropDataContentProvider;
import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.ui.base.WindowAndroid;
+import android.util.SparseArray;
+import android.view.autofill.AutofillValue;
+import android.view.ViewStructure;
+
/**
* Implementation of the abstract class {@link ViewAndroidDelegate} for Chrome.
*/
@@ -149,4 +153,14 @@ public class TabViewAndroidDelegate extends ViewAndroidDelegate {
getContentView().removeOnDragListener(getDragStateTrackerInternal());
}
}
+
+ @Override
+ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
+ mTab.onProvideAutofillVirtualStructure(structure, flags);
+ }
+
+ @Override
+ public void autofill(final SparseArray<AutofillValue> values) {
+ mTab.autofill(values);
+ }
}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2373,6 +2373,14 @@ static_library("browser") {
"//ui/webui/resources/cr_components/most_visited:mojom",
"//ui/webui/resources/js/browser_command:mojo_bindings",
]
+
+ if (is_android) {
+ deps += [
+ "//components/android_autofill/browser",
+ "//components/android_autofill/browser:android"
+ ]
+ }
+
if (is_chromeos_ash) {
sources += [
"apps/digital_goods/digital_goods_factory_impl.cc",
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc
--- a/chrome/browser/android/tab_android.cc
+++ b/chrome/browser/android/tab_android.cc
@@ -66,6 +66,13 @@
#include "url/android/gurl_android.h"
#include "url/gurl.h"
+#include "components/android_autofill/browser/android_autofill_manager.h"
+#include "components/android_autofill/browser/autofill_provider.h"
+#include "components/android_autofill/browser/autofill_provider_android.h"
+#include "components/autofill/content/browser/content_autofill_driver_factory.h"
+#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
+#include "chrome/browser/browser_process.h"
+
using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaParamRef;
@@ -444,3 +451,23 @@ static void JNI_TabImpl_Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
// This will automatically bind to the Java object and pass ownership there.
new TabAndroid(env, obj);
}
+
+void TabAndroid::InitializeAutofillIfNecessary(JNIEnv* env) {
+ if (!autofill::ContentAutofillDriverFactory::FromWebContents(
+ web_contents_.get())) {
+ content::WebContents* web_contents = web_contents_.get();
+ DCHECK(
+ !autofill::ContentAutofillDriverFactory::FromWebContents(web_contents));
+ DCHECK(autofill::AutofillProvider::FromWebContents(web_contents));
+
+ autofill::ChromeAutofillClient::CreateForWebContents(web_contents);
+
+ autofill::ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
+ web_contents,
+ autofill::ChromeAutofillClient::FromWebContents(web_contents),
+ g_browser_process->GetApplicationLocale(),
+ autofill::BrowserAutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER,
+ /*enable_browser_autofill_manager*/ true,
+ base::BindRepeating(&autofill::AndroidAutofillManager::Create));
+ }
+}
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h
--- a/chrome/browser/android/tab_android.h
+++ b/chrome/browser/android/tab_android.h
@@ -154,6 +154,8 @@ class TabAndroid : public base::SupportsUserData {
void SetDevToolsAgentHost(scoped_refptr<content::DevToolsAgentHost> host);
+ void InitializeAutofillIfNecessary(JNIEnv* env);
+
private:
JavaObjectWeakGlobalRef weak_java_tab_;
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -174,7 +174,8 @@ void TabWebContentsDelegateAndroid::PortalWebContentsCreated(
portal_contents,
autofill::ChromeAutofillClient::FromWebContents(portal_contents),
g_browser_process->GetApplicationLocale(),
- autofill::BrowserAutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ autofill::BrowserAutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
+ /*enable_browser_autofill_manager*/ true);
ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
portal_contents,
autofill::ChromeAutofillClient::FromWebContents(portal_contents));
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -639,6 +639,12 @@ CHAR_LIMIT guidelines:
<message name="IDS_PASSWORD_SETTINGS_SAVE_PASSWORDS" desc="Title for the checkbox toggling whether passwords are saved or not. [CHAR_LIMIT=32]">
Save passwords
</message>
+ <message name="IDS_ENABLE_ANDROID_AUTOFILL" desc="Title for the checkbox toggling whether enable Android native autofill or not. [CHAR_LIMIT=32]">
+ Enable native Android autofill
+ </message>
+ <message name="IDS_ENABLE_ANDROID_AUTOFILL_INCOGNITO" desc="Title for the checkbox toggling whether enable Android native autofill or not in incognito mode. [CHAR_LIMIT=32]">
+ Enable native Android autofill in incognito
+ </message>
<message name="IDS_PASSWORDS_AUTO_SIGNIN_TITLE" desc="Title for checkbox to enable automatically signing the user in to websites">
Auto Sign-in
</message>
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -153,6 +153,9 @@
#include "chrome/browser/ui/javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_android.h"
#include "chrome/browser/video_tutorials/video_tutorial_tab_helper.h"
#include "content/public/common/content_features.h"
+#include "components/android_autofill/browser/android_autofill_manager.h"
+#include "components/android_autofill/browser/autofill_provider.h"
+#include "components/android_autofill/browser/autofill_provider_android.h"
#else
#include "chrome/browser/accuracy_tips/accuracy_service_factory.h"
#include "chrome/browser/banners/app_banner_manager_desktop.h"
@@ -291,7 +294,10 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) {
web_contents,
autofill::ChromeAutofillClient::FromWebContents(web_contents),
g_browser_process->GetApplicationLocale(),
- autofill::BrowserAutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ autofill::BrowserAutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
+ /*enable_browser_autofill_manager*/ true,
+ base::BindRepeating(&autofill::AndroidAutofillManager::Create));
+
if (BreadcrumbsStatus::IsEnabled())
BreadcrumbManagerTabHelper::CreateForWebContents(web_contents);
chrome_browser_net::NetErrorTabHelper::CreateForWebContents(web_contents);
diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/components/autofill/content/browser/content_autofill_driver.cc
--- a/components/autofill/content/browser/content_autofill_driver.cc
+++ b/components/autofill/content/browser/content_autofill_driver.cc
@@ -68,6 +68,7 @@ ContentAutofillDriver::ContentAutofillDriver(
const std::string& app_locale,
ContentAutofillRouter* autofill_router,
AutofillManager::AutofillDownloadManagerState enable_download_manager,
+ bool enable_browser_autofill_manager,
AutofillManager::AutofillManagerFactoryCallback
autofill_manager_factory_callback)
: render_frame_host_(render_frame_host),
@@ -83,9 +84,11 @@ ContentAutofillDriver::ContentAutofillDriver(
GetAutofillAgent()->SetSecureContextRequired(true);
GetAutofillAgent()->SetFocusRequiresScroll(false);
GetAutofillAgent()->SetQueryPasswordSuggestion(true);
- } else {
+ }
+ if (!autofill_manager_factory_callback || enable_browser_autofill_manager) {
SetBrowserAutofillManager(std::make_unique<BrowserAutofillManager>(
- this, client, app_locale, enable_download_manager));
+ this, client, app_locale, enable_download_manager),
+ enable_browser_autofill_manager);
}
if (client && ShouldEnableHeavyFormDataScraping(client->GetChannel())) {
GetAutofillAgent()->EnableHeavyFormDataScraping();
@@ -344,6 +347,8 @@ void ContentAutofillDriver::FormsSeenImpl(
const std::vector<FormData>& updated_forms,
const std::vector<FormGlobalId>& removed_forms) {
autofill_manager_->OnFormsSeen(updated_forms, removed_forms);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnFormsSeen(updated_forms, removed_forms);
}
void ContentAutofillDriver::SetFormToBeProbablySubmittedImpl(
@@ -366,6 +371,8 @@ void ContentAutofillDriver::FormSubmittedImpl(const FormData& form,
}
autofill_manager_->OnFormSubmitted(form, known_success, source);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnFormSubmitted(form, known_success, source);
}
void ContentAutofillDriver::TextFieldDidChangeImpl(
@@ -374,6 +381,8 @@ void ContentAutofillDriver::TextFieldDidChangeImpl(
const gfx::RectF& bounding_box,
base::TimeTicks timestamp) {
autofill_manager_->OnTextFieldDidChange(form, field, bounding_box, timestamp);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnTextFieldDidChange(form, field, bounding_box, timestamp);
}
void ContentAutofillDriver::TextFieldDidScrollImpl(
@@ -381,6 +390,8 @@ void ContentAutofillDriver::TextFieldDidScrollImpl(
const FormFieldData& field,
const gfx::RectF& bounding_box) {
autofill_manager_->OnTextFieldDidScroll(form, field, bounding_box);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnTextFieldDidScroll(form, field, bounding_box);
}
void ContentAutofillDriver::SelectControlDidChangeImpl(
@@ -388,6 +399,8 @@ void ContentAutofillDriver::SelectControlDidChangeImpl(
const FormFieldData& field,
const gfx::RectF& bounding_box) {
autofill_manager_->OnSelectControlDidChange(form, field, bounding_box);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnSelectControlDidChange(form, field, bounding_box);
}
void ContentAutofillDriver::AskForValuesToFillImpl(
@@ -398,15 +411,22 @@ void ContentAutofillDriver::AskForValuesToFillImpl(
bool autoselect_first_suggestion) {
autofill_manager_->OnAskForValuesToFill(id, form, field, bounding_box,
autoselect_first_suggestion);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnAskForValuesToFill(id, form, field, bounding_box,
+ autoselect_first_suggestion);
}
void ContentAutofillDriver::HidePopupImpl() {
DCHECK(!IsPrerendering()) << "We should never affect UI while prerendering";
autofill_manager_->OnHidePopup();
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnHidePopup();
}
void ContentAutofillDriver::FocusNoLongerOnFormImpl(bool had_interacted_form) {
autofill_manager_->OnFocusNoLongerOnForm(had_interacted_form);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnFocusNoLongerOnForm(had_interacted_form);
}
void ContentAutofillDriver::FocusOnFormFieldImpl(
@@ -414,25 +434,35 @@ void ContentAutofillDriver::FocusOnFormFieldImpl(
const FormFieldData& field,
const gfx::RectF& bounding_box) {
autofill_manager_->OnFocusOnFormField(form, field, bounding_box);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnFocusOnFormField(form, field, bounding_box);
}
void ContentAutofillDriver::DidFillAutofillFormDataImpl(
const FormData& form,
base::TimeTicks timestamp) {
autofill_manager_->OnDidFillAutofillFormData(form, timestamp);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnDidFillAutofillFormData(form, timestamp);
}
void ContentAutofillDriver::DidPreviewAutofillFormDataImpl() {
autofill_manager_->OnDidPreviewAutofillFormData();
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnDidPreviewAutofillFormData();
}
void ContentAutofillDriver::DidEndTextFieldEditingImpl() {
autofill_manager_->OnDidEndTextFieldEditing();
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->OnDidEndTextFieldEditing();
}
void ContentAutofillDriver::SelectFieldOptionsDidChangeImpl(
const FormData& form) {
autofill_manager_->SelectFieldOptionsDidChange(form);
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->SelectFieldOptionsDidChange(form);
}
void ContentAutofillDriver::FillFormForAssistantImpl(
@@ -653,13 +683,21 @@ void ContentAutofillDriver::DidNavigateFrame(
if (autofill_router_) // Can be nullptr only in tests.
autofill_router_->UnregisterDriver(this);
autofill_manager_->Reset();
+ if (browser_autofill_manager_ptr_)
+ browser_autofill_manager_->Reset();
}
void ContentAutofillDriver::SetBrowserAutofillManager(
- std::unique_ptr<BrowserAutofillManager> manager) {
- autofill_manager_ = std::move(manager);
- browser_autofill_manager_ =
- static_cast<BrowserAutofillManager*>(autofill_manager_.get());
+ std::unique_ptr<BrowserAutofillManager> manager,
+ bool enable_browser_autofill_manager) {
+ if (enable_browser_autofill_manager) {
+ browser_autofill_manager_ptr_ = std::move(manager);
+ browser_autofill_manager_ = browser_autofill_manager_ptr_.get();
+ } else {
+ autofill_manager_ = std::move(manager);
+ browser_autofill_manager_ =
+ static_cast<BrowserAutofillManager*>(autofill_manager_.get());
+ }
}
ContentAutofillDriver::ContentAutofillDriver(content::RenderFrameHost* rfh)
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h
--- a/components/autofill/content/browser/content_autofill_driver.h
+++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -138,6 +138,7 @@ class ContentAutofillDriver : public AutofillDriver,
const std::string& app_locale,
ContentAutofillRouter* autofill_router,
AutofillManager::AutofillDownloadManagerState enable_download_manager,
+ bool enable_browser_autofill_manager,
AutofillManager::AutofillManagerFactoryCallback
autofill_manager_factory_callback);
ContentAutofillDriver(const ContentAutofillDriver&) = delete;
@@ -361,7 +362,8 @@ class ContentAutofillDriver : public AutofillDriver,
// Sets the manager to |manager|. Takes ownership of |manager|.
void SetBrowserAutofillManager(
- std::unique_ptr<BrowserAutofillManager> manager);
+ std::unique_ptr<BrowserAutofillManager> manager,
+ bool enable_browser_autofill_manager);
// Reports whether a document collects phone numbers, uses one time code, uses
// WebOTP. There are cases that the reporting is not expected:
@@ -426,6 +428,10 @@ class ContentAutofillDriver : public AutofillDriver,
// pointer to a common root.
raw_ptr<BrowserAutofillManager> browser_autofill_manager_;
+ // adds a reference for BrowserAutofillManager, since native autofill works in
+ // conjunction with browser autofill in Bromite
+ std::unique_ptr<BrowserAutofillManager> browser_autofill_manager_ptr_;
+
// Pointer to an implementation of InternalAuthenticator.
std::unique_ptr<webauthn::InternalAuthenticator> authenticator_impl_;
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.cc b/components/autofill/content/browser/content_autofill_driver_factory.cc
--- a/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -32,6 +32,7 @@ void ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
const std::string& app_locale,
BrowserAutofillManager::AutofillDownloadManagerState
enable_download_manager,
+ bool enable_browser_autofill_manager,
AutofillManager::AutofillManagerFactoryCallback
autofill_manager_factory_callback) {
if (FromWebContents(contents))
@@ -40,7 +41,7 @@ void ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
contents->SetUserData(
kContentAutofillDriverFactoryWebContentsUserDataKey,
base::WrapUnique(new ContentAutofillDriverFactory(
- contents, client, app_locale, enable_download_manager,
+ contents, client, app_locale, enable_download_manager, enable_browser_autofill_manager,
std::move(autofill_manager_factory_callback))));
}
@@ -78,6 +79,7 @@ ContentAutofillDriverFactory::ContentAutofillDriverFactory(
const std::string& app_locale,
BrowserAutofillManager::AutofillDownloadManagerState
enable_download_manager,
+ bool enable_browser_autofill_manager,
AutofillManager::AutofillManagerFactoryCallback
autofill_manager_factory_callback)
: content::WebContentsObserver(web_contents),
@@ -85,7 +87,8 @@ ContentAutofillDriverFactory::ContentAutofillDriverFactory(
app_locale_(app_locale),
enable_download_manager_(enable_download_manager),
autofill_manager_factory_callback_(
- std::move(autofill_manager_factory_callback)) {}
+ std::move(autofill_manager_factory_callback)),
+ enable_browser_autofill_manager_(enable_browser_autofill_manager) {}
ContentAutofillDriverFactory::~ContentAutofillDriverFactory() = default;
@@ -111,7 +114,7 @@ ContentAutofillDriver* ContentAutofillDriverFactory::DriverForFrame(
if (render_frame_host->IsRenderFrameCreated()) {
driver = std::make_unique<ContentAutofillDriver>(
render_frame_host, client(), app_locale_, &router_,
- enable_download_manager_, autofill_manager_factory_callback_);
+ enable_download_manager_, enable_browser_autofill_manager_, autofill_manager_factory_callback_);
DCHECK_EQ(driver_map_.find(render_frame_host)->second.get(),
driver.get());
} else {
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.h b/components/autofill/content/browser/content_autofill_driver_factory.h
--- a/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -45,6 +45,7 @@ class ContentAutofillDriverFactory : public content::WebContentsObserver,
const std::string& app_locale,
BrowserAutofillManager::AutofillDownloadManagerState
enable_download_manager,
+ bool enable_browser_autofill_manager,
AutofillManager::AutofillManagerFactoryCallback
autofill_manager_factory_callback = {});
@@ -84,6 +85,7 @@ class ContentAutofillDriverFactory : public content::WebContentsObserver,
const std::string& app_locale,
BrowserAutofillManager::AutofillDownloadManagerState
enable_download_manager,
+ bool enable_browser_autofill_manager,
AutofillManager::AutofillManagerFactoryCallback
autofill_manager_factory_callback);
@@ -97,6 +99,8 @@ class ContentAutofillDriverFactory : public content::WebContentsObserver,
// Must be destroyed after |driver_map_|'s elements.
ContentAutofillRouter router_;
+ bool enable_browser_autofill_manager_;
+
// The list of drivers, one for each frame in the WebContents.
// Should be empty at destruction time because its elements are erased in
// RenderFrameDeleted(). In case it is not empty, is must be destroyed before
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -724,7 +724,10 @@ void PasswordAutofillAgent::UpdateStateForTextChange(
void PasswordAutofillAgent::TrackAutofilledElement(
const blink::WebFormControlElement& element) {
- autofill_agent_->TrackAutofilledElement(element);
+ // fix for https://github.com/bromite/bromite/issues/1570
+ AutofillAgent* agent = autofill_agent_.get();
+ if (agent)
+ agent->TrackAutofilledElement(element);
}
bool PasswordAutofillAgent::FillSuggestion(
diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/autofill/core/common/autofill_prefs.cc
--- a/components/autofill/core/common/autofill_prefs.cc
+++ b/components/autofill/core/common/autofill_prefs.cc
@@ -128,6 +128,10 @@ const char kAutofillWalletImportStorageCheckboxState[] =
const char kAutocompleteLastVersionRetentionPolicy[] =
"autocomplete.retention_policy_last_version";
+// Boolean that is true to enable native Android Autofill
+const char kAutofillAndroidEnabled[] = "autofill.android_autofill_enabled";
+const char kAutofillAndroidIncognitoEnabled[] = "autofill.android_autofill_incognito_enabled";
+
void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
// Synced prefs. Used for cross-device choices, e.g., credit card Autofill.
registry->RegisterBooleanPref(
@@ -160,6 +164,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(
prefs::kAutofillCreditCardFidoAuthOfferCheckboxState, true);
#endif
+ registry->RegisterBooleanPref(
+ prefs::kAutofillAndroidEnabled, true);
+ registry->RegisterBooleanPref(
+ prefs::kAutofillAndroidIncognitoEnabled, false);
registry->RegisterIntegerPref(
prefs::kAutofillCreditCardSigninPromoImpressionCount, 0);
registry->RegisterBooleanPref(prefs::kAutofillWalletImportEnabled, true);
diff --git a/components/autofill/core/common/autofill_prefs.h b/components/autofill/core/common/autofill_prefs.h
--- a/components/autofill/core/common/autofill_prefs.h
+++ b/components/autofill/core/common/autofill_prefs.h
@@ -47,6 +47,8 @@ extern const char kAutofillUploadEventsLastResetTimestamp[];
extern const char kAutofillWalletImportEnabled[];
extern const char kAutofillWalletImportStorageCheckboxState[];
extern const char kAutocompleteLastVersionRetentionPolicy[];
+extern const char kAutofillAndroidEnabled[];
+extern const char kAutofillAndroidIncognitoEnabled[];
namespace sync_transport_opt_in {
enum Flags {
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
--- a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
+++ b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
@@ -37,6 +37,11 @@ import org.chromium.content_public.browser.WebContentsAccessibility;
import org.chromium.ui.base.EventForwarder;
import org.chromium.ui.base.EventOffsetHandler;
+import org.chromium.base.Log;
+import android.util.SparseArray;
+import android.view.autofill.AutofillValue;
+import org.chromium.ui.base.ViewAndroidDelegate;
+
/**
* The containing view for {@link WebContents} that exists in the Android UI hierarchy and exposes
* the various {@link View} functionality to it.
@@ -84,6 +89,8 @@ public class ContentView extends FrameLayout
*/
public static ContentView createContentView(Context context,
@Nullable EventOffsetHandler eventOffsetHandler, @Nullable WebContents webContents) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ return new ContentViewWithAutofill(context, eventOffsetHandler, webContents);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return new ContentViewApi23(context, eventOffsetHandler, webContents);
}
@@ -585,4 +592,43 @@ public class ContentView extends FrameLayout
if (wcax != null) wcax.onProvideVirtualStructure(structure, false);
}
}
+
+ /**
+ * API level 26 implementation that includes autofill.
+ */
+ public static class ContentViewWithAutofill extends ContentViewApi23 {
+ private ViewAndroidDelegate viewAndroidDelegate;
+
+ private ContentViewWithAutofill(Context context, EventOffsetHandler eventOffsetHandler, WebContents webContents) {
+ super(context, eventOffsetHandler, webContents);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ // The Autofill system-level infrastructure has heuristics for which Views it considers
+ // important for autofill; only these Views will be queried for their autofill
+ // structure on notifications that a new (virtual) View was entered. By default,
+ // FrameLayout is not considered important for autofill. Thus, for ContentView to be
+ // queried for its autofill structure, we must explicitly inform the autofill system
+ // that this View is important for autofill.
+ setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES);
+ }
+ }
+
+ @Override
+ public void setWebContents(WebContents webContents) {
+ viewAndroidDelegate = webContents.getViewAndroidDelegate();
+ super.setWebContents(webContents);
+ }
+
+ @Override
+ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
+ if (viewAndroidDelegate != null)
+ viewAndroidDelegate.onProvideAutofillVirtualStructure(structure, flags);
+ }
+
+ @Override
+ public void autofill(final SparseArray<AutofillValue> values) {
+ if (viewAndroidDelegate != null)
+ viewAndroidDelegate.autofill(values);
+ }
+ }
}
diff --git a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java b/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java
--- a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java
+++ b/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java
@@ -27,6 +27,10 @@ import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.compat.ApiHelperForN;
import org.chromium.ui.mojom.CursorType;
+import android.util.SparseArray;
+import android.view.autofill.AutofillValue;
+import android.view.ViewStructure;
+
/**
* Class to acquire, position, and remove anchor views from the implementing View.
*/
@@ -526,4 +530,8 @@ public class ViewAndroidDelegate {
public static void setDragAndDropDelegateForTest(DragAndDropDelegate testDelegate) {
sDragAndDropTestDelegate = testDelegate;
}
+
+ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {}
+
+ public void autofill(final SparseArray<AutofillValue> values) {}
}
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc
--- a/weblayer/browser/tab_impl.cc
+++ b/weblayer/browser/tab_impl.cc
@@ -1393,7 +1393,8 @@ void TabImpl::InitializeAutofillDriver() {
autofill::ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
web_contents, AutofillClientImpl::FromWebContents(web_contents),
i18n::GetApplicationLocale(), enable_autofill_download_manager,
- base::BindRepeating(&autofill::AndroidAutofillManager::Create));
+ base::BindRepeating(&autofill::AndroidAutofillManager::Create),
+ /*enable_browser_autofill_manager*/ false);
}
#endif // BUILDFLAG(IS_ANDROID)
--
2.25.1