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