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