Skip to content

Commit ae915bd

Browse files
Vasilii SukhanovKrishna Govind
authored andcommitted
[Canary 6063] Add two new password features for iOS and other platforms.
1. Delete undecryptable passwords on Sync start. Currently it is active for Mac and Linux. It stays active only there. 2. Ignore undecryptable passwords. The feature stays disabled for all. (cherry picked from commit 32b1445) Bug: 1489518 Change-Id: Ic7e5d0def20357e8e47d70c72d037a8a15ab6775 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4934710 Reviewed-by: Marc Treib <treib@chromium.org> Commit-Queue: Vasilii Sukhanov <vasilii@chromium.org> Cr-Original-Commit-Position: refs/heads/main@{#1208940} Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4936851 Reviewed-by: Krishna Govind <govind@chromium.org> Owners-Override: Krishna Govind <govind@chromium.org> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Cr-Commit-Position: refs/branch-heads/6063@{#4} Cr-Branched-From: cc84fa1-refs/heads/main@{#1208799}
1 parent bc9ce80 commit ae915bd

14 files changed

+103
-48
lines changed

chrome/browser/flag-metadata.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,6 +1653,11 @@
16531653
"owners": [ "ckitagawa@google.com", "clank-isochron-team@google.com" ],
16541654
"expiry_milestone": 123
16551655
},
1656+
{
1657+
"name": "delete-undecryptable-passwords",
1658+
"owners": [ "vasilii", "vsemeniuk@google.com"],
1659+
"expiry_milestone": 122
1660+
},
16561661
{
16571662
"name": "deprecate-alt-based-six-pack",
16581663
"owners": [ "zentaro@google.com", "jimmyxgong@google.com",
@@ -4904,6 +4909,11 @@
49044909
"owners": ["eddyhsu"],
49054910
"expiry_milestone": 130
49064911
},
4912+
{
4913+
"name": "ignore-undecryptable-passwords",
4914+
"owners": [ "vasilii", "vsemeniuk@google.com"],
4915+
"expiry_milestone": 122
4916+
},
49074917
{
49084918
"name": "improved-keyboard-shortcuts",
49094919
"owners": [ "zentaro@google.com", "jimmyxgong@google.com",

components/password_manager/core/browser/features/password_features.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ BASE_FEATURE(kBiometricTouchToFill,
1717
"BiometricTouchToFill",
1818
base::FEATURE_DISABLED_BY_DEFAULT);
1919

20+
// Delete undecryptable passwords from the store when Sync is active.
21+
BASE_FEATURE(kClearUndecryptablePasswordsOnSync,
22+
"ClearUndecryptablePasswordsInSync",
23+
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
24+
base::FEATURE_ENABLED_BY_DEFAULT
25+
#else
26+
base::FEATURE_DISABLED_BY_DEFAULT
27+
#endif
28+
);
29+
2030
// Disables fallback filling if the server or the autocomplete attribute says it
2131
// is a credit card field.
2232
BASE_FEATURE(kDisablePasswordsDropdownForCvcFields,
@@ -86,6 +96,12 @@ BASE_FEATURE(kPasswordManagerLogToTerminal,
8696
"PasswordManagerLogToTerminal",
8797
base::FEATURE_DISABLED_BY_DEFAULT);
8898

99+
// Displays at least the decryptable and never saved logins in the password
100+
// manager
101+
BASE_FEATURE(kSkipUndecryptablePasswords,
102+
"SkipUndecryptablePasswords",
103+
base::FEATURE_DISABLED_BY_DEFAULT);
104+
89105
// Improves PSL matching capabilities by utilizing PSL-extension list from
90106
// affiliation service. It fixes problem with incorrect password suggestions on
91107
// websites like slack.com.

components/password_manager/core/browser/features/password_features.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace password_manager::features {
1717
BASE_DECLARE_FEATURE(kAutoApproveSharedPasswordUpdatesFromSameSender);
1818

1919
BASE_DECLARE_FEATURE(kBiometricTouchToFill);
20+
BASE_DECLARE_FEATURE(kClearUndecryptablePasswordsOnSync);
2021
BASE_DECLARE_FEATURE(kDisablePasswordsDropdownForCvcFields);
2122

2223
BASE_DECLARE_FEATURE(kEnablePasswordsAccountStorage);
@@ -39,6 +40,8 @@ BASE_DECLARE_FEATURE(kPasswordManagerEnableSenderService);
3940

4041
BASE_DECLARE_FEATURE(kPasswordManagerLogToTerminal);
4142

43+
BASE_DECLARE_FEATURE(kSkipUndecryptablePasswords);
44+
4245
BASE_DECLARE_FEATURE(kUseExtensionListForPSLMatching);
4346

4447
} // namespace password_manager::features

components/password_manager/core/browser/login_database.cc

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,6 @@ std::string GeneratePlaceholders(size_t count) {
990990
return result;
991991
}
992992

993-
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
994993
// Fills |form| with necessary data required to be removed from the database
995994
// and returns it.
996995
PasswordForm GetFormForRemoval(sql::Statement& statement) {
@@ -1002,16 +1001,11 @@ PasswordForm GetFormForRemoval(sql::Statement& statement) {
10021001
form.signon_realm = statement.ColumnString(COLUMN_SIGNON_REALM);
10031002
return form;
10041003
}
1005-
#endif
10061004

10071005
// Whether we should try to return the decryptable passwords while the
10081006
// encryption service fails for some passwords.
10091007
bool ShouldReturnPartialPasswords() {
1010-
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
10111008
return base::FeatureList::IsEnabled(features::kSkipUndecryptablePasswords);
1012-
#else
1013-
return false;
1014-
#endif
10151009
}
10161010

10171011
std::unique_ptr<sync_pb::EntityMetadata> DecryptAndParseSyncEntityMetadata(
@@ -1897,7 +1891,6 @@ bool LoginDatabase::DeleteAndRecreateDatabaseFile() {
18971891
}
18981892

18991893
DatabaseCleanupResult LoginDatabase::DeleteUndecryptableLogins() {
1900-
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
19011894
TRACE_EVENT0("passwords", "LoginDatabase::DeleteUndecryptableLogins");
19021895
// If the Keychain in MacOS or the real secret key in Linux is unavailable,
19031896
// don't delete any logins.
@@ -1942,7 +1935,6 @@ DatabaseCleanupResult LoginDatabase::DeleteUndecryptableLogins() {
19421935
metrics_util::LogDeleteUndecryptableLoginsReturnValue(
19431936
metrics_util::DeleteCorruptedPasswordsResult::kSuccessPasswordsDeleted);
19441937
}
1945-
#endif
19461938

19471939
return DatabaseCleanupResult::kSuccess;
19481940
}

components/password_manager/core/browser/login_database_unittest.cc

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "components/autofill/core/common/unique_ids.h"
2828
#include "components/os_crypt/sync/os_crypt.h"
2929
#include "components/os_crypt/sync/os_crypt_mocker.h"
30+
#include "components/password_manager/core/browser/features/password_features.h"
3031
#include "components/password_manager/core/browser/password_form.h"
3132
#include "components/password_manager/core/browser/password_manager_test_utils.h"
3233
#include "components/password_manager/core/browser/password_store_change.h"
@@ -2099,6 +2100,7 @@ INSTANTIATE_TEST_SUITE_P(MigrationToVCurrent,
20992100
LoginDatabaseMigrationTestBroken,
21002101
testing::Values(1, 2, 3, 24));
21012102

2103+
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_IOS)
21022104
class LoginDatabaseUndecryptableLoginsTest : public testing::Test {
21032105
protected:
21042106
LoginDatabaseUndecryptableLoginsTest() = default;
@@ -2202,9 +2204,11 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, DeleteUndecryptableLoginsTest) {
22022204
base::HistogramTester histogram_tester;
22032205
ASSERT_TRUE(db.Init());
22042206

2205-
#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
2206-
// Make sure that we can't get any logins when database is corrupted.
2207+
#if BUILDFLAG(IS_CASTOS)
22072208
// Disabling the checks in chromecast because encryption is unavailable.
2209+
EXPECT_EQ(DatabaseCleanupResult::kEncryptionUnavailable,
2210+
db.DeleteUndecryptableLogins());
2211+
#else
22082212
std::vector<PasswordForm> result;
22092213
EXPECT_FALSE(db.GetAutofillableLogins(&result));
22102214
EXPECT_TRUE(result.empty());
@@ -2219,24 +2223,13 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, DeleteUndecryptableLoginsTest) {
22192223
EXPECT_TRUE(db.GetBlocklistLogins(&result));
22202224
EXPECT_THAT(result, IsEmpty());
22212225

2222-
RunUntilIdle();
2223-
#elif BUILDFLAG(IS_CASTOS)
2224-
EXPECT_EQ(DatabaseCleanupResult::kEncryptionUnavailable,
2225-
db.DeleteUndecryptableLogins());
2226-
#else
2227-
EXPECT_EQ(DatabaseCleanupResult::kSuccess, db.DeleteUndecryptableLogins());
2228-
#endif
2229-
2230-
// Check histograms.
2231-
#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
22322226
histogram_tester.ExpectUniqueSample(
22332227
"PasswordManager.DeleteUndecryptableLoginsReturnValue",
22342228
metrics_util::DeleteCorruptedPasswordsResult::kSuccessPasswordsDeleted,
22352229
1);
22362230
#endif
22372231
}
22382232

2239-
#if BUILDFLAG(IS_MAC)
22402233
TEST_F(LoginDatabaseUndecryptableLoginsTest,
22412234
PasswordRecoveryDisabledGetLogins) {
22422235
AddDummyLogin("foo1", GURL("https://foo1.com/"), false,
@@ -2253,6 +2246,7 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest,
22532246
RunUntilIdle();
22542247
}
22552248

2249+
#if BUILDFLAG(IS_MAC)
22562250
TEST_F(LoginDatabaseUndecryptableLoginsTest, KeychainLockedTest) {
22572251
AddDummyLogin("foo1", GURL("https://foo1.com/"), false,
22582252
/*blocklisted=*/false);
@@ -2271,7 +2265,6 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, KeychainLockedTest) {
22712265
}
22722266
#endif // BUILDFLAG(IS_MAC)
22732267

2274-
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
22752268
// Test getting auto sign in logins when there are undecryptable ones
22762269
TEST_F(LoginDatabaseUndecryptableLoginsTest, GetAutoSignInLogins) {
22772270
std::vector<PasswordForm> forms;
@@ -2291,8 +2284,8 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, GetAutoSignInLogins) {
22912284

22922285
EXPECT_FALSE(db.GetAutoSignInLogins(&forms));
22932286

2294-
base::test::ScopedFeatureList feature_list;
2295-
feature_list.InitAndEnableFeature(features::kSkipUndecryptablePasswords);
2287+
base::test::ScopedFeatureList feature_list(
2288+
features::kSkipUndecryptablePasswords);
22962289

22972290
EXPECT_TRUE(db.GetAutoSignInLogins(&forms));
22982291
EXPECT_THAT(forms, UnorderedElementsAre(HasPrimaryKeyAndEquals(form1),
@@ -2315,8 +2308,8 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, GetLogins) {
23152308
EXPECT_FALSE(db.GetLogins(PasswordFormDigest(form),
23162309
/*should_PSL_matching_apply=*/false, &result));
23172310

2318-
base::test::ScopedFeatureList feature_list;
2319-
feature_list.InitAndEnableFeature(features::kSkipUndecryptablePasswords);
2311+
base::test::ScopedFeatureList feature_list(
2312+
features::kSkipUndecryptablePasswords);
23202313
result.clear();
23212314

23222315
EXPECT_TRUE(db.GetLogins(PasswordFormDigest(form),
@@ -2343,13 +2336,13 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, GetAutofillableLogins) {
23432336

23442337
EXPECT_FALSE(db.GetAutofillableLogins(&result));
23452338

2346-
base::test::ScopedFeatureList feature_list;
2347-
feature_list.InitAndEnableFeature(features::kSkipUndecryptablePasswords);
2339+
base::test::ScopedFeatureList feature_list(
2340+
features::kSkipUndecryptablePasswords);
23482341

23492342
EXPECT_TRUE(db.GetAutofillableLogins(&result));
23502343
EXPECT_THAT(result, ElementsAre(HasPrimaryKeyAndEquals(form1)));
23512344
}
2352-
#endif
2345+
#endif // #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_IOS)
23532346

23542347
// Test encrypted passwords are present in add change lists.
23552348
TEST_F(LoginDatabaseTest, EncryptedPasswordAdd) {

components/password_manager/core/browser/sync/password_sync_bridge.cc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "base/strings/escape.h"
1919
#include "base/strings/string_number_conversions.h"
2020
#include "build/build_config.h"
21+
#include "components/password_manager/core/browser/features/password_features.h"
2122
#include "components/password_manager/core/browser/password_form.h"
2223
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
2324
#include "components/password_manager/core/browser/password_store_change.h"
@@ -190,12 +191,9 @@ bool IsCredentialPhished(const sync_pb::PasswordSpecificsData& specifics) {
190191
// the local copy, to be replaced by the remote version coming from Sync during
191192
// merge.
192193
bool ShouldRecoverPasswordsDuringMerge() {
193-
// Delete the local undecryptable copy when this is MacOS or Linux only.
194-
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
195-
return true;
196-
#else
197-
return false;
198-
#endif
194+
// Delete the local undecryptable copy. Launched on MacOS or Linux only.
195+
return base::FeatureList::IsEnabled(
196+
features::kClearUndecryptablePasswordsOnSync);
199197
}
200198

201199
bool ShouldCleanSyncMetadataDuringStartupWhenDecryptionFails() {

components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "base/test/mock_callback.h"
1919
#include "base/test/scoped_feature_list.h"
2020
#include "build/build_config.h"
21+
#include "components/password_manager/core/browser/features/password_features.h"
2122
#include "components/password_manager/core/browser/login_database.h"
2223
#include "components/password_manager/core/browser/password_form.h"
2324
#include "components/password_manager/core/browser/password_store_sync.h"
@@ -1300,7 +1301,6 @@ TEST_F(PasswordSyncBridgeTest,
13001301
syncer::WipeModelUponSyncDisabledBehavior::kNever, base::DoNothing());
13011302
}
13021303

1303-
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
13041304
// Tests that in case ReadAllCredentials() during initial merge returns
13051305
// encryption service failure, the bridge would try to do a DB clean up.
13061306
class PasswordSyncBridgeMergeTest
@@ -1328,6 +1328,8 @@ class PasswordSyncBridgeMergeTest
13281328
};
13291329

13301330
TEST_P(PasswordSyncBridgeMergeTest, ShouldFixWhenDatabaseEncryptionFails) {
1331+
base::test::ScopedFeatureList feature_list(
1332+
features::kClearUndecryptablePasswordsOnSync);
13311333
ShouldDeleteUndecryptableLoginsDuringMerge();
13321334
}
13331335

@@ -1337,7 +1339,6 @@ INSTANTIATE_TEST_SUITE_P(
13371339
testing::Values(
13381340
FormRetrievalResult::kEncryptionServiceFailure,
13391341
FormRetrievalResult::kEncryptionServiceFailureWithPartialData));
1340-
#endif
13411342

13421343
TEST_F(PasswordSyncBridgeTest,
13431344
ShouldDeleteSyncMetadataWhenApplyDisableSyncChanges) {

components/password_manager/core/common/password_manager_features.cc

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,6 @@ BASE_FEATURE(kRecoverFromNeverSaveAndroid,
9999
"RecoverFromNeverSaveAndroid_LAUNCHED",
100100
base::FEATURE_ENABLED_BY_DEFAULT);
101101

102-
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
103-
// Displays at least the decryptable and never saved logins in the password
104-
// manager
105-
BASE_FEATURE(kSkipUndecryptablePasswords,
106-
"SkipUndecryptablePasswords",
107-
base::FEATURE_DISABLED_BY_DEFAULT);
108-
#endif
109-
110102
#if BUILDFLAG(IS_ANDROID)
111103
// Use GMS AccountSettings to manage passkeys when UPM is not available.
112104
BASE_FEATURE(kPasskeyManagementUsingAccountSettingsAndroid,

components/password_manager/core/common/password_manager_features.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ BASE_DECLARE_FEATURE(kPasswordGenerationExperiment);
3939
#endif
4040
BASE_DECLARE_FEATURE(kPasswordsImportM2);
4141
BASE_DECLARE_FEATURE(kRecoverFromNeverSaveAndroid);
42-
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
43-
BASE_DECLARE_FEATURE(kSkipUndecryptablePasswords);
44-
#endif
42+
4543
#if BUILDFLAG(IS_ANDROID)
4644
BASE_DECLARE_FEATURE(kPasskeyManagementUsingAccountSettingsAndroid);
4745
BASE_DECLARE_FEATURE(kPasswordEditDialogWithDetails);

ios/chrome/browser/flags/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ source_set("flags") {
3333
"//components/omnibox/common",
3434
"//components/optimization_guide/core",
3535
"//components/optimization_guide/core:features",
36+
"//components/password_manager/core/browser/features:password_features",
3637
"//components/password_manager/core/common:features",
3738
"//components/payments/core",
3839
"//components/policy:generated",

ios/chrome/browser/flags/about_flags.mm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#import "components/omnibox/common/omnibox_features.h"
4848
#import "components/optimization_guide/core/optimization_guide_features.h"
4949
#import "components/optimization_guide/core/optimization_guide_switches.h"
50+
#import "components/password_manager/core/browser/features/password_features.h"
5051
#import "components/password_manager/core/common/password_manager_features.h"
5152
#import "components/payments/core/features.h"
5253
#import "components/policy/core/common/features.h"
@@ -1543,6 +1544,18 @@
15431544
{"enable-feed-containment", flag_descriptions::kEnableFeedContainmentName,
15441545
flag_descriptions::kEnableFeedContainmentDescription, flags_ui::kOsIos,
15451546
FEATURE_VALUE_TYPE(kEnableFeedContainment)},
1547+
{"delete-undecryptable-passwords",
1548+
flag_descriptions::kClearUndecryptablePasswordsOnSyncName,
1549+
flag_descriptions::kClearUndecryptablePasswordsOnSyncDescription,
1550+
flags_ui::kOsIos,
1551+
FEATURE_VALUE_TYPE(
1552+
password_manager::features::kClearUndecryptablePasswordsOnSync)},
1553+
{"ignore-undecryptable-passwords",
1554+
flag_descriptions::kSkipUndecryptablePasswordsName,
1555+
flag_descriptions::kSkipUndecryptablePasswordsDescription,
1556+
flags_ui::kOsIos,
1557+
FEATURE_VALUE_TYPE(
1558+
password_manager::features::kSkipUndecryptablePasswords)},
15461559
};
15471560

15481561
bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {

ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,12 @@ extern const char kAppleCalendarExperienceKitDescription[] =
200200
"When enabled, long pressing on dates will trigger Experience Kit Apple "
201201
"Calendar event handling.";
202202

203+
const char kClearUndecryptablePasswordsOnSyncName[] =
204+
"Enable cleaning up of password store on initial Sync";
205+
const char kClearUndecryptablePasswordsOnSyncDescription[] =
206+
"Once password sync starts for the first time, the currently undecryptable "
207+
"passwords will be silently cleaned up";
208+
203209
const char kContentPushNotificationsName[] = "Content Push Notifications";
204210
const char kContentPushNotificationsDescription[] =
205211
"Enables the content push notifications.";
@@ -944,6 +950,12 @@ const char kShowInactiveTabsCountDescription[] =
944950
"When enabled, the count of Inactive Tabs is shown in the Inactive Tabs "
945951
"button that appears in the Tab Grid.";
946952

953+
const char kSkipUndecryptablePasswordsName[] =
954+
"Enable silent ignoring of undecryptable passwords";
955+
const char kSkipUndecryptablePasswordsDescription[] =
956+
"The password store will silently skip undecryptable passwords when "
957+
"reading them";
958+
947959
const char kSmartSortingPriceTrackingDestinationName[] =
948960
"Price Tracking destination (with Smart Sorting)";
949961
const char kSmartSortingPriceTrackingDestinationDescription[] =

ios/chrome/browser/flags/ios_chrome_flag_descriptions.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ extern const char kSpotlightDonateNewIntentsDescription[];
166166
extern const char kBreakpadNoDelayInitialUploadName[];
167167
extern const char kBreakpadNoDelayInitialUploadDescription[];
168168

169+
// Title and description for the flag to enable deletion of undecryptable
170+
// passwords from Sync.
171+
extern const char kClearUndecryptablePasswordsOnSyncName[];
172+
extern const char kClearUndecryptablePasswordsOnSyncDescription[];
173+
169174
// Title and description for the flag to enable the content notifications
170175
// feature.
171176
extern const char kContentPushNotificationsName[];
@@ -827,6 +832,11 @@ extern const char kShowAutofillTypePredictionsDescription[];
827832
extern const char kShowInactiveTabsCountName[];
828833
extern const char kShowInactiveTabsCountDescription[];
829834

835+
// Title and description for the flag to enable ignoring undecryptable passwords
836+
// in the password storage.
837+
extern const char kSkipUndecryptablePasswordsName[];
838+
extern const char kSkipUndecryptablePasswordsDescription[];
839+
830840
// Title and description for the flag to add the Price Tracking destination
831841
// (with Smart Sorting) to the new overflow menu.
832842
extern const char kSmartSortingPriceTrackingDestinationName[];

0 commit comments

Comments
 (0)