[Android][Settings] Record usage of autofill options entry point
To check the usage (and in the future compare it with different places),
add a referrer parameter when launching the AutofillOptions screen.
The main entry point is the settings surface and the bucket count
will serve as a regression metric for different locations.
Other planned entry points are:
- deep links (i.e. a link from another App to this setting)
- links from messages (to fix inconsistency device & browser setting)
- potentially entry points from fallback surfaces
The deep link bucket is added but not recorded to satisfy the
argument checks in recording which would crash otherwise.
Bug: 1472225
Change-Id: I442cdff462d102628dd848b623a98a957a8c51fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4798450
Reviewed-by: Timofey Chudakov <tchudakov@google.com>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Commit-Queue: Friedrich Horschig <fhorschig@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1187268}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
index 80af899..ce1b8f6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
@@ -20,6 +20,8 @@
import org.chromium.base.ContextUtils;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.chrome.R;
+import org.chromium.chrome.browser.autofill.options.AutofillOptionsFragment;
+import org.chromium.chrome.browser.autofill.options.AutofillOptionsFragment.AutofillOptionsReferrer;
import org.chromium.chrome.browser.autofill.settings.SettingsLauncherHelper;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.homepage.HomepageManager;
@@ -236,14 +238,6 @@
removePreferenceIfPresent(PREF_SIGN_IN);
}
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
- && ChromeFeatureList.isEnabled(
- ChromeFeatureList.AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID)) {
- addPreferenceIfAbsent(PREF_AUTOFILL_OPTIONS);
- } else {
- removePreferenceIfPresent(PREF_AUTOFILL_OPTIONS);
- }
-
updateManageSyncPreference();
updateSearchEnginePreference();
updateAutofillPreferences();
@@ -326,6 +320,22 @@
}
private void updateAutofillPreferences() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ && ChromeFeatureList.isEnabled(
+ ChromeFeatureList.AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID)) {
+ addPreferenceIfAbsent(PREF_AUTOFILL_OPTIONS);
+ Preference preference = findPreference(PREF_AUTOFILL_OPTIONS);
+ preference.setFragment(null);
+ preference.setOnPreferenceClickListener(unused -> {
+ new SettingsLauncherImpl().launchSettingsActivity(getContext(),
+ AutofillOptionsFragment.class,
+ AutofillOptionsFragment.createRequiredArgs(
+ AutofillOptionsReferrer.SETTINGS));
+ return true; // Means event is consumed.
+ });
+ } else {
+ removePreferenceIfPresent(PREF_AUTOFILL_OPTIONS);
+ }
findPreference(PREF_AUTOFILL_PAYMENTS)
.setOnPreferenceClickListener(preference
-> SettingsLauncherHelper.showAutofillCreditCardSettings(getActivity()));
diff --git a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsCoordinator.java b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsCoordinator.java
index fd4c2b5..426c8ea 100644
--- a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsCoordinator.java
+++ b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsCoordinator.java
@@ -84,7 +84,7 @@
.getBoolean(Pref.AUTOFILL_USING_VIRTUAL_VIEW_STRUCTURE))
.with(ON_THIRD_PARTY_TOGGLE_CHANGED, mMediator::onThirdPartyToggleChanged)
.build();
- mMediator.initialize(model);
+ mMediator.initialize(model, mFragment.getReferrer());
PropertyModelChangeProcessor.create(model, mFragment, AutofillOptionsViewBinder::bind);
return model;
diff --git a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsFragment.java b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsFragment.java
index 2bc33c44..74061a53 100644
--- a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsFragment.java
+++ b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsFragment.java
@@ -9,6 +9,7 @@
import android.view.MenuInflater;
import android.view.MenuItem;
+import androidx.annotation.IntDef;
import androidx.preference.PreferenceFragmentCompat;
import org.chromium.chrome.browser.autofill.R;
@@ -17,15 +18,43 @@
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.settings.ProfileDependentSetting;
import org.chromium.components.browser_ui.settings.SettingsUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* Autofill options fragment, which allows the user to configure autofill.
*/
public class AutofillOptionsFragment extends PreferenceFragmentCompat
implements FragmentHelpAndFeedbackLauncher, ProfileDependentSetting {
+ // Key for the argument with which the AutofillOptions fragment will be launched. The value for
+ // this argument is part of the AutofillOptionsReferrer enum containing all entry points.
+ public static final String AUTOFILL_OPTIONS_REFERRER = "autofill-options-referrer";
public static final String PREF_AUTOFILL_THIRD_PARTY_FILLING = "autofill_third_party_filling";
private Profile mProfile;
private HelpAndFeedbackLauncher mHelpAndFeedbackLauncher;
+ private @AutofillOptionsReferrer int mReferrer;
+
+ // Represents different referrers when navigating to the Autofill Options page.
+ //
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ //
+ // Needs to stay in sync with AutofillOptionsReferrer in enums.xml.
+ @IntDef({AutofillOptionsReferrer.SETTINGS, AutofillOptionsReferrer.DEEP_LINK_TO_SETTINGS,
+ AutofillOptionsReferrer.COUNT})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AutofillOptionsReferrer {
+ /**
+ * Corresponds to the Settings page.
+ */
+ int SETTINGS = 0;
+ /**
+ * Corresponds to an external link opening Chrome.
+ */
+ int DEEP_LINK_TO_SETTINGS = 1;
+ int COUNT = 2;
+ }
/**
* This default constructor is required to instantiate the fragment.
@@ -47,6 +76,12 @@
}
@Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mReferrer = getReferrerFromInstanceStateOrLaunchBundle(savedInstanceState);
+ }
+
+ @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
MenuItem help =
@@ -83,4 +118,33 @@
public void setProfile(Profile profile) {
mProfile = profile;
}
+
+ public static Bundle createRequiredArgs(@AutofillOptionsReferrer int referrer) {
+ Bundle requiredArgs = new Bundle();
+ requiredArgs.putInt(AUTOFILL_OPTIONS_REFERRER, referrer);
+ return requiredArgs;
+ }
+
+ @AutofillOptionsReferrer
+ int getReferrer() {
+ return mReferrer;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(AUTOFILL_OPTIONS_REFERRER, mReferrer);
+ }
+
+ private @AutofillOptionsReferrer int getReferrerFromInstanceStateOrLaunchBundle(
+ Bundle savedInstanceState) {
+ if (savedInstanceState != null
+ && savedInstanceState.containsKey(AUTOFILL_OPTIONS_REFERRER)) {
+ return savedInstanceState.getInt(AUTOFILL_OPTIONS_REFERRER);
+ }
+ Bundle extras = getArguments();
+ assert extras.containsKey(AUTOFILL_OPTIONS_REFERRER)
+ : "AutofillOptionsFragment must be launched with a autofill-options-referrer fragment!";
+ return extras.getInt(AUTOFILL_OPTIONS_REFERRER);
+ }
}
diff --git a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsMediator.java b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsMediator.java
index debd190..0231011 100644
--- a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsMediator.java
+++ b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsMediator.java
@@ -9,6 +9,7 @@
import androidx.annotation.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.autofill.options.AutofillOptionsFragment.AutofillOptionsReferrer;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.prefs.PrefService;
@@ -23,6 +24,8 @@
@VisibleForTesting
static final String HISTOGRAM_USE_THIRD_PARTY_FILLING =
"Autofill.Settings.ToggleUseThirdPartyFilling";
+ @VisibleForTesting
+ static final String HISTOGRAM_REFERRER = "Autofill.Settings.AutofillOptionsReferrerAndroid";
private final Profile mProfile;
private PropertyModel mModel;
@@ -30,8 +33,10 @@
mProfile = profile;
}
- void initialize(PropertyModel model) {
+ void initialize(PropertyModel model, @AutofillOptionsReferrer int referrer) {
mModel = model;
+ RecordHistogram.recordEnumeratedHistogram(
+ HISTOGRAM_REFERRER, referrer, AutofillOptionsReferrer.COUNT);
}
boolean isInitialized() {
diff --git a/chrome/browser/autofill/android/junit/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsTest.java b/chrome/browser/autofill/android/junit/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsTest.java
index ddc4abd8..8659916 100644
--- a/chrome/browser/autofill/android/junit/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsTest.java
+++ b/chrome/browser/autofill/android/junit/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsTest.java
@@ -15,7 +15,6 @@
import static org.chromium.chrome.browser.autofill.options.AutofillOptionsProperties.ON_THIRD_PARTY_TOGGLE_CHANGED;
import static org.chromium.chrome.browser.autofill.options.AutofillOptionsProperties.THIRD_PARTY_AUTOFILL_ENABLED;
-import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -40,6 +39,7 @@
import org.chromium.base.test.util.HistogramWatcher;
import org.chromium.base.test.util.JniMocker;
import org.chromium.chrome.R;
+import org.chromium.chrome.browser.autofill.options.AutofillOptionsFragment.AutofillOptionsReferrer;
import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncher;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.preferences.Pref;
@@ -86,8 +86,9 @@
mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mMockUserPrefsJni);
doReturn(mPrefs).when(mMockUserPrefsJni).get(mProfile);
- mScenario = FragmentScenario.launchInContainer(
- AutofillOptionsFragment.class, Bundle.EMPTY, R.style.Theme_MaterialComponents);
+ mScenario = FragmentScenario.launchInContainer(AutofillOptionsFragment.class,
+ AutofillOptionsFragment.createRequiredArgs(AutofillOptionsReferrer.SETTINGS),
+ R.style.Theme_MaterialComponents);
mScenario.onFragment(fragment -> {
mFragment = (AutofillOptionsFragment) fragment; // Valid until scenario is recreated.
mFragment.setProfile(mProfile);
@@ -217,6 +218,18 @@
.show(mFragment.getActivity(), getString(R.string.help_context_autofill), null);
}
+ @Test
+ @SmallTest
+ public void passedReferrerRecordedInHistogram() {
+ HistogramWatcher histogramWatcher = HistogramWatcher.newSingleRecordWatcher(
+ AutofillOptionsMediator.HISTOGRAM_REFERRER, AutofillOptionsReferrer.SETTINGS);
+
+ // Component initialization triggers the recording.
+ AutofillOptionsCoordinator.createFor(mFragment);
+
+ histogramWatcher.assertExpected();
+ }
+
private String getString(@StringRes int stringId) {
return mFragment.getResources().getString(stringId);
}
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 5a8073d..18669cd 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -7615,6 +7615,11 @@
<int value="2" label="User did not interact with the infobar"/>
</enum>
+<enum name="AutofillOptionsReferrer">
+ <int value="0" label="User entered the autofill options via main settings."/>
+ <int value="1" label="User entered the autofill options via deep link."/>
+</enum>
+
<enum name="AutofillOtpAuthEvent">
<int value="0" label="Unknown result"/>
<int value="1" label="OTP auth succeeded"/>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index 96817138..646afe3 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -4209,6 +4209,16 @@
</summary>
</histogram>
+<histogram name="Autofill.Settings.AutofillOptionsReferrerAndroid"
+ enum="AutofillOptionsReferrer" expires_after="2024-01-30">
+ <owner>fhorschig@chromium.org</owner>
+ <owner>chrome-autofill-alerts@google.com</owner>
+ <summary>
+ Records which entry point opened the Autofill Options screen. Recorded on
+ Android.
+ </summary>
+</histogram>
+
<histogram name="Autofill.Settings.ToggleUseThirdPartyFilling" enum="Boolean"
expires_after="2024-01-30">
<owner>fhorschig@chromium.org</owner>