Commit 96b7e77a authored by Vasilii Sukhanov's avatar Vasilii Sukhanov Committed by Commit Bot

Add "Manage passwords" to the passwords drop-down.

- "Use password for:" title isn't used anymore in the password dropdown.
- The dropdown should have a footer "Manage passwords" leading to the settings.

Bug: 851021
Change-Id: I24696fffa7c2db7bc21c6b9ec7fcb3aa9c277429
Reviewed-on: https://chromium-review.googlesource.com/1125061
Commit-Queue: Vasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarBret Sepulveda <bsep@chromium.org>
Reviewed-by: default avatarVaclav Brozek <vabr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#572533}
parent de8f7d88
......@@ -3374,12 +3374,6 @@ const FeatureEntry kFeatureEntries[] = {
FEATURE_VALUE_TYPE(chrome::android::kPwaPersistentNotification)},
#endif // OS_ANDROID
{"enable-manual-fallbacks-filling",
flag_descriptions::kEnableManualFallbacksFillingName,
flag_descriptions::kEnableManualFallbacksFillingDescription,
kOsDesktop | kOsAndroid,
FEATURE_VALUE_TYPE(password_manager::features::kManualFallbacksFilling)},
#if !defined(OS_ANDROID)
{"voice-search-on-local-ntp", flag_descriptions::kVoiceSearchOnLocalNtpName,
flag_descriptions::kVoiceSearchOnLocalNtpDescription, kOsDesktop,
......
......@@ -542,13 +542,6 @@ const char kEnableMacMaterialDesignDownloadShelfName[] =
const char kEnableMacMaterialDesignDownloadShelfDescription[] =
"If enabled, the download shelf uses Material Design.";
const char kEnableManualFallbacksFillingName[] =
"Manual fallbacks for password manager forms filling";
const char kEnableManualFallbacksFillingDescription[] =
"If enabled, then if user clicks on the password field on a form, popup "
"might contain generation fallbacks or 'Show all saved passwords' "
"fallback.";
const char kEnablePolicyToolName[] = "Enable policy management page";
const char kEnablePolicyToolDescription[] =
"If enabled, the chrome://policy-tool URL loads a page for managing "
......
......@@ -359,9 +359,6 @@ extern const char kEnableLazyFrameLoadingDescription[];
extern const char kEnableMacMaterialDesignDownloadShelfName[];
extern const char kEnableMacMaterialDesignDownloadShelfDescription[];
extern const char kEnableManualFallbacksFillingName[];
extern const char kEnableManualFallbacksFillingDescription[];
extern const char kEnableMaterialDesignBookmarksName[];
extern const char kEnableMaterialDesignBookmarksDescription[];
......@@ -647,9 +644,6 @@ extern const char kLoadMediaRouterComponentExtensionDescription[];
extern const char kMacViewsAutofillPopupName[];
extern const char kMacViewsAutofillPopupDescription[];
extern const char kManualPasswordGenerationName[];
extern const char kManualPasswordGenerationDescription[];
extern const char kMarkHttpAsName[];
extern const char kMarkHttpAsDescription[];
extern const char kMarkHttpAsDangerous[];
......
......@@ -490,7 +490,8 @@ void AutofillPopupViewNativeViews::CreateChildViews() {
item_id == autofill::PopupItemId::POPUP_ITEM_ID_AUTOFILL_OPTIONS ||
item_id == autofill::PopupItemId::POPUP_ITEM_ID_SCAN_CREDIT_CARD ||
item_id ==
autofill::PopupItemId::POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO) {
autofill::PopupItemId::POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO ||
item_id == POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY) {
// This is a footer, so this suggestion will be processed later. Don't
// increment |line_number|, or else it will be skipped when adding footer
// rows below.
......
......@@ -153,10 +153,6 @@
Scan new card
</message>
<message name="IDS_AUTOFILL_PASSWORD_FIELD_SUGGESTIONS_TITLE" desc="Text shown as the title of the suggestion drop down when a password field is clicked.">
Use password for:
</message>
<if expr="not use_titlecase">
<message name="IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK" desc="The text shown as an option in the suggestion drop down when a password field is clicked">
Show all saved passwords
......
......@@ -141,20 +141,6 @@ bool ShouldShowManualFallbackForPreLollipop(syncer::SyncService* sync_service) {
#endif
}
void AddSimpleSuggestionWithSeparatorOnTop(
int value,
int frontend_id,
std::vector<autofill::Suggestion>* suggestions) {
#if !defined(OS_ANDROID)
suggestions->push_back(autofill::Suggestion());
suggestions->back().frontend_id = autofill::POPUP_ITEM_ID_SEPARATOR;
#endif
autofill::Suggestion suggestion(l10n_util::GetStringUTF8(value),
std::string(), std::string(), frontend_id);
suggestions->push_back(suggestion);
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
......@@ -241,24 +227,17 @@ void PasswordAutofillManager::OnShowPasswordSuggestions(
return;
}
if (options & autofill::IS_PASSWORD_FIELD) {
autofill::Suggestion password_field_suggestions(l10n_util::GetStringUTF16(
IDS_AUTOFILL_PASSWORD_FIELD_SUGGESTIONS_TITLE));
password_field_suggestions.frontend_id = autofill::POPUP_ITEM_ID_TITLE;
suggestions.insert(suggestions.begin(), password_field_suggestions);
}
GURL origin = (fill_data_it->second).origin;
GURL origin = fill_data_it->second.origin;
if (ShouldShowManualFallbackForPreLollipop(
autofill_client_->GetSyncService())) {
if (base::FeatureList::IsEnabled(
password_manager::features::kManualFallbacksFilling) &&
(options & autofill::IS_PASSWORD_FIELD) && password_client_ &&
if (password_client_ &&
password_client_->IsFillingFallbackEnabledForCurrentPage()) {
AddSimpleSuggestionWithSeparatorOnTop(
IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK,
autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY, &suggestions);
autofill::Suggestion suggestion(
l10n_util::GetStringUTF8(IDS_PASSWORD_MANAGER_MANAGE_PASSWORDS),
std::string(), std::string(),
autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY);
suggestions.push_back(suggestion);
show_all_saved_passwords_shown_context_ =
metrics_util::SHOW_ALL_SAVED_PASSWORDS_CONTEXT_PASSWORD;
......
......@@ -130,6 +130,15 @@ bool IsPreLollipopAndroid() {
#endif
}
std::vector<base::string16> GetSuggestionList(
std::vector<base::string16> credentials) {
if (!IsPreLollipopAndroid()) {
credentials.push_back(
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_MANAGE_PASSWORDS));
}
return credentials;
}
} // namespace
class PasswordAutofillManagerTest : public testing::Test {
......@@ -165,16 +174,6 @@ class PasswordAutofillManagerTest : public testing::Test {
int fill_data_id() { return fill_data_id_; }
autofill::PasswordFormFillData& fill_data() { return fill_data_; }
void SetManualFallbacksForFilling(bool enabled) {
if (enabled) {
scoped_feature_list_.InitAndEnableFeature(
password_manager::features::kManualFallbacksFilling);
} else {
scoped_feature_list_.InitAndDisableFeature(
password_manager::features::kManualFallbacksFilling);
}
}
void SetManualFallbacksForFillingStandalone(bool enabled) {
if (enabled) {
scoped_feature_list_.InitAndEnableFeature(
......@@ -185,12 +184,6 @@ class PasswordAutofillManagerTest : public testing::Test {
}
}
static bool IsManualFallbackForFillingEnabled() {
return base::FeatureList::IsEnabled(
password_manager::features::kManualFallbacksFilling) &&
!IsPreLollipopAndroid();
}
std::unique_ptr<PasswordAutofillManager> password_autofill_manager_;
base::string16 test_username_;
......@@ -260,6 +253,8 @@ TEST_F(PasswordAutofillManagerTest, PreviewSuggestion) {
// suggestions.
TEST_F(PasswordAutofillManagerTest, ExternalDelegatePasswordSuggestions) {
for (bool is_suggestion_on_password_field : {false, true}) {
SCOPED_TRACE(testing::Message() << "is_suggestion_on_password_field = "
<< is_suggestion_on_password_field);
std::unique_ptr<TestPasswordManagerClient> client(
new TestPasswordManagerClient);
std::unique_ptr<MockAutofillClient> autofill_client(new MockAutofillClient);
......@@ -277,16 +272,11 @@ TEST_F(PasswordAutofillManagerTest, ExternalDelegatePasswordSuggestions) {
FillSuggestion(test_username_, test_password_));
std::vector<autofill::PopupItemId> ids = {
autofill::POPUP_ITEM_ID_USERNAME_ENTRY};
if (is_suggestion_on_password_field) {
ids = {autofill::POPUP_ITEM_ID_TITLE,
autofill::POPUP_ITEM_ID_PASSWORD_ENTRY};
if (IsManualFallbackForFillingEnabled()) {
#if !defined(OS_ANDROID)
ids.push_back(autofill::POPUP_ITEM_ID_SEPARATOR);
#endif
ids.push_back(autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY);
}
is_suggestion_on_password_field
? autofill::POPUP_ITEM_ID_PASSWORD_ENTRY
: autofill::POPUP_ITEM_ID_USERNAME_ENTRY};
if (!IsPreLollipopAndroid()) {
ids.push_back(autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY);
}
EXPECT_CALL(
*autofill_client,
......@@ -334,41 +324,43 @@ TEST_F(PasswordAutofillManagerTest, ExtractSuggestions) {
// First, simulate displaying suggestions matching an empty prefix. Also
// verify that both the values and labels are filled correctly. The 'value'
// should be the user name; the 'label' should be the realm.
EXPECT_CALL(*autofill_client,
ShowAutofillPopup(
element_bounds, _,
testing::AllOf(
SuggestionVectorValuesAre(testing::UnorderedElementsAre(
test_username_, additional_username)),
SuggestionVectorLabelsAre(testing::UnorderedElementsAre(
base::UTF8ToUTF16(data.preferred_realm),
base::UTF8ToUTF16(additional.realm)))),
_));
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(
element_bounds, _,
testing::AllOf(
SuggestionVectorValuesAre(testing::UnorderedElementsAreArray(
GetSuggestionList({test_username_, additional_username}))),
SuggestionVectorLabelsAre(testing::AllOf(
testing::Contains(base::UTF8ToUTF16(data.preferred_realm)),
testing::Contains(base::UTF8ToUTF16(additional.realm))))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, base::string16(), false,
dummy_key, base::i18n::RIGHT_TO_LEFT, base::string16(), 0,
element_bounds);
// Now simulate displaying suggestions matching "John".
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(
testing::UnorderedElementsAre(additional_username)),
SuggestionVectorValuesAre(testing::ElementsAreArray(
GetSuggestionList({additional_username}))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("John"), false,
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("John"), 0,
element_bounds);
// Finally, simulate displaying all suggestions, without any prefix matching.
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(testing::UnorderedElementsAre(
test_username_, additional_username)),
_));
ShowAutofillPopup(
element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAreArray(
GetSuggestionList({test_username_, additional_username}))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("xyz"), true,
element_bounds);
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("xyz"),
autofill::SHOW_ALL, element_bounds);
}
// Verify that, for Android application credentials, the prettified realms of
......@@ -393,15 +385,15 @@ TEST_F(PasswordAutofillManagerTest, PrettifiedAndroidRealmsAreShownAsLabels) {
password_autofill_manager_->OnAddPasswordFormMapping(dummy_key, data);
EXPECT_CALL(*autofill_client,
ShowAutofillPopup(
_, _,
SuggestionVectorLabelsAre(testing::UnorderedElementsAre(
base::ASCIIToUTF16("android://com.example1.android/"),
base::ASCIIToUTF16("android://com.example2.android/"))),
_));
ShowAutofillPopup(_, _,
SuggestionVectorLabelsAre(testing::AllOf(
testing::Contains(base::ASCIIToUTF16(
"android://com.example1.android/")),
testing::Contains(base::ASCIIToUTF16(
"android://com.example2.android/")))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, base::string16(), false,
gfx::RectF());
dummy_key, base::i18n::RIGHT_TO_LEFT, base::string16(), 0, gfx::RectF());
}
TEST_F(PasswordAutofillManagerTest, FillSuggestionPasswordField) {
......@@ -427,27 +419,12 @@ TEST_F(PasswordAutofillManagerTest, FillSuggestionPasswordField) {
int dummy_key = 0;
password_autofill_manager_->OnAddPasswordFormMapping(dummy_key, data);
// Simulate displaying suggestions matching a username and specifying that the
// field is a password field.
base::string16 title = l10n_util::GetStringUTF16(
IDS_AUTOFILL_PASSWORD_FIELD_SUGGESTIONS_TITLE);
std::vector<base::string16> elements = {title, test_username_};
if (IsManualFallbackForFillingEnabled()) {
elements = {
title,
test_username_,
#if !defined(OS_ANDROID)
base::string16(),
#endif
l10n_util::GetStringUTF16(IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK)
};
}
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(
element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAreArray(elements)), _));
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAreArray(
GetSuggestionList({test_username_}))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, test_username_,
autofill::IS_PASSWORD_FIELD, element_bounds);
......@@ -483,14 +460,14 @@ TEST_F(PasswordAutofillManagerTest, DisplaySuggestionsWithMatchingTokens) {
int dummy_key = 0;
password_autofill_manager_->OnAddPasswordFormMapping(dummy_key, data);
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(testing::UnorderedElementsAre(
username, additional_username)),
_));
EXPECT_CALL(*autofill_client,
ShowAutofillPopup(
element_bounds, _,
SuggestionVectorValuesAre(testing::UnorderedElementsAreArray(
GetSuggestionList({username, additional_username}))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("foo"), false,
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("foo"), 0,
element_bounds);
}
......@@ -527,7 +504,7 @@ TEST_F(PasswordAutofillManagerTest, NoSuggestionForNonPrefixTokenMatch) {
EXPECT_CALL(*autofill_client, ShowAutofillPopup(_, _, _, _)).Times(0);
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("oo"), false,
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("oo"), 0,
element_bounds);
}
......@@ -566,12 +543,12 @@ TEST_F(PasswordAutofillManagerTest,
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(
testing::UnorderedElementsAre(additional_username)),
SuggestionVectorValuesAre(testing::ElementsAreArray(
GetSuggestionList({additional_username}))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("foo@exam"),
false, element_bounds);
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("foo@exam"), 0,
element_bounds);
}
// Verify that typing "example" into the username field will match and order
......@@ -606,12 +583,12 @@ TEST_F(PasswordAutofillManagerTest,
int dummy_key = 0;
password_autofill_manager_->OnAddPasswordFormMapping(dummy_key, data);
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(testing::UnorderedElementsAre(
username, additional_username)),
_));
EXPECT_CALL(*autofill_client,
ShowAutofillPopup(
element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAreArray(
GetSuggestionList({username, additional_username}))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, base::ASCIIToUTF16("foo"), false,
element_bounds);
......@@ -651,45 +628,8 @@ TEST_F(PasswordAutofillManagerTest, PreviewAndFillEmptyUsernameSuggestion) {
testing::Mock::VerifyAndClearExpectations(client->mock_driver());
}
// Tests that the "Show all passwords" suggestion isn't shown along with
// "Use password for" in the popup when the feature which controls its
// appearance is disabled.
TEST_F(PasswordAutofillManagerTest,
NotShowAllPasswordsOptionOnPasswordFieldWhenFeatureDisabled) {
auto client = std::make_unique<TestPasswordManagerClient>();
auto autofill_client = std::make_unique<MockAutofillClient>();
InitializePasswordAutofillManager(client.get(), autofill_client.get());
gfx::RectF element_bounds;
autofill::PasswordFormFillData data;
data.username_field.value = test_username_;
data.password_field.value = test_password_;
data.origin = GURL("https://foo.test");
int dummy_key = 0;
password_autofill_manager_->OnAddPasswordFormMapping(dummy_key, data);
// String "Use password for:" shown when displaying suggestions matching a
// username and specifying that the field is a password field.
base::string16 title =
l10n_util::GetStringUTF16(IDS_AUTOFILL_PASSWORD_FIELD_SUGGESTIONS_TITLE);
SetManualFallbacksForFilling(false);
// No "Show all passwords row" when feature is disabled.
EXPECT_CALL(*autofill_client,
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAre(
title, test_username_)),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, test_username_,
autofill::IS_PASSWORD_FIELD, element_bounds);
}
// Tests that the "Show all passwords" suggestion is shown along with
// "Use password for" in the popup when the feature which controls its
// appearance is enabled.
// Tests that the "Manage passwords" suggestion is shown along with the password
// popup.
TEST_F(PasswordAutofillManagerTest, ShowAllPasswordsOptionOnPasswordField) {
const char kShownContextHistogram[] =
"PasswordManager.ShowAllSavedPasswordsShownContext";
......@@ -716,30 +656,12 @@ TEST_F(PasswordAutofillManagerTest, ShowAllPasswordsOptionOnPasswordField) {
int dummy_key = 0;
password_autofill_manager_->OnAddPasswordFormMapping(dummy_key, data);
// String "Use password for:" shown when displaying suggestions matching a
// username and specifying that the field is a password field.
base::string16 title =
l10n_util::GetStringUTF16(IDS_AUTOFILL_PASSWORD_FIELD_SUGGESTIONS_TITLE);
SetManualFallbacksForFilling(true);
std::vector<base::string16> elements = {title, test_username_};
if (!IsPreLollipopAndroid()) {
elements = {
title,
test_username_,
#if !defined(OS_ANDROID)
base::string16(),
#endif
l10n_util::GetStringUTF16(IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK)
};
}
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(
element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAreArray(elements)), _));
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAreArray(
GetSuggestionList({test_username_}))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, test_username_,
......@@ -880,10 +802,9 @@ TEST_F(PasswordAutofillManagerTest, ShowStandaloneShowAllPasswords) {
}
}
// Tests that the "Show all passwords" fallback doesn't shows up in non-password
// Tests that the "Manage passwords" fallback shows up in non-password
// fields of login forms.
TEST_F(PasswordAutofillManagerTest,
NotShowAllPasswordsOptionOnNonPasswordField) {
TEST_F(PasswordAutofillManagerTest, ShowAllPasswordsOptionOnNonPasswordField) {
auto client = std::make_unique<TestPasswordManagerClient>();
auto autofill_client = std::make_unique<MockAutofillClient>();
InitializePasswordAutofillManager(client.get(), autofill_client.get());
......@@ -897,13 +818,12 @@ TEST_F(PasswordAutofillManagerTest,
int dummy_key = 0;
password_autofill_manager_->OnAddPasswordFormMapping(dummy_key, data);
SetManualFallbacksForFilling(true);
EXPECT_CALL(
*autofill_client,
ShowAutofillPopup(
element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAre(test_username_)), _));
ShowAutofillPopup(element_bounds, _,
SuggestionVectorValuesAre(testing::ElementsAreArray(
GetSuggestionList({test_username_}))),
_));
password_autofill_manager_->OnShowPasswordSuggestions(
dummy_key, base::i18n::RIGHT_TO_LEFT, test_username_, 0, element_bounds);
}
......
......@@ -23,11 +23,6 @@ const base::Feature kAutofillHome = {"AutofillHome",
const base::Feature kHtmlBasedUsernameDetector = {
"HtmlBaseUsernameDetector", base::FEATURE_ENABLED_BY_DEFAULT};
// Enable additional elements in the form popup UI, which will allow the user to
// view all saved passwords.
const base::Feature kManualFallbacksFilling = {
"ManualFallbacksFilling", base::FEATURE_DISABLED_BY_DEFAULT};
// Enable a standalone popup UI, which will allow the user to view all saved
// passwords.
const base::Feature kManualFallbacksFillingStandalone = {
......@@ -38,10 +33,6 @@ const base::Feature kManualFallbacksFillingStandalone = {
const base::Feature kPasswordForceSaving = {
"PasswordForceSaving", base::FEATURE_DISABLED_BY_DEFAULT};
// Enable the user to trigger password generation manually.
const base::Feature kManualPasswordGeneration = {
"manual-password-generation", base::FEATURE_ENABLED_BY_DEFAULT};
// Controls the ability to generate passwords that fit sites' requirements.
const base::Feature kPasswordGenerationRequirements = {
"PasswordGenerationRequirements", base::FEATURE_ENABLED_BY_DEFAULT};
......
......@@ -20,9 +20,7 @@ namespace features {
extern const base::Feature kAffiliationBasedMatching;
extern const base::Feature kAutofillHome;
extern const base::Feature kHtmlBasedUsernameDetector;
extern const base::Feature kManualFallbacksFilling;
extern const base::Feature kManualFallbacksFillingStandalone;
extern const base::Feature kManualPasswordGeneration;
extern const base::Feature kPasswordGenerationRequirements;
extern const base::Feature kPasswordGenerationRequirementsDomainOverrides;
extern const base::Feature kPasswordForceSaving;
......
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