Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / sync_setup_handler_unittest.cc
blob1af7560d64d78070c9457759b3b47d4086ff2b9a
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/webui/options/sync_setup_handler.h"
7 #include <vector>
9 #include "base/command_line.h"
10 #include "base/json/json_writer.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/stl_util.h"
14 #include "base/values.h"
15 #include "chrome/browser/signin/fake_signin_manager_builder.h"
16 #include "chrome/browser/signin/signin_error_controller_factory.h"
17 #include "chrome/browser/signin/signin_manager_factory.h"
18 #include "chrome/browser/sync/profile_sync_service_factory.h"
19 #include "chrome/browser/sync/profile_sync_service_mock.h"
20 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
21 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/pref_names.h"
24 #include "chrome/test/base/scoped_testing_local_state.h"
25 #include "chrome/test/base/testing_browser_process.h"
26 #include "chrome/test/base/testing_profile.h"
27 #include "components/signin/core/browser/fake_auth_status_provider.h"
28 #include "components/signin/core/browser/signin_manager.h"
29 #include "components/sync_driver/sync_prefs.h"
30 #include "content/public/browser/web_ui.h"
31 #include "content/public/test/test_browser_thread.h"
32 #include "content/public/test/test_browser_thread_bundle.h"
33 #include "content/public/test/test_web_ui.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "ui/base/layout.h"
37 using ::testing::_;
38 using ::testing::Mock;
39 using ::testing::Return;
40 using ::testing::ReturnRef;
41 using ::testing::Values;
43 typedef GoogleServiceAuthError AuthError;
45 namespace {
47 MATCHER_P(ModelTypeSetMatches, value, "") { return arg.Equals(value); }
49 const char kTestUser[] = "chrome.p13n.test@gmail.com";
51 // Returns a ModelTypeSet with all user selectable types set.
52 syncer::ModelTypeSet GetAllTypes() {
53 return syncer::UserSelectableTypes();
56 enum SyncAllDataConfig {
57 SYNC_ALL_DATA,
58 CHOOSE_WHAT_TO_SYNC,
59 SYNC_NOTHING
62 enum EncryptAllConfig {
63 ENCRYPT_ALL_DATA,
64 ENCRYPT_PASSWORDS
67 // Create a json-format string with the key/value pairs appropriate for a call
68 // to HandleConfigure(). If |extra_values| is non-null, then the values from
69 // the passed dictionary are added to the json.
70 std::string GetConfiguration(const base::DictionaryValue* extra_values,
71 SyncAllDataConfig sync_all,
72 syncer::ModelTypeSet types,
73 const std::string& passphrase,
74 EncryptAllConfig encrypt_all) {
75 base::DictionaryValue result;
76 if (extra_values)
77 result.MergeDictionary(extra_values);
78 result.SetBoolean("syncAllDataTypes", sync_all == SYNC_ALL_DATA);
79 result.SetBoolean("syncNothing", sync_all == SYNC_NOTHING);
80 result.SetBoolean("encryptAllData", encrypt_all == ENCRYPT_ALL_DATA);
81 result.SetBoolean("usePassphrase", !passphrase.empty());
82 if (!passphrase.empty())
83 result.SetString("passphrase", passphrase);
84 // Add all of our data types.
85 result.SetBoolean("appsSynced", types.Has(syncer::APPS));
86 result.SetBoolean("autofillSynced", types.Has(syncer::AUTOFILL));
87 result.SetBoolean("bookmarksSynced", types.Has(syncer::BOOKMARKS));
88 result.SetBoolean("extensionsSynced", types.Has(syncer::EXTENSIONS));
89 result.SetBoolean("passwordsSynced", types.Has(syncer::PASSWORDS));
90 result.SetBoolean("preferencesSynced", types.Has(syncer::PREFERENCES));
91 result.SetBoolean("tabsSynced", types.Has(syncer::PROXY_TABS));
92 result.SetBoolean("themesSynced", types.Has(syncer::THEMES));
93 result.SetBoolean("typedUrlsSynced", types.Has(syncer::TYPED_URLS));
94 result.SetBoolean("wifiCredentialsSynced",
95 types.Has(syncer::WIFI_CREDENTIALS));
96 std::string args;
97 base::JSONWriter::Write(result, &args);
98 return args;
101 // Checks whether the passed |dictionary| contains a |key| with the given
102 // |expected_value|. If |omit_if_false| is true, then the value should only
103 // be present if |expected_value| is true.
104 void CheckBool(const base::DictionaryValue* dictionary,
105 const std::string& key,
106 bool expected_value,
107 bool omit_if_false) {
108 if (omit_if_false && !expected_value) {
109 EXPECT_FALSE(dictionary->HasKey(key)) <<
110 "Did not expect to find value for " << key;
111 } else {
112 bool actual_value;
113 EXPECT_TRUE(dictionary->GetBoolean(key, &actual_value)) <<
114 "No value found for " << key;
115 EXPECT_EQ(expected_value, actual_value) <<
116 "Mismatch found for " << key;
120 void CheckBool(const base::DictionaryValue* dictionary,
121 const std::string& key,
122 bool expected_value) {
123 return CheckBool(dictionary, key, expected_value, false);
126 // Checks to make sure that the values stored in |dictionary| match the values
127 // expected by the showSyncSetupPage() JS function for a given set of data
128 // types.
129 void CheckConfigDataTypeArguments(const base::DictionaryValue* dictionary,
130 SyncAllDataConfig config,
131 syncer::ModelTypeSet types) {
132 CheckBool(dictionary, "syncAllDataTypes", config == SYNC_ALL_DATA);
133 CheckBool(dictionary, "syncNothing", config == SYNC_NOTHING);
134 CheckBool(dictionary, "appsSynced", types.Has(syncer::APPS));
135 CheckBool(dictionary, "autofillSynced", types.Has(syncer::AUTOFILL));
136 CheckBool(dictionary, "bookmarksSynced", types.Has(syncer::BOOKMARKS));
137 CheckBool(dictionary, "extensionsSynced", types.Has(syncer::EXTENSIONS));
138 CheckBool(dictionary, "passwordsSynced", types.Has(syncer::PASSWORDS));
139 CheckBool(dictionary, "preferencesSynced", types.Has(syncer::PREFERENCES));
140 CheckBool(dictionary, "tabsSynced", types.Has(syncer::PROXY_TABS));
141 CheckBool(dictionary, "themesSynced", types.Has(syncer::THEMES));
142 CheckBool(dictionary, "typedUrlsSynced", types.Has(syncer::TYPED_URLS));
143 CheckBool(dictionary, "wifiCredentialsSynced",
144 types.Has(syncer::WIFI_CREDENTIALS));
148 } // namespace
150 class TestingSyncSetupHandler : public SyncSetupHandler {
151 public:
152 TestingSyncSetupHandler(content::WebUI* web_ui, Profile* profile)
153 : profile_(profile) {
154 set_web_ui(web_ui);
156 ~TestingSyncSetupHandler() override { set_web_ui(NULL); }
158 void FocusUI() override {}
160 Profile* GetProfile() const override { return profile_; }
162 using SyncSetupHandler::is_configuring_sync;
164 private:
165 #if !defined(OS_CHROMEOS)
166 void DisplayGaiaLoginInNewTabOrWindow() override {}
167 #endif
169 // Weak pointer to parent profile.
170 Profile* profile_;
171 DISALLOW_COPY_AND_ASSIGN(TestingSyncSetupHandler);
174 // The boolean parameter indicates whether the test is run with ClientOAuth
175 // or not. The test parameter is a bool: whether or not to test with/
176 // /ClientLogin enabled or not.
177 class SyncSetupHandlerTest : public testing::Test {
178 public:
179 SyncSetupHandlerTest() : error_(GoogleServiceAuthError::NONE) {}
180 void SetUp() override {
181 error_ = GoogleServiceAuthError::AuthErrorNone();
183 TestingProfile::Builder builder;
184 builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
185 BuildFakeSigninManagerBase);
186 profile_ = builder.Build();
188 // Sign in the user.
189 mock_signin_ = static_cast<SigninManagerBase*>(
190 SigninManagerFactory::GetForProfile(profile_.get()));
191 std::string username = GetTestUser();
192 if (!username.empty())
193 mock_signin_->SetAuthenticatedAccountInfo(username, username);
195 mock_pss_ = static_cast<ProfileSyncServiceMock*>(
196 ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
197 profile_.get(),
198 ProfileSyncServiceMock::BuildMockProfileSyncService));
199 EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_));
200 ON_CALL(*mock_pss_, GetPassphraseType()).WillByDefault(
201 Return(syncer::IMPLICIT_PASSPHRASE));
202 ON_CALL(*mock_pss_, GetPassphraseTime()).WillByDefault(
203 Return(base::Time()));
204 ON_CALL(*mock_pss_, GetExplicitPassphraseTime()).WillByDefault(
205 Return(base::Time()));
206 ON_CALL(*mock_pss_, GetRegisteredDataTypes())
207 .WillByDefault(Return(syncer::ModelTypeSet()));
209 mock_pss_->Initialize();
211 handler_.reset(new TestingSyncSetupHandler(&web_ui_, profile_.get()));
214 // Setup the expectations for calls made when displaying the config page.
215 void SetDefaultExpectationsForConfigPage() {
216 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
217 EXPECT_CALL(*mock_pss_, GetRegisteredDataTypes()).
218 WillRepeatedly(Return(GetAllTypes()));
219 EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()).
220 WillRepeatedly(Return(GetAllTypes()));
221 EXPECT_CALL(*mock_pss_, GetActiveDataTypes()).
222 WillRepeatedly(Return(GetAllTypes()));
223 EXPECT_CALL(*mock_pss_, EncryptEverythingAllowed()).
224 WillRepeatedly(Return(true));
225 EXPECT_CALL(*mock_pss_, EncryptEverythingEnabled()).
226 WillRepeatedly(Return(false));
229 void SetupInitializedProfileSyncService() {
230 // An initialized ProfileSyncService will have already completed sync setup
231 // and will have an initialized sync backend.
232 ASSERT_TRUE(mock_signin_->IsInitialized());
233 EXPECT_CALL(*mock_pss_, backend_initialized()).WillRepeatedly(Return(true));
236 void ExpectConfig() {
237 ASSERT_EQ(1U, web_ui_.call_data().size());
238 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
239 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
240 std::string page;
241 ASSERT_TRUE(data.arg1()->GetAsString(&page));
242 EXPECT_EQ(page, "configure");
245 void ExpectDone() {
246 ASSERT_EQ(1U, web_ui_.call_data().size());
247 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
248 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
249 std::string page;
250 ASSERT_TRUE(data.arg1()->GetAsString(&page));
251 EXPECT_EQ(page, "done");
254 void ExpectSpinnerAndClose() {
255 // We expect a call to SyncSetupOverlay.showSyncSetupPage.
256 EXPECT_EQ(1U, web_ui_.call_data().size());
257 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
258 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
260 std::string page;
261 ASSERT_TRUE(data.arg1()->GetAsString(&page));
262 EXPECT_EQ(page, "spinner");
263 // Cancelling the spinner dialog will cause CloseSyncSetup().
264 handler_->CloseSyncSetup();
265 EXPECT_EQ(NULL,
266 LoginUIServiceFactory::GetForProfile(
267 profile_.get())->current_login_ui());
270 // It's difficult to notify sync listeners when using a ProfileSyncServiceMock
271 // so this helper routine dispatches an OnStateChanged() notification to the
272 // SyncStartupTracker.
273 void NotifySyncListeners() {
274 if (handler_->sync_startup_tracker_)
275 handler_->sync_startup_tracker_->OnStateChanged();
278 virtual std::string GetTestUser() {
279 return std::string(kTestUser);
282 content::TestBrowserThreadBundle thread_bundle_;
283 scoped_ptr<Profile> profile_;
284 ProfileSyncServiceMock* mock_pss_;
285 GoogleServiceAuthError error_;
286 SigninManagerBase* mock_signin_;
287 content::TestWebUI web_ui_;
288 scoped_ptr<TestingSyncSetupHandler> handler_;
291 class SyncSetupHandlerFirstSigninTest : public SyncSetupHandlerTest {
292 std::string GetTestUser() override { return std::string(); }
295 TEST_F(SyncSetupHandlerTest, Basic) {
298 #if !defined(OS_CHROMEOS)
299 TEST_F(SyncSetupHandlerFirstSigninTest, DisplayBasicLogin) {
300 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
301 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
302 .WillRepeatedly(Return(false));
303 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
304 .WillRepeatedly(Return(false));
305 // Ensure that the user is not signed in before calling |HandleStartSignin()|.
306 SigninManager* manager = static_cast<SigninManager*>(mock_signin_);
307 manager->SignOut(signin_metrics::SIGNOUT_TEST);
308 handler_->HandleStartSignin(NULL);
310 // Sync setup hands off control to the gaia login tab.
311 EXPECT_EQ(NULL,
312 LoginUIServiceFactory::GetForProfile(
313 profile_.get())->current_login_ui());
315 ASSERT_FALSE(handler_->is_configuring_sync());
317 handler_->CloseSyncSetup();
318 EXPECT_EQ(NULL,
319 LoginUIServiceFactory::GetForProfile(
320 profile_.get())->current_login_ui());
323 TEST_F(SyncSetupHandlerTest, ShowSyncSetupWhenNotSignedIn) {
324 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
325 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
326 .WillRepeatedly(Return(false));
327 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
328 .WillRepeatedly(Return(false));
329 handler_->HandleShowSetupUI(NULL);
331 // We expect a call to SyncSetupOverlay.showSyncSetupPage.
332 ASSERT_EQ(1U, web_ui_.call_data().size());
333 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
334 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
336 ASSERT_FALSE(handler_->is_configuring_sync());
337 EXPECT_EQ(NULL,
338 LoginUIServiceFactory::GetForProfile(
339 profile_.get())->current_login_ui());
341 #endif // !defined(OS_CHROMEOS)
343 // Verifies that the sync setup is terminated correctly when the
344 // sync is disabled.
345 TEST_F(SyncSetupHandlerTest, HandleSetupUIWhenSyncDisabled) {
346 EXPECT_CALL(*mock_pss_, IsManaged()).WillRepeatedly(Return(true));
347 handler_->HandleShowSetupUI(NULL);
349 // Sync setup is closed when sync is disabled.
350 EXPECT_EQ(NULL,
351 LoginUIServiceFactory::GetForProfile(
352 profile_.get())->current_login_ui());
353 ASSERT_FALSE(handler_->is_configuring_sync());
356 // Verifies that the handler correctly handles a cancellation when
357 // it is displaying the spinner to the user.
358 TEST_F(SyncSetupHandlerTest, DisplayConfigureWithBackendDisabledAndCancel) {
359 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
360 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
361 .WillRepeatedly(Return(true));
362 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
363 .WillRepeatedly(Return(false));
364 error_ = GoogleServiceAuthError::AuthErrorNone();
365 EXPECT_CALL(*mock_pss_, backend_initialized()).WillRepeatedly(Return(false));
367 // We're simulating a user setting up sync, which would cause the backend to
368 // kick off initialization, but not download user data types. The sync
369 // backend will try to download control data types (e.g encryption info), but
370 // that won't finish for this test as we're simulating cancelling while the
371 // spinner is showing.
372 handler_->HandleShowSetupUI(NULL);
374 EXPECT_EQ(handler_.get(),
375 LoginUIServiceFactory::GetForProfile(
376 profile_.get())->current_login_ui());
378 ExpectSpinnerAndClose();
381 // Verifies that the handler correctly transitions from showing the spinner
382 // to showing a configuration page when sync setup completes successfully.
383 TEST_F(SyncSetupHandlerTest,
384 DisplayConfigureWithBackendDisabledAndSyncStartupCompleted) {
385 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
386 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
387 .WillRepeatedly(Return(true));
388 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
389 .WillRepeatedly(Return(false));
390 error_ = GoogleServiceAuthError::AuthErrorNone();
391 // Sync backend is stopped initially, and will start up.
392 EXPECT_CALL(*mock_pss_, backend_initialized())
393 .WillRepeatedly(Return(false));
394 SetDefaultExpectationsForConfigPage();
396 handler_->OpenSyncSetup();
398 // We expect a call to SyncSetupOverlay.showSyncSetupPage.
399 EXPECT_EQ(1U, web_ui_.call_data().size());
401 const content::TestWebUI::CallData& data0 = *web_ui_.call_data()[0];
402 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data0.function_name());
403 std::string page;
404 ASSERT_TRUE(data0.arg1()->GetAsString(&page));
405 EXPECT_EQ(page, "spinner");
407 Mock::VerifyAndClearExpectations(mock_pss_);
408 // Now, act as if the ProfileSyncService has started up.
409 SetDefaultExpectationsForConfigPage();
410 EXPECT_CALL(*mock_pss_, backend_initialized())
411 .WillRepeatedly(Return(true));
412 error_ = GoogleServiceAuthError::AuthErrorNone();
413 EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_));
414 NotifySyncListeners();
416 // We expect a second call to SyncSetupOverlay.showSyncSetupPage.
417 EXPECT_EQ(2U, web_ui_.call_data().size());
418 const content::TestWebUI::CallData& data1 = *web_ui_.call_data().back();
419 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data1.function_name());
420 ASSERT_TRUE(data1.arg1()->GetAsString(&page));
421 EXPECT_EQ(page, "configure");
422 const base::DictionaryValue* dictionary = nullptr;
423 ASSERT_TRUE(data1.arg2()->GetAsDictionary(&dictionary));
424 CheckBool(dictionary, "passphraseFailed", false);
425 CheckBool(dictionary, "syncAllDataTypes", true);
426 CheckBool(dictionary, "encryptAllDataAllowed", true);
427 CheckBool(dictionary, "encryptAllData", false);
428 CheckBool(dictionary, "usePassphrase", false);
431 // Verifies the case where the user cancels after the sync backend has
432 // initialized (meaning it already transitioned from the spinner to a proper
433 // configuration page, tested by
434 // DisplayConfigureWithBackendDisabledAndSigninSuccess), but before the user
435 // before the user has continued on.
436 TEST_F(SyncSetupHandlerTest,
437 DisplayConfigureWithBackendDisabledAndCancelAfterSigninSuccess) {
438 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
439 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
440 .WillRepeatedly(Return(true));
441 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
442 .WillRepeatedly(Return(false));
443 error_ = GoogleServiceAuthError::AuthErrorNone();
444 EXPECT_CALL(*mock_pss_, backend_initialized())
445 .WillOnce(Return(false))
446 .WillRepeatedly(Return(true));
447 SetDefaultExpectationsForConfigPage();
448 handler_->OpenSyncSetup();
450 // It's important to tell sync the user cancelled the setup flow before we
451 // tell it we're through with the setup progress.
452 testing::InSequence seq;
453 EXPECT_CALL(*mock_pss_, RequestStop(ProfileSyncService::CLEAR_DATA));
454 EXPECT_CALL(*mock_pss_, SetSetupInProgress(false));
456 handler_->CloseSyncSetup();
457 EXPECT_EQ(NULL,
458 LoginUIServiceFactory::GetForProfile(
459 profile_.get())->current_login_ui());
462 TEST_F(SyncSetupHandlerTest,
463 DisplayConfigureWithBackendDisabledAndSigninFailed) {
464 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
465 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
466 .WillRepeatedly(Return(true));
467 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
468 .WillRepeatedly(Return(false));
469 error_ = GoogleServiceAuthError::AuthErrorNone();
470 EXPECT_CALL(*mock_pss_, backend_initialized()).WillRepeatedly(Return(false));
472 handler_->OpenSyncSetup();
473 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
474 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
475 std::string page;
476 ASSERT_TRUE(data.arg1()->GetAsString(&page));
477 EXPECT_EQ(page, "spinner");
478 Mock::VerifyAndClearExpectations(mock_pss_);
479 error_ = GoogleServiceAuthError(
480 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
481 EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_));
482 NotifySyncListeners();
484 // On failure, the dialog will be closed.
485 EXPECT_EQ(NULL,
486 LoginUIServiceFactory::GetForProfile(
487 profile_.get())->current_login_ui());
490 #if !defined(OS_CHROMEOS)
492 class SyncSetupHandlerNonCrosTest : public SyncSetupHandlerTest {
493 public:
494 SyncSetupHandlerNonCrosTest() {}
497 TEST_F(SyncSetupHandlerNonCrosTest, HandleGaiaAuthFailure) {
498 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
499 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
500 .WillRepeatedly(Return(false));
501 EXPECT_CALL(*mock_pss_, HasUnrecoverableError())
502 .WillRepeatedly(Return(false));
503 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
504 .WillRepeatedly(Return(false));
505 // Open the web UI.
506 handler_->OpenSyncSetup();
508 ASSERT_FALSE(handler_->is_configuring_sync());
511 // TODO(kochi): We need equivalent tests for ChromeOS.
512 TEST_F(SyncSetupHandlerNonCrosTest, UnrecoverableErrorInitializingSync) {
513 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
514 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
515 .WillRepeatedly(Return(false));
516 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
517 .WillRepeatedly(Return(false));
518 // Open the web UI.
519 handler_->OpenSyncSetup();
521 ASSERT_FALSE(handler_->is_configuring_sync());
524 TEST_F(SyncSetupHandlerNonCrosTest, GaiaErrorInitializingSync) {
525 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
526 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
527 .WillRepeatedly(Return(false));
528 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
529 .WillRepeatedly(Return(false));
530 // Open the web UI.
531 handler_->OpenSyncSetup();
533 ASSERT_FALSE(handler_->is_configuring_sync());
536 #endif // #if !defined(OS_CHROMEOS)
538 TEST_F(SyncSetupHandlerTest, TestSyncEverything) {
539 std::string args = GetConfiguration(
540 NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
541 base::ListValue list_args;
542 list_args.Append(new base::StringValue(args));
543 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
544 .WillRepeatedly(Return(false));
545 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
546 .WillRepeatedly(Return(false));
547 SetupInitializedProfileSyncService();
548 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
549 handler_->HandleConfigure(&list_args);
551 // Ensure that we navigated to the "done" state since we don't need a
552 // passphrase.
553 ExpectDone();
556 TEST_F(SyncSetupHandlerTest, TestSyncNothing) {
557 std::string args = GetConfiguration(
558 NULL, SYNC_NOTHING, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
559 base::ListValue list_args;
560 list_args.Append(new base::StringValue(args));
561 EXPECT_CALL(*mock_pss_, RequestStop(ProfileSyncService::CLEAR_DATA));
562 SetupInitializedProfileSyncService();
563 handler_->HandleConfigure(&list_args);
565 // We expect a call to SyncSetupOverlay.showSyncSetupPage.
566 ASSERT_EQ(1U, web_ui_.call_data().size());
567 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
568 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
571 TEST_F(SyncSetupHandlerTest, TurnOnEncryptAll) {
572 std::string args = GetConfiguration(
573 NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_ALL_DATA);
574 base::ListValue list_args;
575 list_args.Append(new base::StringValue(args));
576 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
577 .WillRepeatedly(Return(false));
578 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
579 .WillRepeatedly(Return(false));
580 EXPECT_CALL(*mock_pss_, EncryptEverythingAllowed())
581 .WillRepeatedly(Return(true));
582 SetupInitializedProfileSyncService();
583 EXPECT_CALL(*mock_pss_, EnableEncryptEverything());
584 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
585 handler_->HandleConfigure(&list_args);
587 // Ensure that we navigated to the "done" state since we don't need a
588 // passphrase.
589 ExpectDone();
592 TEST_F(SyncSetupHandlerTest, TestPassphraseStillRequired) {
593 std::string args = GetConfiguration(
594 NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
595 base::ListValue list_args;
596 list_args.Append(new base::StringValue(args));
597 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
598 .WillRepeatedly(Return(true));
599 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
600 .WillRepeatedly(Return(true));
601 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
602 .WillRepeatedly(Return(false));
603 SetupInitializedProfileSyncService();
604 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
605 SetDefaultExpectationsForConfigPage();
607 // We should navigate back to the configure page since we need a passphrase.
608 handler_->HandleConfigure(&list_args);
610 ExpectConfig();
613 TEST_F(SyncSetupHandlerTest, SuccessfullySetPassphrase) {
614 base::DictionaryValue dict;
615 dict.SetBoolean("isGooglePassphrase", true);
616 std::string args = GetConfiguration(&dict,
617 SYNC_ALL_DATA,
618 GetAllTypes(),
619 "gaiaPassphrase",
620 ENCRYPT_PASSWORDS);
621 base::ListValue list_args;
622 list_args.Append(new base::StringValue(args));
623 // Act as if an encryption passphrase is required the first time, then never
624 // again after that.
625 EXPECT_CALL(*mock_pss_, IsPassphraseRequired()).WillOnce(Return(true));
626 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
627 .WillRepeatedly(Return(false));
628 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
629 .WillRepeatedly(Return(false));
630 SetupInitializedProfileSyncService();
631 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
632 EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("gaiaPassphrase")).
633 WillOnce(Return(true));
635 handler_->HandleConfigure(&list_args);
636 // We should navigate to "done" page since we finished configuring.
637 ExpectDone();
640 TEST_F(SyncSetupHandlerTest, SelectCustomEncryption) {
641 base::DictionaryValue dict;
642 dict.SetBoolean("isGooglePassphrase", false);
643 std::string args = GetConfiguration(&dict,
644 SYNC_ALL_DATA,
645 GetAllTypes(),
646 "custom_passphrase",
647 ENCRYPT_PASSWORDS);
648 base::ListValue list_args;
649 list_args.Append(new base::StringValue(args));
650 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
651 .WillRepeatedly(Return(false));
652 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
653 .WillRepeatedly(Return(false));
654 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
655 .WillRepeatedly(Return(false));
656 SetupInitializedProfileSyncService();
657 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
658 EXPECT_CALL(*mock_pss_,
659 SetEncryptionPassphrase("custom_passphrase",
660 ProfileSyncService::EXPLICIT));
662 handler_->HandleConfigure(&list_args);
663 // We should navigate to "done" page since we finished configuring.
664 ExpectDone();
667 TEST_F(SyncSetupHandlerTest, UnsuccessfullySetPassphrase) {
668 base::DictionaryValue dict;
669 dict.SetBoolean("isGooglePassphrase", true);
670 std::string args = GetConfiguration(&dict,
671 SYNC_ALL_DATA,
672 GetAllTypes(),
673 "invalid_passphrase",
674 ENCRYPT_PASSWORDS);
675 base::ListValue list_args;
676 list_args.Append(new base::StringValue(args));
677 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
678 .WillRepeatedly(Return(true));
679 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
680 .WillRepeatedly(Return(true));
681 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
682 .WillRepeatedly(Return(false));
683 SetupInitializedProfileSyncService();
684 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
685 EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("invalid_passphrase")).
686 WillOnce(Return(false));
688 SetDefaultExpectationsForConfigPage();
689 // We should navigate back to the configure page since we need a passphrase.
690 handler_->HandleConfigure(&list_args);
692 ExpectConfig();
694 // Make sure we display an error message to the user due to the failed
695 // passphrase.
696 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
697 const base::DictionaryValue* dictionary = nullptr;
698 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
699 CheckBool(dictionary, "passphraseFailed", true);
702 // Walks through each user selectable type, and tries to sync just that single
703 // data type.
704 TEST_F(SyncSetupHandlerTest, TestSyncIndividualTypes) {
705 syncer::ModelTypeSet user_selectable_types = GetAllTypes();
706 syncer::ModelTypeSet::Iterator it;
707 for (it = user_selectable_types.First(); it.Good(); it.Inc()) {
708 syncer::ModelTypeSet type_to_set;
709 type_to_set.Put(it.Get());
710 std::string args = GetConfiguration(NULL,
711 CHOOSE_WHAT_TO_SYNC,
712 type_to_set,
713 std::string(),
714 ENCRYPT_PASSWORDS);
715 base::ListValue list_args;
716 list_args.Append(new base::StringValue(args));
717 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
718 .WillRepeatedly(Return(false));
719 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
720 .WillRepeatedly(Return(false));
721 SetupInitializedProfileSyncService();
722 EXPECT_CALL(*mock_pss_,
723 OnUserChoseDatatypes(false, ModelTypeSetMatches(type_to_set)));
724 handler_->HandleConfigure(&list_args);
726 ExpectDone();
727 Mock::VerifyAndClearExpectations(mock_pss_);
728 web_ui_.ClearTrackedCalls();
732 TEST_F(SyncSetupHandlerTest, TestSyncAllManually) {
733 std::string args = GetConfiguration(NULL,
734 CHOOSE_WHAT_TO_SYNC,
735 GetAllTypes(),
736 std::string(),
737 ENCRYPT_PASSWORDS);
738 base::ListValue list_args;
739 list_args.Append(new base::StringValue(args));
740 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
741 .WillRepeatedly(Return(false));
742 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
743 .WillRepeatedly(Return(false));
744 SetupInitializedProfileSyncService();
745 EXPECT_CALL(*mock_pss_,
746 OnUserChoseDatatypes(false, ModelTypeSetMatches(GetAllTypes())));
747 handler_->HandleConfigure(&list_args);
749 ExpectDone();
752 TEST_F(SyncSetupHandlerTest, ShowSyncSetup) {
753 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
754 .WillRepeatedly(Return(false));
755 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
756 .WillRepeatedly(Return(false));
757 SetupInitializedProfileSyncService();
758 // This should display the sync setup dialog (not login).
759 SetDefaultExpectationsForConfigPage();
760 handler_->OpenSyncSetup();
762 ExpectConfig();
765 // We do not display signin on chromeos in the case of auth error.
766 TEST_F(SyncSetupHandlerTest, ShowSigninOnAuthError) {
767 // Initialize the system to a signed in state, but with an auth error.
768 error_ = GoogleServiceAuthError(
769 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
771 SetupInitializedProfileSyncService();
772 mock_signin_->SetAuthenticatedAccountInfo(kTestUser, kTestUser);
773 FakeAuthStatusProvider provider(
774 SigninErrorControllerFactory::GetForProfile(profile_.get()));
775 provider.SetAuthError(kTestUser, error_);
776 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
777 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
778 .WillRepeatedly(Return(true));
779 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
780 .WillRepeatedly(Return(false));
781 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
782 .WillRepeatedly(Return(false));
783 EXPECT_CALL(*mock_pss_, backend_initialized()).WillRepeatedly(Return(false));
785 #if defined(OS_CHROMEOS)
786 // On ChromeOS, auth errors are ignored - instead we just try to start the
787 // sync backend (which will fail due to the auth error). This should only
788 // happen if the user manually navigates to chrome://settings/syncSetup -
789 // clicking on the button in the UI will sign the user out rather than
790 // displaying a spinner. Should be no visible UI on ChromeOS in this case.
791 EXPECT_EQ(NULL, LoginUIServiceFactory::GetForProfile(
792 profile_.get())->current_login_ui());
793 #else
795 // On ChromeOS, this should display the spinner while we try to startup the
796 // sync backend, and on desktop this displays the login dialog.
797 handler_->OpenSyncSetup();
799 // Sync setup is closed when re-auth is in progress.
800 EXPECT_EQ(NULL,
801 LoginUIServiceFactory::GetForProfile(
802 profile_.get())->current_login_ui());
804 ASSERT_FALSE(handler_->is_configuring_sync());
805 #endif
808 TEST_F(SyncSetupHandlerTest, ShowSetupSyncEverything) {
809 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
810 .WillRepeatedly(Return(false));
811 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
812 .WillRepeatedly(Return(false));
813 SetupInitializedProfileSyncService();
814 SetDefaultExpectationsForConfigPage();
815 // This should display the sync setup dialog (not login).
816 handler_->OpenSyncSetup();
818 ExpectConfig();
819 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
820 const base::DictionaryValue* dictionary = nullptr;
821 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
822 CheckBool(dictionary, "syncAllDataTypes", true);
823 CheckBool(dictionary, "appsRegistered", true);
824 CheckBool(dictionary, "autofillRegistered", true);
825 CheckBool(dictionary, "bookmarksRegistered", true);
826 CheckBool(dictionary, "extensionsRegistered", true);
827 CheckBool(dictionary, "passwordsRegistered", true);
828 CheckBool(dictionary, "preferencesRegistered", true);
829 CheckBool(dictionary, "wifiCredentialsRegistered", true);
830 CheckBool(dictionary, "tabsRegistered", true);
831 CheckBool(dictionary, "themesRegistered", true);
832 CheckBool(dictionary, "typedUrlsRegistered", true);
833 CheckBool(dictionary, "showPassphrase", false);
834 CheckBool(dictionary, "usePassphrase", false);
835 CheckBool(dictionary, "passphraseFailed", false);
836 CheckBool(dictionary, "encryptAllData", false);
837 CheckConfigDataTypeArguments(dictionary, SYNC_ALL_DATA, GetAllTypes());
840 TEST_F(SyncSetupHandlerTest, ShowSetupManuallySyncAll) {
841 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
842 .WillRepeatedly(Return(false));
843 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
844 .WillRepeatedly(Return(false));
845 SetupInitializedProfileSyncService();
846 sync_driver::SyncPrefs sync_prefs(profile_->GetPrefs());
847 sync_prefs.SetKeepEverythingSynced(false);
848 SetDefaultExpectationsForConfigPage();
849 // This should display the sync setup dialog (not login).
850 handler_->OpenSyncSetup();
852 ExpectConfig();
853 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
854 const base::DictionaryValue* dictionary = nullptr;
855 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
856 CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, GetAllTypes());
859 TEST_F(SyncSetupHandlerTest, ShowSetupSyncForAllTypesIndividually) {
860 syncer::ModelTypeSet user_selectable_types = GetAllTypes();
861 syncer::ModelTypeSet::Iterator it;
862 for (it = user_selectable_types.First(); it.Good(); it.Inc()) {
863 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
864 .WillRepeatedly(Return(false));
865 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
866 .WillRepeatedly(Return(false));
867 SetupInitializedProfileSyncService();
868 sync_driver::SyncPrefs sync_prefs(profile_->GetPrefs());
869 sync_prefs.SetKeepEverythingSynced(false);
870 SetDefaultExpectationsForConfigPage();
871 syncer::ModelTypeSet types;
872 types.Put(it.Get());
873 EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()).
874 WillRepeatedly(Return(types));
876 // This should display the sync setup dialog (not login).
877 handler_->OpenSyncSetup();
879 ExpectConfig();
880 // Close the config overlay.
881 LoginUIServiceFactory::GetForProfile(profile_.get())->LoginUIClosed(
882 handler_.get());
883 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
884 const base::DictionaryValue* dictionary = nullptr;
885 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
886 CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, types);
887 Mock::VerifyAndClearExpectations(mock_pss_);
888 // Clean up so we can loop back to display the dialog again.
889 web_ui_.ClearTrackedCalls();
893 TEST_F(SyncSetupHandlerTest, ShowSetupGaiaPassphraseRequired) {
894 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
895 .WillRepeatedly(Return(true));
896 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
897 .WillRepeatedly(Return(false));
898 SetupInitializedProfileSyncService();
899 SetDefaultExpectationsForConfigPage();
901 // This should display the sync setup dialog (not login).
902 handler_->OpenSyncSetup();
904 ExpectConfig();
905 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
906 const base::DictionaryValue* dictionary = nullptr;
907 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
908 CheckBool(dictionary, "showPassphrase", true);
909 CheckBool(dictionary, "usePassphrase", false);
910 CheckBool(dictionary, "passphraseFailed", false);
913 TEST_F(SyncSetupHandlerTest, ShowSetupCustomPassphraseRequired) {
914 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
915 .WillRepeatedly(Return(true));
916 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
917 .WillRepeatedly(Return(true));
918 EXPECT_CALL(*mock_pss_, GetPassphraseType())
919 .WillRepeatedly(Return(syncer::CUSTOM_PASSPHRASE));
920 SetupInitializedProfileSyncService();
921 SetDefaultExpectationsForConfigPage();
923 // This should display the sync setup dialog (not login).
924 handler_->OpenSyncSetup();
926 ExpectConfig();
927 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
928 const base::DictionaryValue* dictionary = nullptr;
929 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
930 CheckBool(dictionary, "showPassphrase", true);
931 CheckBool(dictionary, "usePassphrase", true);
932 CheckBool(dictionary, "passphraseFailed", false);
935 TEST_F(SyncSetupHandlerTest, ShowSetupEncryptAll) {
936 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
937 .WillRepeatedly(Return(false));
938 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
939 .WillRepeatedly(Return(false));
940 SetupInitializedProfileSyncService();
941 SetDefaultExpectationsForConfigPage();
942 EXPECT_CALL(*mock_pss_, EncryptEverythingEnabled()).
943 WillRepeatedly(Return(true));
945 // This should display the sync setup dialog (not login).
946 handler_->OpenSyncSetup();
948 ExpectConfig();
949 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
950 const base::DictionaryValue* dictionary = nullptr;
951 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
952 CheckBool(dictionary, "encryptAllData", true);
955 TEST_F(SyncSetupHandlerTest, ShowSetupEncryptAllDisallowed) {
956 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
957 .WillRepeatedly(Return(false));
958 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
959 .WillRepeatedly(Return(false));
960 SetupInitializedProfileSyncService();
961 SetDefaultExpectationsForConfigPage();
962 EXPECT_CALL(*mock_pss_, EncryptEverythingAllowed()).
963 WillRepeatedly(Return(false));
965 // This should display the sync setup dialog (not login).
966 handler_->OpenSyncSetup();
968 ExpectConfig();
969 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
970 const base::DictionaryValue* dictionary = nullptr;
971 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
972 CheckBool(dictionary, "encryptAllData", false);
973 CheckBool(dictionary, "encryptAllDataAllowed", false);
976 TEST_F(SyncSetupHandlerTest, TurnOnEncryptAllDisallowed) {
977 std::string args = GetConfiguration(
978 NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_ALL_DATA);
979 base::ListValue list_args;
980 list_args.Append(new base::StringValue(args));
981 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
982 .WillRepeatedly(Return(false));
983 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
984 .WillRepeatedly(Return(false));
985 SetupInitializedProfileSyncService();
986 EXPECT_CALL(*mock_pss_, EncryptEverythingAllowed()).
987 WillRepeatedly(Return(false));
988 EXPECT_CALL(*mock_pss_, EnableEncryptEverything()).Times(0);
989 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
990 handler_->HandleConfigure(&list_args);
992 // Ensure that we navigated to the "done" state since we don't need a
993 // passphrase.
994 ExpectDone();