1 // Copyright 2018 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/feature_list.h"
6 #include "base/files/file_util.h"
7 #include "base/macros.h"
8 #include "base/path_service.h"
9 #include "base/test/scoped_feature_list.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "build/build_config.h"
12 #include "chrome/browser/defaults.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
15 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
16 #include "chrome/browser/sync/test/integration/sync_test.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "components/sync/base/model_type.h"
19 #include "components/sync/driver/profile_sync_service.h"
20 #include "components/sync/driver/sync_driver_switches.h"
21 #include "content/public/test/browser_test.h"
22 
23 #if defined(OS_CHROMEOS)
24 #include "chrome/browser/sync/test/integration/os_sync_test.h"
25 #include "chromeos/constants/chromeos_features.h"
26 #include "components/browser_sync/browser_sync_switches.h"
27 #endif
28 
29 namespace {
30 
AllowedTypesInStandaloneTransportMode()31 syncer::ModelTypeSet AllowedTypesInStandaloneTransportMode() {
32   static_assert(41 == syncer::ModelType::NUM_ENTRIES,
33                 "Add new types below if they run in transport mode");
34   // Only some special whitelisted types (and control types) are allowed in
35   // standalone transport mode.
36   syncer::ModelTypeSet allowed_types(
37       syncer::DEVICE_INFO, syncer::USER_CONSENTS, syncer::SECURITY_EVENTS,
38       syncer::AUTOFILL_WALLET_DATA, syncer::SHARING_MESSAGE);
39   allowed_types.PutAll(syncer::ControlTypes());
40 #if defined(OS_CHROMEOS)
41   // OS sync types run in transport mode.
42   if (chromeos::features::IsSplitSettingsSyncEnabled()) {
43     allowed_types.PutAll({syncer::APPS, syncer::APP_SETTINGS, syncer::APP_LIST,
44                           syncer::APP_SETTINGS, syncer::ARC_PACKAGE,
45                           syncer::PRINTERS, syncer::OS_PREFERENCES,
46                           syncer::OS_PRIORITY_PREFERENCES, syncer::WEB_APPS});
47   }
48   if (base::FeatureList::IsEnabled(switches::kSyncWifiConfigurations)) {
49     allowed_types.Put(syncer::WIFI_CONFIGURATIONS);
50   }
51 #endif  // defined(OS_CHROMEOS)
52   return allowed_types;
53 }
54 
GetTestFilePathForCacheGuid()55 base::FilePath GetTestFilePathForCacheGuid() {
56   base::FilePath user_data_path;
57   base::PathService::Get(chrome::DIR_USER_DATA, &user_data_path);
58   return user_data_path.AppendASCII("SyncTestTmpCacheGuid");
59 }
60 
61 class SyncDisabledByUserChecker : public SingleClientStatusChangeChecker {
62  public:
SyncDisabledByUserChecker(syncer::ProfileSyncService * service)63   explicit SyncDisabledByUserChecker(syncer::ProfileSyncService* service)
64       : SingleClientStatusChangeChecker(service) {}
65 
IsExitConditionSatisfied(std::ostream * os)66   bool IsExitConditionSatisfied(std::ostream* os) override {
67     *os << "Waiting for sync disabled by user";
68     return service()->HasDisableReason(
69         syncer::SyncService::DISABLE_REASON_USER_CHOICE);
70   }
71 };
72 
73 class SingleClientStandaloneTransportSyncTest : public SyncTest {
74  public:
SingleClientStandaloneTransportSyncTest()75   SingleClientStandaloneTransportSyncTest() : SyncTest(SINGLE_CLIENT) {}
76   ~SingleClientStandaloneTransportSyncTest() override = default;
77 };
78 
IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,StartsSyncTransportOnSignin)79 IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,
80                        StartsSyncTransportOnSignin) {
81 #if defined(OS_CHROMEOS)
82   // On Chrome OS before SplitSettingSync, sync auto-starts on sign-in.
83   if (!chromeos::features::IsSplitSettingsSyncEnabled())
84     return;
85 #endif
86   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
87 
88   // Signing in (without explicitly setting up Sync) should trigger starting the
89   // Sync machinery in standalone transport mode.
90   ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
91   EXPECT_NE(syncer::SyncService::TransportState::DISABLED,
92             GetSyncService(0)->GetTransportState());
93 
94   EXPECT_TRUE(GetClient(0)->AwaitSyncTransportActive());
95 
96   EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
97             GetSyncService(0)->GetTransportState());
98 
99   // Both IsSyncRequested and IsFirstSetupComplete should remain false (i.e.
100   // at their default values). They only get set during the Sync setup flow,
101   // either by the Sync confirmation dialog or by the settings page if going
102   // through the advanced settings flow.
103   EXPECT_FALSE(GetSyncService(0)->GetUserSettings()->IsFirstSetupComplete());
104   // TODO(crbug.com/906034,crbug.com/973770): Sort out the proper default value
105   // for IsSyncRequested().
106   // EXPECT_FALSE(GetSyncService(0)->GetUserSettings()->IsSyncRequested());
107 
108   EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
109   EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureActive());
110 
111   // Make sure that only the allowed types got activated. Note that, depending
112   // on some other feature flags, not all of the allowed types are necessarily
113   // active, and that's okay.
114   syncer::ModelTypeSet bad_types =
115       syncer::Difference(GetSyncService(0)->GetActiveDataTypes(),
116                          AllowedTypesInStandaloneTransportMode());
117   EXPECT_TRUE(bad_types.Empty()) << syncer::ModelTypeSetToString(bad_types);
118 }
119 
IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,SwitchesBetweenTransportAndFeature)120 IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,
121                        SwitchesBetweenTransportAndFeature) {
122   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
123 
124   // Set up Sync-the-feature.
125   ASSERT_TRUE(GetClient(0)->SetupSync());
126   ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
127             GetSyncService(0)->GetTransportState());
128   ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
129   ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
130 
131   // Make sure that some model type which is not allowed in transport-only mode
132   // got activated.
133   ASSERT_FALSE(AllowedTypesInStandaloneTransportMode().Has(syncer::BOOKMARKS));
134   ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has(
135       syncer::UserSelectableType::kBookmarks));
136   EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::BOOKMARKS));
137 
138   // Turn off Sync-the-feature by user choice. The machinery should start up
139   // again in transport-only mode.
140   GetSyncService(0)->GetUserSettings()->SetSyncRequested(false);
141   EXPECT_TRUE(GetClient(0)->AwaitSyncTransportActive());
142 
143   EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
144             GetSyncService(0)->GetTransportState());
145   EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
146   EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureActive());
147 
148   syncer::ModelTypeSet bad_types =
149       syncer::Difference(GetSyncService(0)->GetActiveDataTypes(),
150                          AllowedTypesInStandaloneTransportMode());
151   EXPECT_TRUE(bad_types.Empty()) << syncer::ModelTypeSetToString(bad_types);
152 
153   // Finally, turn Sync-the-feature on again.
154   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
155   EXPECT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
156   EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
157             GetSyncService(0)->GetTransportState());
158   EXPECT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
159   EXPECT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
160   EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::BOOKMARKS));
161 }
162 
163 // Tests the behavior of receiving a "Reset Sync" operation from the dashboard
164 // while Sync-the-feature is active: On non-ChromeOS, this signs the user out,
165 // so Sync will be fully disabled. On ChromeOS, there is no sign-out, so
166 // Sync-the-transport will start.
IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,HandlesResetFromDashboardWhenSyncActive)167 IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,
168                        HandlesResetFromDashboardWhenSyncActive) {
169   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
170 
171   // Set up Sync-the-feature.
172   ASSERT_TRUE(GetClient(0)->SetupSync());
173   ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
174             GetSyncService(0)->GetTransportState());
175   ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
176   ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
177 
178   // Trigger a "Reset Sync" from the dashboard and wait for it to apply. This
179   // involves clearing the server data so that the birthday gets incremented,
180   // and also sending an appropriate error.
181   GetFakeServer()->ClearServerData();
182   GetFakeServer()->TriggerActionableError(
183       sync_pb::SyncEnums::NOT_MY_BIRTHDAY, "Reset Sync from Dashboard",
184       "https://chrome.google.com/sync", sync_pb::SyncEnums::UNKNOWN_ACTION);
185   EXPECT_TRUE(SyncDisabledByUserChecker(GetSyncService(0)).Wait());
186   GetFakeServer()->ClearActionableError();
187 
188   // On all platforms, Sync-the-feature should now be disabled.
189   EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
190   EXPECT_TRUE(GetSyncService(0)->HasDisableReason(
191       syncer::SyncService::DISABLE_REASON_USER_CHOICE));
192 
193 #if defined(OS_CHROMEOS)
194   // On ChromeOS, the primary account should remain, and Sync should start up
195   // again in standalone transport mode.
196   EXPECT_TRUE(GetSyncService(0)->IsAuthenticatedAccountPrimary());
197   EXPECT_FALSE(GetSyncService(0)->HasDisableReason(
198       syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN));
199   EXPECT_NE(syncer::SyncService::TransportState::DISABLED,
200             GetSyncService(0)->GetTransportState());
201 
202   EXPECT_TRUE(GetClient(0)->AwaitSyncTransportActive());
203   EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
204             GetSyncService(0)->GetTransportState());
205   EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
206 #else
207   // On non-ChromeOS platforms, the "Reset Sync" operation should also remove
208   // the primary account. Note that this behavior may change in the future, see
209   // crbug.com/246839.
210   EXPECT_FALSE(GetSyncService(0)->IsAuthenticatedAccountPrimary());
211   // Note: In real life, the account would remain as an *unconsented* primary
212   // account, and so Sync would start up again in standalone transport mode.
213   // However, since we haven't set up cookies in this test, the account is *not*
214   // considered primary anymore (not even "unconsented").
215 #endif  // defined(OS_CHROMEOS)
216 }
217 
218 // Regression test for crbug.com/955989 that verifies the cache GUID is not
219 // reset upon restart of the browser, in standalone transport mode.
IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,PRE_ReusesSameCacheGuid)220 IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,
221                        PRE_ReusesSameCacheGuid) {
222   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
223   ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
224   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
225 
226   ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
227             GetSyncService(0)->GetTransportState());
228 
229   // On platforms where Sync starts automatically (in practice, Android and
230   // ChromeOS), IsFirstSetupComplete gets set automatically, and so the full
231   // Sync feature will start upon sign-in to a primary account.
232 #if !defined(OS_CHROMEOS)
233   ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->IsFirstSetupComplete());
234   ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
235 #endif  // !defined(OS_CHROMEOS)
236 
237   syncer::SyncPrefs prefs(GetProfile(0)->GetPrefs());
238   const std::string cache_guid = prefs.GetCacheGuid();
239   ASSERT_FALSE(cache_guid.empty());
240 
241   // Save the cache GUID to file to remember after restart, for test
242   // verification purposes only.
243   base::ScopedAllowBlockingForTesting allow_blocking;
244   ASSERT_NE(-1, base::WriteFile(GetTestFilePathForCacheGuid(),
245                                 cache_guid.c_str(), cache_guid.size()));
246 }
247 
IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,ReusesSameCacheGuid)248 IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest,
249                        ReusesSameCacheGuid) {
250   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
251   ASSERT_FALSE(GetSyncService(0)->HasDisableReason(
252       syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN));
253   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
254 
255   ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
256             GetSyncService(0)->GetTransportState());
257 
258   // On platforms where Sync starts automatically (in practice, Android and
259   // ChromeOS), IsFirstSetupComplete gets set automatically, and so the full
260   // Sync feature will start upon sign-in to a primary account.
261 #if !defined(OS_CHROMEOS)
262   ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->IsFirstSetupComplete());
263   ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
264 #endif  // !defined(OS_CHROMEOS)
265 
266   syncer::SyncPrefs prefs(GetProfile(0)->GetPrefs());
267   ASSERT_FALSE(prefs.GetCacheGuid().empty());
268 
269   std::string old_cache_guid;
270   base::ScopedAllowBlockingForTesting allow_blocking;
271   ASSERT_TRUE(
272       base::ReadFileToString(GetTestFilePathForCacheGuid(), &old_cache_guid));
273   ASSERT_FALSE(old_cache_guid.empty());
274 
275   EXPECT_EQ(old_cache_guid, prefs.GetCacheGuid());
276 }
277 
278 #if defined(OS_CHROMEOS)
279 class SingleClientStandaloneTransportOsSyncTest : public OsSyncTest {
280  public:
SingleClientStandaloneTransportOsSyncTest()281   SingleClientStandaloneTransportOsSyncTest() : OsSyncTest(SINGLE_CLIENT) {
282     // Enable in-development types.
283     scoped_features_.InitAndEnableFeature(switches::kSyncWifiConfigurations);
284   }
285   ~SingleClientStandaloneTransportOsSyncTest() override = default;
286 
287  private:
288   base::test::ScopedFeatureList scoped_features_;
289 };
290 
IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportOsSyncTest,OsTypesAreActiveWhenBrowserSyncIsOff)291 IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportOsSyncTest,
292                        OsTypesAreActiveWhenBrowserSyncIsOff) {
293   ASSERT_TRUE(chromeos::features::IsSplitSettingsSyncEnabled());
294 
295   // Setup clients but don't start syncing yet.
296   ASSERT_TRUE(SetupClients());
297   syncer::SyncService* service = GetSyncService(0);
298   syncer::SyncUserSettings* settings = service->GetUserSettings();
299 
300   // Simulate a signed-in user with browser sync off and OS sync on.
301   settings->SetSyncRequested(false);
302   settings->SetOsSyncFeatureEnabled(true);
303   ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
304   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
305   ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
306             GetSyncService(0)->GetTransportState());
307   ASSERT_FALSE(service->IsSyncFeatureActive());
308 
309   // OS data types synced by the transport layer are active.
310   syncer::ModelTypeSet active_types = service->GetActiveDataTypes();
311   EXPECT_TRUE(active_types.Has(syncer::APP_LIST));
312   EXPECT_TRUE(active_types.Has(syncer::APP_SETTINGS));
313   EXPECT_TRUE(active_types.Has(syncer::APPS));
314   EXPECT_TRUE(active_types.Has(syncer::ARC_PACKAGE));
315   EXPECT_TRUE(active_types.Has(syncer::OS_PREFERENCES));
316   EXPECT_TRUE(active_types.Has(syncer::OS_PRIORITY_PREFERENCES));
317   EXPECT_TRUE(active_types.Has(syncer::PRINTERS));
318   EXPECT_TRUE(active_types.Has(syncer::WEB_APPS));
319   EXPECT_TRUE(active_types.Has(syncer::WIFI_CONFIGURATIONS));
320 
321   // Verify that a few browser non-transport-mode types are not active.
322   EXPECT_FALSE(active_types.Has(syncer::BOOKMARKS));
323   EXPECT_FALSE(active_types.Has(syncer::SESSIONS));
324   EXPECT_FALSE(active_types.Has(syncer::TYPED_URLS));
325 }
326 
IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportOsSyncTest,OsTypesAreNotActiveWhenOsSyncIsOff)327 IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportOsSyncTest,
328                        OsTypesAreNotActiveWhenOsSyncIsOff) {
329   ASSERT_TRUE(chromeos::features::IsSplitSettingsSyncEnabled());
330 
331   // Setup clients but don't start syncing yet.
332   ASSERT_TRUE(SetupClients());
333   syncer::SyncService* service = GetSyncService(0);
334   syncer::SyncUserSettings* settings = service->GetUserSettings();
335 
336   // Simulate a user who leaves OS sync disabled but starts browser sync.
337   settings->SetOsSyncFeatureEnabled(false);
338   ASSERT_TRUE(GetClient(0)->SetupSync());
339   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
340   ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
341             GetSyncService(0)->GetTransportState());
342   ASSERT_TRUE(service->IsSyncFeatureActive());
343   ASSERT_FALSE(settings->IsOsSyncFeatureEnabled());
344 
345   // OS data types synced by the transport layer are not active.
346   syncer::ModelTypeSet active_types = service->GetActiveDataTypes();
347   EXPECT_FALSE(active_types.Has(syncer::APP_LIST));
348   EXPECT_FALSE(active_types.Has(syncer::APP_SETTINGS));
349   EXPECT_FALSE(active_types.Has(syncer::APPS));
350   EXPECT_FALSE(active_types.Has(syncer::ARC_PACKAGE));
351   EXPECT_FALSE(active_types.Has(syncer::OS_PREFERENCES));
352   EXPECT_FALSE(active_types.Has(syncer::OS_PRIORITY_PREFERENCES));
353   EXPECT_FALSE(active_types.Has(syncer::PRINTERS));
354   EXPECT_FALSE(active_types.Has(syncer::WEB_APPS));
355   EXPECT_FALSE(active_types.Has(syncer::WIFI_CONFIGURATIONS));
356 
357   // Browser non-transport-mode types are active.
358   EXPECT_TRUE(active_types.Has(syncer::BOOKMARKS));
359   EXPECT_TRUE(active_types.Has(syncer::SESSIONS));
360   EXPECT_TRUE(active_types.Has(syncer::TYPED_URLS));
361 }
362 #endif  // defined(OS_CHROMEOS)
363 
364 }  // namespace
365