Vectorize sad tab image.
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / sync_setup_handler_unittest.cc
blob233d473d59d94097c5ca65ddb479caca04d0d7cd
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_, IsEncryptEverythingAllowed())
224 .WillRepeatedly(Return(true));
225 EXPECT_CALL(*mock_pss_, IsEncryptEverythingEnabled())
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_, IsBackendInitialized())
234 .WillRepeatedly(Return(true));
237 void ExpectConfig() {
238 ASSERT_EQ(1U, web_ui_.call_data().size());
239 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
240 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
241 std::string page;
242 ASSERT_TRUE(data.arg1()->GetAsString(&page));
243 EXPECT_EQ(page, "configure");
246 void ExpectDone() {
247 ASSERT_EQ(1U, web_ui_.call_data().size());
248 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
249 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
250 std::string page;
251 ASSERT_TRUE(data.arg1()->GetAsString(&page));
252 EXPECT_EQ(page, "done");
255 void ExpectSpinnerAndClose() {
256 // We expect a call to SyncSetupOverlay.showSyncSetupPage.
257 EXPECT_EQ(1U, web_ui_.call_data().size());
258 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
259 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
261 std::string page;
262 ASSERT_TRUE(data.arg1()->GetAsString(&page));
263 EXPECT_EQ(page, "spinner");
264 // Cancelling the spinner dialog will cause CloseSyncSetup().
265 handler_->CloseSyncSetup();
266 EXPECT_EQ(NULL,
267 LoginUIServiceFactory::GetForProfile(
268 profile_.get())->current_login_ui());
271 // It's difficult to notify sync listeners when using a ProfileSyncServiceMock
272 // so this helper routine dispatches an OnStateChanged() notification to the
273 // SyncStartupTracker.
274 void NotifySyncListeners() {
275 if (handler_->sync_startup_tracker_)
276 handler_->sync_startup_tracker_->OnStateChanged();
279 virtual std::string GetTestUser() {
280 return std::string(kTestUser);
283 content::TestBrowserThreadBundle thread_bundle_;
284 scoped_ptr<Profile> profile_;
285 ProfileSyncServiceMock* mock_pss_;
286 GoogleServiceAuthError error_;
287 SigninManagerBase* mock_signin_;
288 content::TestWebUI web_ui_;
289 scoped_ptr<TestingSyncSetupHandler> handler_;
292 class SyncSetupHandlerFirstSigninTest : public SyncSetupHandlerTest {
293 std::string GetTestUser() override { return std::string(); }
296 TEST_F(SyncSetupHandlerTest, Basic) {
299 #if !defined(OS_CHROMEOS)
300 TEST_F(SyncSetupHandlerFirstSigninTest, DisplayBasicLogin) {
301 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
302 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
303 .WillRepeatedly(Return(false));
304 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
305 .WillRepeatedly(Return(false));
306 // Ensure that the user is not signed in before calling |HandleStartSignin()|.
307 SigninManager* manager = static_cast<SigninManager*>(mock_signin_);
308 manager->SignOut(signin_metrics::SIGNOUT_TEST);
309 handler_->HandleStartSignin(NULL);
311 // Sync setup hands off control to the gaia login tab.
312 EXPECT_EQ(NULL,
313 LoginUIServiceFactory::GetForProfile(
314 profile_.get())->current_login_ui());
316 ASSERT_FALSE(handler_->is_configuring_sync());
318 handler_->CloseSyncSetup();
319 EXPECT_EQ(NULL,
320 LoginUIServiceFactory::GetForProfile(
321 profile_.get())->current_login_ui());
324 TEST_F(SyncSetupHandlerTest, ShowSyncSetupWhenNotSignedIn) {
325 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
326 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
327 .WillRepeatedly(Return(false));
328 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
329 .WillRepeatedly(Return(false));
330 handler_->HandleShowSetupUI(NULL);
332 // We expect a call to SyncSetupOverlay.showSyncSetupPage.
333 ASSERT_EQ(1U, web_ui_.call_data().size());
334 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
335 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
337 ASSERT_FALSE(handler_->is_configuring_sync());
338 EXPECT_EQ(NULL,
339 LoginUIServiceFactory::GetForProfile(
340 profile_.get())->current_login_ui());
342 #endif // !defined(OS_CHROMEOS)
344 // Verifies that the sync setup is terminated correctly when the
345 // sync is disabled.
346 TEST_F(SyncSetupHandlerTest, HandleSetupUIWhenSyncDisabled) {
347 EXPECT_CALL(*mock_pss_, IsManaged()).WillRepeatedly(Return(true));
348 handler_->HandleShowSetupUI(NULL);
350 // Sync setup is closed when sync is disabled.
351 EXPECT_EQ(NULL,
352 LoginUIServiceFactory::GetForProfile(
353 profile_.get())->current_login_ui());
354 ASSERT_FALSE(handler_->is_configuring_sync());
357 // Verifies that the handler correctly handles a cancellation when
358 // it is displaying the spinner to the user.
359 TEST_F(SyncSetupHandlerTest, DisplayConfigureWithBackendDisabledAndCancel) {
360 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
361 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
362 .WillRepeatedly(Return(true));
363 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
364 .WillRepeatedly(Return(false));
365 error_ = GoogleServiceAuthError::AuthErrorNone();
366 EXPECT_CALL(*mock_pss_, IsBackendInitialized()).WillRepeatedly(Return(false));
368 // We're simulating a user setting up sync, which would cause the backend to
369 // kick off initialization, but not download user data types. The sync
370 // backend will try to download control data types (e.g encryption info), but
371 // that won't finish for this test as we're simulating cancelling while the
372 // spinner is showing.
373 handler_->HandleShowSetupUI(NULL);
375 EXPECT_EQ(handler_.get(),
376 LoginUIServiceFactory::GetForProfile(
377 profile_.get())->current_login_ui());
379 ExpectSpinnerAndClose();
382 // Verifies that the handler correctly transitions from showing the spinner
383 // to showing a configuration page when sync setup completes successfully.
384 TEST_F(SyncSetupHandlerTest,
385 DisplayConfigureWithBackendDisabledAndSyncStartupCompleted) {
386 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
387 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
388 .WillRepeatedly(Return(true));
389 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
390 .WillRepeatedly(Return(false));
391 error_ = GoogleServiceAuthError::AuthErrorNone();
392 // Sync backend is stopped initially, and will start up.
393 EXPECT_CALL(*mock_pss_, IsBackendInitialized()).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_, IsBackendInitialized()).WillRepeatedly(Return(true));
411 error_ = GoogleServiceAuthError::AuthErrorNone();
412 EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_));
413 NotifySyncListeners();
415 // We expect a second call to SyncSetupOverlay.showSyncSetupPage.
416 EXPECT_EQ(2U, web_ui_.call_data().size());
417 const content::TestWebUI::CallData& data1 = *web_ui_.call_data().back();
418 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data1.function_name());
419 ASSERT_TRUE(data1.arg1()->GetAsString(&page));
420 EXPECT_EQ(page, "configure");
421 const base::DictionaryValue* dictionary = nullptr;
422 ASSERT_TRUE(data1.arg2()->GetAsDictionary(&dictionary));
423 CheckBool(dictionary, "passphraseFailed", false);
424 CheckBool(dictionary, "syncAllDataTypes", true);
425 CheckBool(dictionary, "encryptAllDataAllowed", true);
426 CheckBool(dictionary, "encryptAllData", false);
427 CheckBool(dictionary, "usePassphrase", false);
430 // Verifies the case where the user cancels after the sync backend has
431 // initialized (meaning it already transitioned from the spinner to a proper
432 // configuration page, tested by
433 // DisplayConfigureWithBackendDisabledAndSigninSuccess), but before the user
434 // before the user has continued on.
435 TEST_F(SyncSetupHandlerTest,
436 DisplayConfigureWithBackendDisabledAndCancelAfterSigninSuccess) {
437 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
438 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
439 .WillRepeatedly(Return(true));
440 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
441 .WillRepeatedly(Return(false));
442 error_ = GoogleServiceAuthError::AuthErrorNone();
443 EXPECT_CALL(*mock_pss_, IsBackendInitialized())
444 .WillOnce(Return(false))
445 .WillRepeatedly(Return(true));
446 SetDefaultExpectationsForConfigPage();
447 handler_->OpenSyncSetup();
449 // It's important to tell sync the user cancelled the setup flow before we
450 // tell it we're through with the setup progress.
451 testing::InSequence seq;
452 EXPECT_CALL(*mock_pss_, RequestStop(ProfileSyncService::CLEAR_DATA));
453 EXPECT_CALL(*mock_pss_, SetSetupInProgress(false));
455 handler_->CloseSyncSetup();
456 EXPECT_EQ(NULL,
457 LoginUIServiceFactory::GetForProfile(
458 profile_.get())->current_login_ui());
461 TEST_F(SyncSetupHandlerTest,
462 DisplayConfigureWithBackendDisabledAndSigninFailed) {
463 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
464 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
465 .WillRepeatedly(Return(true));
466 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
467 .WillRepeatedly(Return(false));
468 error_ = GoogleServiceAuthError::AuthErrorNone();
469 EXPECT_CALL(*mock_pss_, IsBackendInitialized()).WillRepeatedly(Return(false));
471 handler_->OpenSyncSetup();
472 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
473 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
474 std::string page;
475 ASSERT_TRUE(data.arg1()->GetAsString(&page));
476 EXPECT_EQ(page, "spinner");
477 Mock::VerifyAndClearExpectations(mock_pss_);
478 error_ = GoogleServiceAuthError(
479 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
480 EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_));
481 NotifySyncListeners();
483 // On failure, the dialog will be closed.
484 EXPECT_EQ(NULL,
485 LoginUIServiceFactory::GetForProfile(
486 profile_.get())->current_login_ui());
489 #if !defined(OS_CHROMEOS)
491 class SyncSetupHandlerNonCrosTest : public SyncSetupHandlerTest {
492 public:
493 SyncSetupHandlerNonCrosTest() {}
496 TEST_F(SyncSetupHandlerNonCrosTest, HandleGaiaAuthFailure) {
497 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
498 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
499 .WillRepeatedly(Return(false));
500 EXPECT_CALL(*mock_pss_, HasUnrecoverableError())
501 .WillRepeatedly(Return(false));
502 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
503 .WillRepeatedly(Return(false));
504 // Open the web UI.
505 handler_->OpenSyncSetup();
507 ASSERT_FALSE(handler_->is_configuring_sync());
510 // TODO(kochi): We need equivalent tests for ChromeOS.
511 TEST_F(SyncSetupHandlerNonCrosTest, UnrecoverableErrorInitializingSync) {
512 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
513 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
514 .WillRepeatedly(Return(false));
515 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
516 .WillRepeatedly(Return(false));
517 // Open the web UI.
518 handler_->OpenSyncSetup();
520 ASSERT_FALSE(handler_->is_configuring_sync());
523 TEST_F(SyncSetupHandlerNonCrosTest, GaiaErrorInitializingSync) {
524 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
525 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
526 .WillRepeatedly(Return(false));
527 EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
528 .WillRepeatedly(Return(false));
529 // Open the web UI.
530 handler_->OpenSyncSetup();
532 ASSERT_FALSE(handler_->is_configuring_sync());
535 #endif // #if !defined(OS_CHROMEOS)
537 TEST_F(SyncSetupHandlerTest, TestSyncEverything) {
538 std::string args = GetConfiguration(
539 NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
540 base::ListValue list_args;
541 list_args.Append(new base::StringValue(args));
542 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
543 .WillRepeatedly(Return(false));
544 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
545 .WillRepeatedly(Return(false));
546 SetupInitializedProfileSyncService();
547 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
548 handler_->HandleConfigure(&list_args);
550 // Ensure that we navigated to the "done" state since we don't need a
551 // passphrase.
552 ExpectDone();
555 TEST_F(SyncSetupHandlerTest, TestSyncNothing) {
556 std::string args = GetConfiguration(
557 NULL, SYNC_NOTHING, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
558 base::ListValue list_args;
559 list_args.Append(new base::StringValue(args));
560 EXPECT_CALL(*mock_pss_, RequestStop(ProfileSyncService::CLEAR_DATA));
561 SetupInitializedProfileSyncService();
562 handler_->HandleConfigure(&list_args);
564 // We expect a call to SyncSetupOverlay.showSyncSetupPage.
565 ASSERT_EQ(1U, web_ui_.call_data().size());
566 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
567 EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name());
570 TEST_F(SyncSetupHandlerTest, TurnOnEncryptAll) {
571 std::string args = GetConfiguration(
572 NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_ALL_DATA);
573 base::ListValue list_args;
574 list_args.Append(new base::StringValue(args));
575 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
576 .WillRepeatedly(Return(false));
577 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
578 .WillRepeatedly(Return(false));
579 EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed())
580 .WillRepeatedly(Return(true));
581 SetupInitializedProfileSyncService();
582 EXPECT_CALL(*mock_pss_, EnableEncryptEverything());
583 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
584 handler_->HandleConfigure(&list_args);
586 // Ensure that we navigated to the "done" state since we don't need a
587 // passphrase.
588 ExpectDone();
591 TEST_F(SyncSetupHandlerTest, TestPassphraseStillRequired) {
592 std::string args = GetConfiguration(
593 NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
594 base::ListValue list_args;
595 list_args.Append(new base::StringValue(args));
596 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
597 .WillRepeatedly(Return(true));
598 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
599 .WillRepeatedly(Return(true));
600 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
601 .WillRepeatedly(Return(false));
602 SetupInitializedProfileSyncService();
603 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
604 SetDefaultExpectationsForConfigPage();
606 // We should navigate back to the configure page since we need a passphrase.
607 handler_->HandleConfigure(&list_args);
609 ExpectConfig();
612 TEST_F(SyncSetupHandlerTest, SuccessfullySetPassphrase) {
613 base::DictionaryValue dict;
614 dict.SetBoolean("isGooglePassphrase", true);
615 std::string args = GetConfiguration(&dict,
616 SYNC_ALL_DATA,
617 GetAllTypes(),
618 "gaiaPassphrase",
619 ENCRYPT_PASSWORDS);
620 base::ListValue list_args;
621 list_args.Append(new base::StringValue(args));
622 // Act as if an encryption passphrase is required the first time, then never
623 // again after that.
624 EXPECT_CALL(*mock_pss_, IsPassphraseRequired()).WillOnce(Return(true));
625 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
626 .WillRepeatedly(Return(false));
627 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
628 .WillRepeatedly(Return(false));
629 SetupInitializedProfileSyncService();
630 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
631 EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("gaiaPassphrase")).
632 WillOnce(Return(true));
634 handler_->HandleConfigure(&list_args);
635 // We should navigate to "done" page since we finished configuring.
636 ExpectDone();
639 TEST_F(SyncSetupHandlerTest, SelectCustomEncryption) {
640 base::DictionaryValue dict;
641 dict.SetBoolean("isGooglePassphrase", false);
642 std::string args = GetConfiguration(&dict,
643 SYNC_ALL_DATA,
644 GetAllTypes(),
645 "custom_passphrase",
646 ENCRYPT_PASSWORDS);
647 base::ListValue list_args;
648 list_args.Append(new base::StringValue(args));
649 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
650 .WillRepeatedly(Return(false));
651 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
652 .WillRepeatedly(Return(false));
653 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
654 .WillRepeatedly(Return(false));
655 SetupInitializedProfileSyncService();
656 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
657 EXPECT_CALL(*mock_pss_,
658 SetEncryptionPassphrase("custom_passphrase",
659 ProfileSyncService::EXPLICIT));
661 handler_->HandleConfigure(&list_args);
662 // We should navigate to "done" page since we finished configuring.
663 ExpectDone();
666 TEST_F(SyncSetupHandlerTest, UnsuccessfullySetPassphrase) {
667 base::DictionaryValue dict;
668 dict.SetBoolean("isGooglePassphrase", true);
669 std::string args = GetConfiguration(&dict,
670 SYNC_ALL_DATA,
671 GetAllTypes(),
672 "invalid_passphrase",
673 ENCRYPT_PASSWORDS);
674 base::ListValue list_args;
675 list_args.Append(new base::StringValue(args));
676 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
677 .WillRepeatedly(Return(true));
678 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
679 .WillRepeatedly(Return(true));
680 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
681 .WillRepeatedly(Return(false));
682 SetupInitializedProfileSyncService();
683 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
684 EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("invalid_passphrase")).
685 WillOnce(Return(false));
687 SetDefaultExpectationsForConfigPage();
688 // We should navigate back to the configure page since we need a passphrase.
689 handler_->HandleConfigure(&list_args);
691 ExpectConfig();
693 // Make sure we display an error message to the user due to the failed
694 // passphrase.
695 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
696 const base::DictionaryValue* dictionary = nullptr;
697 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
698 CheckBool(dictionary, "passphraseFailed", true);
701 // Walks through each user selectable type, and tries to sync just that single
702 // data type.
703 TEST_F(SyncSetupHandlerTest, TestSyncIndividualTypes) {
704 syncer::ModelTypeSet user_selectable_types = GetAllTypes();
705 syncer::ModelTypeSet::Iterator it;
706 for (it = user_selectable_types.First(); it.Good(); it.Inc()) {
707 syncer::ModelTypeSet type_to_set;
708 type_to_set.Put(it.Get());
709 std::string args = GetConfiguration(NULL,
710 CHOOSE_WHAT_TO_SYNC,
711 type_to_set,
712 std::string(),
713 ENCRYPT_PASSWORDS);
714 base::ListValue list_args;
715 list_args.Append(new base::StringValue(args));
716 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
717 .WillRepeatedly(Return(false));
718 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
719 .WillRepeatedly(Return(false));
720 SetupInitializedProfileSyncService();
721 EXPECT_CALL(*mock_pss_,
722 OnUserChoseDatatypes(false, ModelTypeSetMatches(type_to_set)));
723 handler_->HandleConfigure(&list_args);
725 ExpectDone();
726 Mock::VerifyAndClearExpectations(mock_pss_);
727 web_ui_.ClearTrackedCalls();
731 TEST_F(SyncSetupHandlerTest, TestSyncAllManually) {
732 std::string args = GetConfiguration(NULL,
733 CHOOSE_WHAT_TO_SYNC,
734 GetAllTypes(),
735 std::string(),
736 ENCRYPT_PASSWORDS);
737 base::ListValue list_args;
738 list_args.Append(new base::StringValue(args));
739 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
740 .WillRepeatedly(Return(false));
741 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
742 .WillRepeatedly(Return(false));
743 SetupInitializedProfileSyncService();
744 EXPECT_CALL(*mock_pss_,
745 OnUserChoseDatatypes(false, ModelTypeSetMatches(GetAllTypes())));
746 handler_->HandleConfigure(&list_args);
748 ExpectDone();
751 TEST_F(SyncSetupHandlerTest, ShowSyncSetup) {
752 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
753 .WillRepeatedly(Return(false));
754 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
755 .WillRepeatedly(Return(false));
756 SetupInitializedProfileSyncService();
757 // This should display the sync setup dialog (not login).
758 SetDefaultExpectationsForConfigPage();
759 handler_->OpenSyncSetup();
761 ExpectConfig();
764 // We do not display signin on chromeos in the case of auth error.
765 TEST_F(SyncSetupHandlerTest, ShowSigninOnAuthError) {
766 // Initialize the system to a signed in state, but with an auth error.
767 error_ = GoogleServiceAuthError(
768 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
770 SetupInitializedProfileSyncService();
771 mock_signin_->SetAuthenticatedAccountInfo(kTestUser, kTestUser);
772 FakeAuthStatusProvider provider(
773 SigninErrorControllerFactory::GetForProfile(profile_.get()));
774 provider.SetAuthError(kTestUser, error_);
775 EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
776 EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
777 .WillRepeatedly(Return(true));
778 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
779 .WillRepeatedly(Return(false));
780 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
781 .WillRepeatedly(Return(false));
782 EXPECT_CALL(*mock_pss_, IsBackendInitialized()).WillRepeatedly(Return(false));
784 #if defined(OS_CHROMEOS)
785 // On ChromeOS, auth errors are ignored - instead we just try to start the
786 // sync backend (which will fail due to the auth error). This should only
787 // happen if the user manually navigates to chrome://settings/syncSetup -
788 // clicking on the button in the UI will sign the user out rather than
789 // displaying a spinner. Should be no visible UI on ChromeOS in this case.
790 EXPECT_EQ(NULL, LoginUIServiceFactory::GetForProfile(
791 profile_.get())->current_login_ui());
792 #else
794 // On ChromeOS, this should display the spinner while we try to startup the
795 // sync backend, and on desktop this displays the login dialog.
796 handler_->OpenSyncSetup();
798 // Sync setup is closed when re-auth is in progress.
799 EXPECT_EQ(NULL,
800 LoginUIServiceFactory::GetForProfile(
801 profile_.get())->current_login_ui());
803 ASSERT_FALSE(handler_->is_configuring_sync());
804 #endif
807 TEST_F(SyncSetupHandlerTest, ShowSetupSyncEverything) {
808 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
809 .WillRepeatedly(Return(false));
810 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
811 .WillRepeatedly(Return(false));
812 SetupInitializedProfileSyncService();
813 SetDefaultExpectationsForConfigPage();
814 // This should display the sync setup dialog (not login).
815 handler_->OpenSyncSetup();
817 ExpectConfig();
818 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
819 const base::DictionaryValue* dictionary = nullptr;
820 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
821 CheckBool(dictionary, "syncAllDataTypes", true);
822 CheckBool(dictionary, "appsRegistered", true);
823 CheckBool(dictionary, "autofillRegistered", true);
824 CheckBool(dictionary, "bookmarksRegistered", true);
825 CheckBool(dictionary, "extensionsRegistered", true);
826 CheckBool(dictionary, "passwordsRegistered", true);
827 CheckBool(dictionary, "preferencesRegistered", true);
828 CheckBool(dictionary, "wifiCredentialsRegistered", true);
829 CheckBool(dictionary, "tabsRegistered", true);
830 CheckBool(dictionary, "themesRegistered", true);
831 CheckBool(dictionary, "typedUrlsRegistered", true);
832 CheckBool(dictionary, "showPassphrase", false);
833 CheckBool(dictionary, "usePassphrase", false);
834 CheckBool(dictionary, "passphraseFailed", false);
835 CheckBool(dictionary, "encryptAllData", false);
836 CheckConfigDataTypeArguments(dictionary, SYNC_ALL_DATA, GetAllTypes());
839 TEST_F(SyncSetupHandlerTest, ShowSetupManuallySyncAll) {
840 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
841 .WillRepeatedly(Return(false));
842 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
843 .WillRepeatedly(Return(false));
844 SetupInitializedProfileSyncService();
845 sync_driver::SyncPrefs sync_prefs(profile_->GetPrefs());
846 sync_prefs.SetKeepEverythingSynced(false);
847 SetDefaultExpectationsForConfigPage();
848 // This should display the sync setup dialog (not login).
849 handler_->OpenSyncSetup();
851 ExpectConfig();
852 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
853 const base::DictionaryValue* dictionary = nullptr;
854 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
855 CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, GetAllTypes());
858 TEST_F(SyncSetupHandlerTest, ShowSetupSyncForAllTypesIndividually) {
859 syncer::ModelTypeSet user_selectable_types = GetAllTypes();
860 syncer::ModelTypeSet::Iterator it;
861 for (it = user_selectable_types.First(); it.Good(); it.Inc()) {
862 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
863 .WillRepeatedly(Return(false));
864 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
865 .WillRepeatedly(Return(false));
866 SetupInitializedProfileSyncService();
867 sync_driver::SyncPrefs sync_prefs(profile_->GetPrefs());
868 sync_prefs.SetKeepEverythingSynced(false);
869 SetDefaultExpectationsForConfigPage();
870 syncer::ModelTypeSet types;
871 types.Put(it.Get());
872 EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()).
873 WillRepeatedly(Return(types));
875 // This should display the sync setup dialog (not login).
876 handler_->OpenSyncSetup();
878 ExpectConfig();
879 // Close the config overlay.
880 LoginUIServiceFactory::GetForProfile(profile_.get())->LoginUIClosed(
881 handler_.get());
882 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
883 const base::DictionaryValue* dictionary = nullptr;
884 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
885 CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, types);
886 Mock::VerifyAndClearExpectations(mock_pss_);
887 // Clean up so we can loop back to display the dialog again.
888 web_ui_.ClearTrackedCalls();
892 TEST_F(SyncSetupHandlerTest, ShowSetupGaiaPassphraseRequired) {
893 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
894 .WillRepeatedly(Return(true));
895 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
896 .WillRepeatedly(Return(false));
897 SetupInitializedProfileSyncService();
898 SetDefaultExpectationsForConfigPage();
900 // This should display the sync setup dialog (not login).
901 handler_->OpenSyncSetup();
903 ExpectConfig();
904 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
905 const base::DictionaryValue* dictionary = nullptr;
906 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
907 CheckBool(dictionary, "showPassphrase", true);
908 CheckBool(dictionary, "usePassphrase", false);
909 CheckBool(dictionary, "passphraseFailed", false);
912 TEST_F(SyncSetupHandlerTest, ShowSetupCustomPassphraseRequired) {
913 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
914 .WillRepeatedly(Return(true));
915 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
916 .WillRepeatedly(Return(true));
917 EXPECT_CALL(*mock_pss_, GetPassphraseType())
918 .WillRepeatedly(Return(syncer::CUSTOM_PASSPHRASE));
919 SetupInitializedProfileSyncService();
920 SetDefaultExpectationsForConfigPage();
922 // This should display the sync setup dialog (not login).
923 handler_->OpenSyncSetup();
925 ExpectConfig();
926 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
927 const base::DictionaryValue* dictionary = nullptr;
928 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
929 CheckBool(dictionary, "showPassphrase", true);
930 CheckBool(dictionary, "usePassphrase", true);
931 CheckBool(dictionary, "passphraseFailed", false);
934 TEST_F(SyncSetupHandlerTest, ShowSetupEncryptAll) {
935 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
936 .WillRepeatedly(Return(false));
937 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
938 .WillRepeatedly(Return(false));
939 SetupInitializedProfileSyncService();
940 SetDefaultExpectationsForConfigPage();
941 EXPECT_CALL(*mock_pss_, IsEncryptEverythingEnabled())
942 .WillRepeatedly(Return(true));
944 // This should display the sync setup dialog (not login).
945 handler_->OpenSyncSetup();
947 ExpectConfig();
948 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
949 const base::DictionaryValue* dictionary = nullptr;
950 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
951 CheckBool(dictionary, "encryptAllData", true);
954 TEST_F(SyncSetupHandlerTest, ShowSetupEncryptAllDisallowed) {
955 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
956 .WillRepeatedly(Return(false));
957 EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
958 .WillRepeatedly(Return(false));
959 SetupInitializedProfileSyncService();
960 SetDefaultExpectationsForConfigPage();
961 EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed())
962 .WillRepeatedly(Return(false));
964 // This should display the sync setup dialog (not login).
965 handler_->OpenSyncSetup();
967 ExpectConfig();
968 const content::TestWebUI::CallData& data = *web_ui_.call_data()[0];
969 const base::DictionaryValue* dictionary = nullptr;
970 ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
971 CheckBool(dictionary, "encryptAllData", false);
972 CheckBool(dictionary, "encryptAllDataAllowed", false);
975 TEST_F(SyncSetupHandlerTest, TurnOnEncryptAllDisallowed) {
976 std::string args = GetConfiguration(
977 NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_ALL_DATA);
978 base::ListValue list_args;
979 list_args.Append(new base::StringValue(args));
980 EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
981 .WillRepeatedly(Return(false));
982 EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
983 .WillRepeatedly(Return(false));
984 SetupInitializedProfileSyncService();
985 EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed())
986 .WillRepeatedly(Return(false));
987 EXPECT_CALL(*mock_pss_, EnableEncryptEverything()).Times(0);
988 EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
989 handler_->HandleConfigure(&list_args);
991 // Ensure that we navigated to the "done" state since we don't need a
992 // passphrase.
993 ExpectDone();