1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/macros.h"
6 #include "base/test/metrics/histogram_tester.h"
7 #include "chrome/browser/signin/identity_manager_factory.h"
8 #include "chrome/browser/sync/test/integration/encryption_helper.h"
9 #include "chrome/browser/sync/test/integration/passwords_helper.h"
10 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
11 #include "chrome/browser/sync/test/integration/secondary_account_helper.h"
12 #include "chrome/browser/sync/test/integration/sync_test.h"
13 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
14 #include "components/password_manager/core/browser/password_manager_features_util.h"
15 #include "components/password_manager/core/browser/password_manager_test_utils.h"
16 #include "components/password_manager/core/browser/sync/password_sync_bridge.h"
17 #include "components/password_manager/core/common/password_manager_features.h"
18 #include "components/signin/public/identity_manager/identity_test_utils.h"
19 #include "components/sync/driver/profile_sync_service.h"
20 #include "components/sync/test/fake_server/fake_server_nigori_helper.h"
21 #include "content/public/test/browser_test.h"
22 #include "content/public/test/test_launcher.h"
23
24 namespace {
25
26 using password_manager::features_util::OptInToAccountStorage;
27 using passwords_helper::AddLogin;
28 using passwords_helper::CreateTestPasswordForm;
29 using passwords_helper::GetPasswordCount;
30 using passwords_helper::GetPasswordStore;
31 using passwords_helper::GetVerifierPasswordCount;
32 using passwords_helper::GetVerifierPasswordStore;
33 using passwords_helper::ProfileContainsSamePasswordFormsAsVerifier;
34
35 using password_manager::PasswordForm;
36
37 using testing::ElementsAre;
38 using testing::IsEmpty;
39
40 const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
41 syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
42
43 class SingleClientPasswordsSyncTest : public SyncTest {
44 public:
SingleClientPasswordsSyncTest()45 SingleClientPasswordsSyncTest() : SyncTest(SINGLE_CLIENT) {}
46 ~SingleClientPasswordsSyncTest() override = default;
47 };
48
49 class SingleClientPasswordsSyncTestWithVerifier
50 : public SingleClientPasswordsSyncTest {
51 public:
52 SingleClientPasswordsSyncTestWithVerifier() = default;
53 ~SingleClientPasswordsSyncTestWithVerifier() override = default;
54
UseVerifier()55 bool UseVerifier() override {
56 // TODO(crbug.com/1137740): rewrite tests to not use verifier.
57 return true;
58 }
59 };
60
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTestWithVerifier,Sanity)61 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTestWithVerifier, Sanity) {
62 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
63
64 PasswordForm form = CreateTestPasswordForm(0);
65 AddLogin(GetVerifierPasswordStore(), form);
66 ASSERT_EQ(1, GetVerifierPasswordCount());
67 AddLogin(GetPasswordStore(0), form);
68 ASSERT_EQ(1, GetPasswordCount(0));
69
70 ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
71 ASSERT_TRUE(ProfileContainsSamePasswordFormsAsVerifier(0));
72 ASSERT_EQ(1, GetPasswordCount(0));
73 }
74
75 // Verifies that committed passwords contain the appropriate proto fields, and
76 // in particular lack some others that could potentially contain unencrypted
77 // data. In this test, custom passphrase is NOT set.
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTestWithVerifier,CommitWithoutCustomPassphrase)78 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTestWithVerifier,
79 CommitWithoutCustomPassphrase) {
80 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
81
82 PasswordForm form = CreateTestPasswordForm(0);
83 AddLogin(GetVerifierPasswordStore(), form);
84 ASSERT_EQ(1, GetVerifierPasswordCount());
85 AddLogin(GetPasswordStore(0), form);
86 ASSERT_EQ(1, GetPasswordCount(0));
87 ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
88
89 const std::vector<sync_pb::SyncEntity> entities =
90 fake_server_->GetSyncEntitiesByModelType(syncer::PASSWORDS);
91 ASSERT_EQ(1U, entities.size());
92 EXPECT_EQ("", entities[0].non_unique_name());
93 EXPECT_TRUE(entities[0].specifics().password().has_encrypted());
94 EXPECT_FALSE(
95 entities[0].specifics().password().has_client_only_encrypted_data());
96 EXPECT_TRUE(entities[0].specifics().password().has_unencrypted_metadata());
97 EXPECT_TRUE(
98 entities[0].specifics().password().unencrypted_metadata().has_url());
99 }
100
101 // Same as above but with custom passphrase set, which requires to prune commit
102 // data even further.
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTestWithVerifier,CommitWithCustomPassphrase)103 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTestWithVerifier,
104 CommitWithCustomPassphrase) {
105 SetEncryptionPassphraseForClient(/*index=*/0, "hunter2");
106 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
107
108 PasswordForm form = CreateTestPasswordForm(0);
109 AddLogin(GetVerifierPasswordStore(), form);
110 ASSERT_EQ(1, GetVerifierPasswordCount());
111 AddLogin(GetPasswordStore(0), form);
112 ASSERT_EQ(1, GetPasswordCount(0));
113 ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
114
115 const std::vector<sync_pb::SyncEntity> entities =
116 fake_server_->GetSyncEntitiesByModelType(syncer::PASSWORDS);
117 ASSERT_EQ(1U, entities.size());
118 EXPECT_EQ("", entities[0].non_unique_name());
119 EXPECT_TRUE(entities[0].specifics().password().has_encrypted());
120 EXPECT_FALSE(
121 entities[0].specifics().password().has_client_only_encrypted_data());
122 EXPECT_FALSE(entities[0].specifics().password().has_unencrypted_metadata());
123 }
124
125 // Tests the scenario when a syncing user enables a custom passphrase. PASSWORDS
126 // should be recommitted with the new encryption key.
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTestWithVerifier,ReencryptsDataWhenPassphraseIsSet)127 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTestWithVerifier,
128 ReencryptsDataWhenPassphraseIsSet) {
129 ASSERT_TRUE(SetupSync());
130 ASSERT_TRUE(ServerNigoriChecker(GetSyncService(0), fake_server_.get(),
131 syncer::PassphraseType::kKeystorePassphrase)
132 .Wait());
133
134 PasswordForm form = CreateTestPasswordForm(0);
135 AddLogin(GetVerifierPasswordStore(), form);
136 ASSERT_EQ(1, GetVerifierPasswordCount());
137 AddLogin(GetPasswordStore(0), form);
138 ASSERT_EQ(1, GetPasswordCount(0));
139 ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
140
141 std::string prior_encryption_key_name;
142 {
143 const std::vector<sync_pb::SyncEntity> entities =
144 fake_server_->GetSyncEntitiesByModelType(syncer::PASSWORDS);
145 ASSERT_EQ(1U, entities.size());
146 ASSERT_EQ("", entities[0].non_unique_name());
147 ASSERT_TRUE(entities[0].specifics().password().has_encrypted());
148 ASSERT_FALSE(
149 entities[0].specifics().password().has_client_only_encrypted_data());
150 ASSERT_TRUE(entities[0].specifics().password().has_unencrypted_metadata());
151 prior_encryption_key_name =
152 entities[0].specifics().password().encrypted().key_name();
153 }
154
155 ASSERT_FALSE(prior_encryption_key_name.empty());
156
157 GetSyncService(0)->GetUserSettings()->SetEncryptionPassphrase("hunter2");
158 ASSERT_TRUE(ServerNigoriChecker(GetSyncService(0), fake_server_.get(),
159 syncer::PassphraseType::kCustomPassphrase)
160 .Wait());
161 ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
162
163 const std::vector<sync_pb::SyncEntity> entities =
164 fake_server_->GetSyncEntitiesByModelType(syncer::PASSWORDS);
165 ASSERT_EQ(1U, entities.size());
166 EXPECT_EQ("", entities[0].non_unique_name());
167 EXPECT_TRUE(entities[0].specifics().password().has_encrypted());
168 EXPECT_FALSE(
169 entities[0].specifics().password().has_client_only_encrypted_data());
170 EXPECT_FALSE(entities[0].specifics().password().has_unencrypted_metadata());
171
172 const std::string new_encryption_key_name =
173 entities[0].specifics().password().encrypted().key_name();
174 EXPECT_FALSE(new_encryption_key_name.empty());
175 EXPECT_NE(new_encryption_key_name, prior_encryption_key_name);
176 }
177
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTest,PRE_PersistProgressMarkerOnRestart)178 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTest,
179 PRE_PersistProgressMarkerOnRestart) {
180 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
181 PasswordForm form = CreateTestPasswordForm(0);
182 AddLogin(GetPasswordStore(0), form);
183 ASSERT_EQ(1, GetPasswordCount(0));
184 // Setup sync, wait for its completion, and make sure changes were synced.
185 base::HistogramTester histogram_tester;
186 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
187 ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
188 // Upon a local creation, the received update will be seen as reflection and
189 // get counted as incremental update.
190 EXPECT_EQ(
191 1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.PASSWORD",
192 /*REMOTE_NON_INITIAL_UPDATE=*/4));
193 }
194
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTest,PersistProgressMarkerOnRestart)195 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncTest,
196 PersistProgressMarkerOnRestart) {
197 base::HistogramTester histogram_tester;
198 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
199 ASSERT_EQ(1, GetPasswordCount(0));
200 #if defined(OS_CHROMEOS)
201 // signin::SetRefreshTokenForPrimaryAccount() is needed on ChromeOS in order
202 // to get a non-empty refresh token on startup.
203 GetClient(0)->SignInPrimaryAccount();
204 #endif // defined(OS_CHROMEOS)
205 ASSERT_TRUE(GetClient(0)->AwaitEngineInitialization());
206
207 // After restart, the last sync cycle snapshot should be empty. Once a sync
208 // request happened (e.g. by a poll), that snapshot is populated. We use the
209 // following checker to simply wait for an non-empty snapshot.
210 EXPECT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
211
212 // If that metadata hasn't been properly persisted, the password stored on the
213 // server will be received at the client as an initial update or an
214 // incremental once.
215 EXPECT_EQ(
216 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.PASSWORD",
217 /*REMOTE_INITIAL_UPDATE=*/5));
218 EXPECT_EQ(
219 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.PASSWORD",
220 /*REMOTE_NON_INITIAL_UPDATE=*/4));
221 }
222
223 class SingleClientPasswordsWithAccountStorageSyncTest : public SyncTest {
224 public:
SingleClientPasswordsWithAccountStorageSyncTest()225 SingleClientPasswordsWithAccountStorageSyncTest() : SyncTest(SINGLE_CLIENT) {
226 feature_list_.InitWithFeatures(
227 /*enabled_features=*/{password_manager::features::
228 kEnablePasswordsAccountStorage},
229 /*disabled_features=*/{});
230 }
231 ~SingleClientPasswordsWithAccountStorageSyncTest() override = default;
232
SetUpInProcessBrowserTestFixture()233 void SetUpInProcessBrowserTestFixture() override {
234 test_signin_client_factory_ =
235 secondary_account_helper::SetUpSigninClient(&test_url_loader_factory_);
236 }
237
SetUpOnMainThread()238 void SetUpOnMainThread() override {
239 #if defined(OS_CHROMEOS)
240 secondary_account_helper::InitNetwork();
241 #endif // defined(OS_CHROMEOS)
242 SyncTest::SetUpOnMainThread();
243
244 fake_server::SetKeystoreNigoriInFakeServer(GetFakeServer());
245 }
246
AddTestPasswordToFakeServer()247 void AddTestPasswordToFakeServer() {
248 sync_pb::PasswordSpecificsData password_data;
249 // Used for computing the client tag.
250 password_data.set_origin("https://origin.com");
251 password_data.set_username_element("username_element");
252 password_data.set_username_value("username_value");
253 password_data.set_password_element("password_element");
254 password_data.set_signon_realm("abc");
255 // Other data.
256 password_data.set_password_value("password_value");
257
258 passwords_helper::InjectKeystoreEncryptedServerPassword(password_data,
259 GetFakeServer());
260 }
261
262 private:
263 base::test::ScopedFeatureList feature_list_;
264
265 secondary_account_helper::ScopedSigninClientFactory
266 test_signin_client_factory_;
267
268 DISALLOW_COPY_AND_ASSIGN(SingleClientPasswordsWithAccountStorageSyncTest);
269 };
270
271 // Sanity check: For Sync-the-feature, password data still ends up in the
272 // profile database.
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,StoresDataForSyncingPrimaryAccountInProfileDB)273 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
274 StoresDataForSyncingPrimaryAccountInProfileDB) {
275 AddTestPasswordToFakeServer();
276
277 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
278
279 // Sign in and enable Sync.
280 ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
281 GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
282 GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
283 kSetSourceFromTest);
284 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
285
286 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
287 ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
288
289 // Make sure the password showed up in the account store and not in the
290 // profile store.
291 password_manager::PasswordStore* profile_store =
292 passwords_helper::GetPasswordStore(0);
293 EXPECT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 1u);
294
295 password_manager::PasswordStore* account_store =
296 passwords_helper::GetAccountPasswordStore(0);
297 EXPECT_EQ(passwords_helper::GetAllLogins(account_store).size(), 0u);
298 }
299
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,StoresDataForNonSyncingPrimaryAccountInAccountDB)300 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
301 StoresDataForNonSyncingPrimaryAccountInAccountDB) {
302 AddTestPasswordToFakeServer();
303
304 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
305
306 #if defined(OS_CHROMEOS)
307 // On ChromeOS, Sync-the-feature gets started automatically once a primary
308 // account is signed in. To prevent that, explicitly set SyncRequested to
309 // false.
310 GetSyncService(0)->GetUserSettings()->SetSyncRequested(false);
311 #endif // defined(OS_CHROMEOS)
312
313 // Setup a primary account, but don't actually enable Sync-the-feature (so
314 // that Sync will start in transport mode).
315 ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
316 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
317 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
318
319 // Let the user opt in to the account-scoped password storage, and wait for it
320 // to become active.
321 OptInToAccountStorage(GetProfile(0)->GetPrefs(), GetSyncService(0));
322 PasswordSyncActiveChecker(GetSyncService(0)).Wait();
323 ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
324
325 // Make sure the password showed up in the account store and not in the
326 // profile store.
327 password_manager::PasswordStore* profile_store =
328 passwords_helper::GetPasswordStore(0);
329 EXPECT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 0u);
330
331 password_manager::PasswordStore* account_store =
332 passwords_helper::GetAccountPasswordStore(0);
333 EXPECT_EQ(passwords_helper::GetAllLogins(account_store).size(), 1u);
334 }
335
336 // The unconsented primary account isn't supported on ChromeOS (see
337 // IdentityManager::ComputeUnconsentedPrimaryAccountInfo()) so Sync won't start
338 // up for a secondary account.
339 #if !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,StoresDataForSecondaryAccountInAccountDB)340 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
341 StoresDataForSecondaryAccountInAccountDB) {
342 AddTestPasswordToFakeServer();
343
344 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
345
346 // Setup Sync for a secondary account (i.e. in transport mode).
347 secondary_account_helper::SignInSecondaryAccount(
348 GetProfile(0), &test_url_loader_factory_, "user@email.com");
349 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
350 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
351
352 // Let the user opt in to the account-scoped password storage, and wait for it
353 // to become active.
354 OptInToAccountStorage(GetProfile(0)->GetPrefs(), GetSyncService(0));
355 PasswordSyncActiveChecker(GetSyncService(0)).Wait();
356 ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
357
358 // Make sure the password showed up in the account store and not in the
359 // profile store.
360 password_manager::PasswordStore* profile_store =
361 passwords_helper::GetPasswordStore(0);
362 EXPECT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 0u);
363
364 password_manager::PasswordStore* account_store =
365 passwords_helper::GetAccountPasswordStore(0);
366 EXPECT_EQ(passwords_helper::GetAllLogins(account_store).size(), 1u);
367 }
368 #endif // !defined(OS_CHROMEOS)
369
370 // ChromeOS does not support signing out of a primary account.
371 #if !defined(OS_CHROMEOS)
372 // Sanity check: The profile database should *not* get cleared on signout.
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,DoesNotClearProfileDBOnSignout)373 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
374 DoesNotClearProfileDBOnSignout) {
375 AddTestPasswordToFakeServer();
376
377 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
378
379 // Sign in and enable Sync.
380 ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
381 GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
382 GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
383 kSetSourceFromTest);
384 ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
385
386 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
387
388 // Make sure the password showed up in the profile store.
389 password_manager::PasswordStore* profile_store =
390 passwords_helper::GetPasswordStore(0);
391 ASSERT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 1u);
392
393 // Sign out again.
394 GetClient(0)->SignOutPrimaryAccount();
395 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
396
397 // Make sure the password is still in the store.
398 ASSERT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 1u);
399 }
400 #endif // !defined(OS_CHROMEOS)
401
402 // The unconsented primary account isn't supported on ChromeOS (see
403 // IdentityManager::ComputeUnconsentedPrimaryAccountInfo()) so Sync won't start
404 // up for a secondary account.
405 #if !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,ClearsAccountDBOnSignout)406 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
407 ClearsAccountDBOnSignout) {
408 AddTestPasswordToFakeServer();
409
410 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
411
412 // Setup Sync for a secondary account (i.e. in transport mode).
413 AccountInfo account_info = secondary_account_helper::SignInSecondaryAccount(
414 GetProfile(0), &test_url_loader_factory_, "user@email.com");
415 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
416 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
417
418 // Let the user opt in to the account-scoped password storage, and wait for it
419 // to become active.
420 OptInToAccountStorage(GetProfile(0)->GetPrefs(), GetSyncService(0));
421 PasswordSyncActiveChecker(GetSyncService(0)).Wait();
422
423 // Make sure the password showed up in the account store.
424 password_manager::PasswordStore* account_store =
425 passwords_helper::GetAccountPasswordStore(0);
426 ASSERT_EQ(passwords_helper::GetAllLogins(account_store).size(), 1u);
427
428 // Sign out again.
429 secondary_account_helper::SignOutSecondaryAccount(
430 GetProfile(0), &test_url_loader_factory_, account_info.account_id);
431
432 // Make sure the password is gone from the store.
433 ASSERT_EQ(passwords_helper::GetAllLogins(account_store).size(), 0u);
434 }
435 #endif // !defined(OS_CHROMEOS)
436
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,SwitchesStoresOnEnablingSync)437 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
438 SwitchesStoresOnEnablingSync) {
439 AddTestPasswordToFakeServer();
440
441 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
442
443 // On ChromeOS, Sync-the-feature starts automatically as soon as a primary
444 // account is signed in. To prevent that, explicitly set SyncRequested to
445 // false on ChromeOS.
446 #if defined(OS_CHROMEOS)
447 GetSyncService(0)->GetUserSettings()->SetSyncRequested(false);
448 #endif // !defined(OS_CHROMEOS)
449
450 // Sign in to a primary account, but don't enable Sync-the-feature.
451 // Note: This state shouldn't actually be reachable (the flow for setting a
452 // primary account also enables Sync), but still best to cover it here.
453 ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
454 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
455 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
456
457 // Let the user opt in to the account-scoped password storage, and wait for it
458 // to become active.
459 OptInToAccountStorage(GetProfile(0)->GetPrefs(), GetSyncService(0));
460 PasswordSyncActiveChecker(GetSyncService(0)).Wait();
461
462 // Make sure the password showed up in the account store.
463 password_manager::PasswordStore* account_store =
464 passwords_helper::GetAccountPasswordStore(0);
465 ASSERT_EQ(passwords_helper::GetAllLogins(account_store).size(), 1u);
466
467 // Turn on Sync-the-feature.
468 GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
469 GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
470 kSetSourceFromTest);
471 ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
472 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
473
474 // Make sure the password is now in the profile store, but *not* in the
475 // account store anymore.
476 password_manager::PasswordStore* profile_store =
477 passwords_helper::GetPasswordStore(0);
478 EXPECT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 1u);
479 EXPECT_EQ(passwords_helper::GetAllLogins(account_store).size(), 0u);
480
481 // Turn off Sync-the-feature again.
482 // Note: Turning Sync off without signing out isn't actually exposed to the
483 // user, so this generally shouldn't happen. Still best to cover it here.
484 GetSyncService(0)->GetUserSettings()->SetSyncRequested(false);
485 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
486 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
487
488 // Now the password should be in both stores: The profile store does *not* get
489 // cleared when Sync gets disabled.
490 EXPECT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 1u);
491 EXPECT_EQ(passwords_helper::GetAllLogins(account_store).size(), 1u);
492 }
493
494 // The unconsented primary account isn't supported on ChromeOS (see
495 // IdentityManager::ComputeUnconsentedPrimaryAccountInfo()) so Sync won't start
496 // up for a secondary account.
497 #if !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,SwitchesStoresOnMakingAccountPrimary)498 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
499 SwitchesStoresOnMakingAccountPrimary) {
500 AddTestPasswordToFakeServer();
501
502 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
503
504 // Setup Sync for a secondary account (i.e. in transport mode).
505 AccountInfo account_info = secondary_account_helper::SignInSecondaryAccount(
506 GetProfile(0), &test_url_loader_factory_, "user@email.com");
507 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
508 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
509
510 // Let the user opt in to the account-scoped password storage, and wait for it
511 // to become active.
512 OptInToAccountStorage(GetProfile(0)->GetPrefs(), GetSyncService(0));
513 PasswordSyncActiveChecker(GetSyncService(0)).Wait();
514
515 // Make sure the password showed up in the account store.
516 password_manager::PasswordStore* account_store =
517 passwords_helper::GetAccountPasswordStore(0);
518 ASSERT_EQ(passwords_helper::GetAllLogins(account_store).size(), 1u);
519
520 // Make the account primary and turn on Sync-the-feature.
521 secondary_account_helper::MakeAccountPrimary(GetProfile(0), "user@email.com");
522 GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
523 GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
524 kSetSourceFromTest);
525 ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
526 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
527
528 // Make sure the password is now in the profile store, but *not* in the
529 // account store anymore.
530 password_manager::PasswordStore* profile_store =
531 passwords_helper::GetPasswordStore(0);
532 EXPECT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 1u);
533 EXPECT_EQ(passwords_helper::GetAllLogins(account_store).size(), 0u);
534
535 // Clear the primary account to put Sync into transport mode again.
536 // Note: Clearing the primary account without also signing out isn't exposed
537 // to the user, so this shouldn't happen. Still best to cover it here.
538 signin::ClearPrimaryAccount(
539 IdentityManagerFactory::GetForProfile(GetProfile(0)),
540 signin::ClearPrimaryAccountPolicy::KEEP_ALL_ACCOUNTS);
541 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
542 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
543
544 // The account-storage opt-in gets cleared when turning off Sync, so opt in
545 // again.
546 OptInToAccountStorage(GetProfile(0)->GetPrefs(), GetSyncService(0));
547 PasswordSyncActiveChecker(GetSyncService(0)).Wait();
548
549 // Now the password should be in both stores: The profile store does *not* get
550 // cleared when Sync gets disabled.
551 EXPECT_EQ(passwords_helper::GetAllLogins(profile_store).size(), 1u);
552 EXPECT_EQ(passwords_helper::GetAllLogins(account_store).size(), 1u);
553 }
554
555 // Regression test for crbug.com/1076378.
IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,EnablesPasswordSyncOnOptingInToSync)556 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
557 EnablesPasswordSyncOnOptingInToSync) {
558 AddTestPasswordToFakeServer();
559
560 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
561
562 // Setup Sync for a secondary account (i.e. in transport mode).
563 AccountInfo account_info = secondary_account_helper::SignInSecondaryAccount(
564 GetProfile(0), &test_url_loader_factory_, "user@email.com");
565 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
566 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
567
568 // The user is not opted in to the account-scoped password storage, so the
569 // passwords data type should *not* be active.
570 ASSERT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
571
572 // Make the account primary and turn on Sync-the-feature.
573 secondary_account_helper::MakeAccountPrimary(GetProfile(0), "user@email.com");
574 GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
575 GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
576 kSetSourceFromTest);
577 ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
578 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
579
580 // Now password sync should be active.
581 EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
582 }
583 #endif // !defined(OS_CHROMEOS)
584
585 } // namespace
586