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"
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"
38 using ::testing::Mock
;
39 using ::testing::Return
;
40 using ::testing::ReturnRef
;
41 using ::testing::Values
;
43 typedef GoogleServiceAuthError AuthError
;
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
{
62 enum EncryptAllConfig
{
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
;
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
));
97 base::JSONWriter::Write(result
, &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
,
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
;
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
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
));
150 class TestingSyncSetupHandler
: public SyncSetupHandler
{
152 TestingSyncSetupHandler(content::WebUI
* web_ui
, Profile
* profile
)
153 : profile_(profile
) {
156 ~TestingSyncSetupHandler() override
{ set_web_ui(NULL
); }
158 void FocusUI() override
{}
160 Profile
* GetProfile() const override
{ return profile_
; }
162 using SyncSetupHandler::is_configuring_sync
;
165 #if !defined(OS_CHROMEOS)
166 void DisplayGaiaLoginInNewTabOrWindow() override
{}
169 // Weak pointer to parent 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
{
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();
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(
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());
241 ASSERT_TRUE(data
.arg1()->GetAsString(&page
));
242 EXPECT_EQ(page
, "configure");
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());
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());
261 ASSERT_TRUE(data
.arg1()->GetAsString(&page
));
262 EXPECT_EQ(page
, "spinner");
263 // Cancelling the spinner dialog will cause CloseSyncSetup().
264 handler_
->CloseSyncSetup();
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.
312 LoginUIServiceFactory::GetForProfile(
313 profile_
.get())->current_login_ui());
315 ASSERT_FALSE(handler_
->is_configuring_sync());
317 handler_
->CloseSyncSetup();
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());
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
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.
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());
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();
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());
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.
486 LoginUIServiceFactory::GetForProfile(
487 profile_
.get())->current_login_ui());
490 #if !defined(OS_CHROMEOS)
492 class SyncSetupHandlerNonCrosTest
: public SyncSetupHandlerTest
{
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));
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));
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));
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
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
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
);
613 TEST_F(SyncSetupHandlerTest
, SuccessfullySetPassphrase
) {
614 base::DictionaryValue dict
;
615 dict
.SetBoolean("isGooglePassphrase", true);
616 std::string args
= GetConfiguration(&dict
,
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
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.
640 TEST_F(SyncSetupHandlerTest
, SelectCustomEncryption
) {
641 base::DictionaryValue dict
;
642 dict
.SetBoolean("isGooglePassphrase", false);
643 std::string args
= GetConfiguration(&dict
,
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.
667 TEST_F(SyncSetupHandlerTest
, UnsuccessfullySetPassphrase
) {
668 base::DictionaryValue dict
;
669 dict
.SetBoolean("isGooglePassphrase", true);
670 std::string args
= GetConfiguration(&dict
,
673 "invalid_passphrase",
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
);
694 // Make sure we display an error message to the user due to the failed
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
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
,
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
);
727 Mock::VerifyAndClearExpectations(mock_pss_
);
728 web_ui_
.ClearTrackedCalls();
732 TEST_F(SyncSetupHandlerTest
, TestSyncAllManually
) {
733 std::string args
= GetConfiguration(NULL
,
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
);
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();
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());
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.
801 LoginUIServiceFactory::GetForProfile(
802 profile_
.get())->current_login_ui());
804 ASSERT_FALSE(handler_
->is_configuring_sync());
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();
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();
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
;
873 EXPECT_CALL(*mock_pss_
, GetPreferredDataTypes()).
874 WillRepeatedly(Return(types
));
876 // This should display the sync setup dialog (not login).
877 handler_
->OpenSyncSetup();
880 // Close the config overlay.
881 LoginUIServiceFactory::GetForProfile(profile_
.get())->LoginUIClosed(
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();
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();
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();
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();
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