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.
4
5#include "chrome/browser/ui/webui/sync_setup_handler.h"
6
7#include <vector>
8
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.h"
16#include "chrome/browser/signin/profile_oauth2_token_service_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/profile_oauth2_token_service.h"
29#include "components/signin/core/browser/signin_manager.h"
30#include "components/sync_driver/sync_prefs.h"
31#include "content/public/browser/web_ui.h"
32#include "content/public/test/test_browser_thread.h"
33#include "content/public/test/test_browser_thread_bundle.h"
34#include "testing/gtest/include/gtest/gtest.h"
35#include "ui/base/layout.h"
36
37using ::testing::_;
38using ::testing::Mock;
39using ::testing::Return;
40using ::testing::ReturnRef;
41using ::testing::Values;
42
43typedef GoogleServiceAuthError AuthError;
44
45namespace {
46
47MATCHER_P(ModelTypeSetMatches, value, "") { return arg.Equals(value); }
48
49const char kTestUser[] = "chrome.p13n.test@gmail.com";
50
51// Returns a ModelTypeSet with all user selectable types set.
52syncer::ModelTypeSet GetAllTypes() {
53  return syncer::UserSelectableTypes();
54}
55
56enum SyncAllDataConfig {
57  SYNC_ALL_DATA,
58  CHOOSE_WHAT_TO_SYNC,
59  SYNC_NOTHING
60};
61
62enum EncryptAllConfig {
63  ENCRYPT_ALL_DATA,
64  ENCRYPT_PASSWORDS
65};
66
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.
70std::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  std::string args;
95  base::JSONWriter::Write(&result, &args);
96  return args;
97}
98
99// Checks whether the passed |dictionary| contains a |key| with the given
100// |expected_value|. If |omit_if_false| is true, then the value should only
101// be present if |expected_value| is true.
102void CheckBool(const base::DictionaryValue* dictionary,
103               const std::string& key,
104               bool expected_value,
105               bool omit_if_false) {
106  if (omit_if_false && !expected_value) {
107    EXPECT_FALSE(dictionary->HasKey(key)) <<
108        "Did not expect to find value for " << key;
109  } else {
110    bool actual_value;
111    EXPECT_TRUE(dictionary->GetBoolean(key, &actual_value)) <<
112        "No value found for " << key;
113    EXPECT_EQ(actual_value, expected_value) <<
114        "Mismatch found for " << key;
115  }
116}
117
118void CheckBool(const base::DictionaryValue* dictionary,
119               const std::string& key,
120               bool expected_value) {
121  return CheckBool(dictionary, key, expected_value, false);
122}
123
124// Checks to make sure that the values stored in |dictionary| match the values
125// expected by the showSyncSetupPage() JS function for a given set of data
126// types.
127void CheckConfigDataTypeArguments(base::DictionaryValue* dictionary,
128                                  SyncAllDataConfig config,
129                                  syncer::ModelTypeSet types) {
130  CheckBool(dictionary, "syncAllDataTypes", config == SYNC_ALL_DATA);
131  CheckBool(dictionary, "syncNothing", config == SYNC_NOTHING);
132  CheckBool(dictionary, "appsSynced", types.Has(syncer::APPS));
133  CheckBool(dictionary, "autofillSynced", types.Has(syncer::AUTOFILL));
134  CheckBool(dictionary, "bookmarksSynced", types.Has(syncer::BOOKMARKS));
135  CheckBool(dictionary, "extensionsSynced", types.Has(syncer::EXTENSIONS));
136  CheckBool(dictionary, "passwordsSynced", types.Has(syncer::PASSWORDS));
137  CheckBool(dictionary, "preferencesSynced", types.Has(syncer::PREFERENCES));
138  CheckBool(dictionary, "tabsSynced", types.Has(syncer::PROXY_TABS));
139  CheckBool(dictionary, "themesSynced", types.Has(syncer::THEMES));
140  CheckBool(dictionary, "typedUrlsSynced", types.Has(syncer::TYPED_URLS));
141}
142
143
144}  // namespace
145
146// Test instance of WebUI that tracks the data passed to
147// CallJavascriptFunction().
148class TestWebUI : public content::WebUI {
149 public:
150  virtual ~TestWebUI() {
151    ClearTrackedCalls();
152  }
153
154  void ClearTrackedCalls() {
155    // Manually free the arguments stored in CallData, since there's no good
156    // way to use a self-freeing reference like scoped_ptr in a std::vector.
157    for (std::vector<CallData>::iterator i = call_data_.begin();
158         i != call_data_.end();
159         ++i) {
160      delete i->arg1;
161      delete i->arg2;
162    }
163    call_data_.clear();
164  }
165
166  virtual void CallJavascriptFunction(const std::string& function_name)
167      OVERRIDE {
168    call_data_.push_back(CallData());
169    call_data_.back().function_name = function_name;
170  }
171
172  virtual void CallJavascriptFunction(const std::string& function_name,
173                                      const base::Value& arg1) OVERRIDE {
174    call_data_.push_back(CallData());
175    call_data_.back().function_name = function_name;
176    call_data_.back().arg1 = arg1.DeepCopy();
177  }
178
179  virtual void CallJavascriptFunction(const std::string& function_name,
180                                      const base::Value& arg1,
181                                      const base::Value& arg2) OVERRIDE {
182    call_data_.push_back(CallData());
183    call_data_.back().function_name = function_name;
184    call_data_.back().arg1 = arg1.DeepCopy();
185    call_data_.back().arg2 = arg2.DeepCopy();
186  }
187
188  virtual content::WebContents* GetWebContents() const OVERRIDE {
189    return NULL;
190  }
191  virtual content::WebUIController* GetController() const OVERRIDE {
192    return NULL;
193  }
194  virtual void SetController(content::WebUIController* controller) OVERRIDE {}
195  virtual float GetDeviceScaleFactor() const OVERRIDE {
196    return 1.0f;
197  }
198  virtual const base::string16& GetOverriddenTitle() const OVERRIDE {
199    return temp_string_;
200  }
201  virtual void OverrideTitle(const base::string16& title) OVERRIDE {}
202  virtual ui::PageTransition GetLinkTransitionType() const OVERRIDE {
203    return ui::PAGE_TRANSITION_LINK;
204  }
205  virtual void SetLinkTransitionType(ui::PageTransition type) OVERRIDE {}
206  virtual int GetBindings() const OVERRIDE {
207    return 0;
208  }
209  virtual void SetBindings(int bindings) OVERRIDE {}
210  virtual void OverrideJavaScriptFrame(
211      const std::string& frame_name) OVERRIDE {}
212  virtual void AddMessageHandler(
213      content::WebUIMessageHandler* handler) OVERRIDE {}
214  virtual void RegisterMessageCallback(
215      const std::string& message,
216      const MessageCallback& callback) OVERRIDE {}
217  virtual void ProcessWebUIMessage(const GURL& source_url,
218                                   const std::string& message,
219                                   const base::ListValue& args) OVERRIDE {}
220  virtual void CallJavascriptFunction(const std::string& function_name,
221                                      const base::Value& arg1,
222                                      const base::Value& arg2,
223                                      const base::Value& arg3) OVERRIDE {}
224  virtual void CallJavascriptFunction(const std::string& function_name,
225                                      const base::Value& arg1,
226                                      const base::Value& arg2,
227                                      const base::Value& arg3,
228                                      const base::Value& arg4) OVERRIDE {}
229  virtual void CallJavascriptFunction(
230      const std::string& function_name,
231      const std::vector<const base::Value*>& args) OVERRIDE {}
232
233  class CallData {
234   public:
235    CallData() : arg1(NULL), arg2(NULL) {}
236    std::string function_name;
237    base::Value* arg1;
238    base::Value* arg2;
239  };
240  const std::vector<CallData>& call_data() { return call_data_; }
241 private:
242  std::vector<CallData> call_data_;
243  base::string16 temp_string_;
244};
245
246class TestingSyncSetupHandler : public SyncSetupHandler {
247 public:
248  TestingSyncSetupHandler(content::WebUI* web_ui, Profile* profile)
249      : SyncSetupHandler(NULL),
250        profile_(profile) {
251    set_web_ui(web_ui);
252  }
253  virtual ~TestingSyncSetupHandler() {
254    set_web_ui(NULL);
255  }
256
257  virtual void FocusUI() OVERRIDE {}
258
259  virtual Profile* GetProfile() const OVERRIDE { return profile_; }
260
261  using SyncSetupHandler::is_configuring_sync;
262
263 private:
264#if !defined(OS_CHROMEOS)
265  virtual void DisplayGaiaLoginInNewTabOrWindow() OVERRIDE {}
266#endif
267
268  // Weak pointer to parent profile.
269  Profile* profile_;
270  DISALLOW_COPY_AND_ASSIGN(TestingSyncSetupHandler);
271};
272
273// The boolean parameter indicates whether the test is run with ClientOAuth
274// or not.  The test parameter is a bool: whether or not to test with/
275// /ClientLogin enabled or not.
276class SyncSetupHandlerTest : public testing::Test {
277 public:
278  SyncSetupHandlerTest() : error_(GoogleServiceAuthError::NONE) {}
279  virtual void SetUp() OVERRIDE {
280    error_ = GoogleServiceAuthError::AuthErrorNone();
281
282    TestingProfile::Builder builder;
283    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
284                              FakeSigninManagerBase::Build);
285    profile_ = builder.Build();
286
287    // Sign in the user.
288    mock_signin_ = static_cast<SigninManagerBase*>(
289        SigninManagerFactory::GetForProfile(profile_.get()));
290    mock_signin_->SetAuthenticatedUsername(GetTestUser());
291    profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
292                                    GetTestUser());
293
294    mock_pss_ = static_cast<ProfileSyncServiceMock*>(
295        ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
296            profile_.get(),
297            ProfileSyncServiceMock::BuildMockProfileSyncService));
298    EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_));
299    ON_CALL(*mock_pss_, GetPassphraseType()).WillByDefault(
300        Return(syncer::IMPLICIT_PASSPHRASE));
301    ON_CALL(*mock_pss_, GetPassphraseTime()).WillByDefault(
302        Return(base::Time()));
303    ON_CALL(*mock_pss_, GetExplicitPassphraseTime()).WillByDefault(
304        Return(base::Time()));
305    ON_CALL(*mock_pss_, GetRegisteredDataTypes())
306        .WillByDefault(Return(syncer::ModelTypeSet()));
307
308    mock_pss_->Initialize();
309
310    handler_.reset(new TestingSyncSetupHandler(&web_ui_, profile_.get()));
311  }
312
313  // Setup the expectations for calls made when displaying the config page.
314  void SetDefaultExpectationsForConfigPage() {
315    EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn()).
316        WillRepeatedly(Return(true));
317    EXPECT_CALL(*mock_pss_, GetRegisteredDataTypes()).
318        WillRepeatedly(Return(GetAllTypes()));
319    EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()).
320        WillRepeatedly(Return(GetAllTypes()));
321    EXPECT_CALL(*mock_pss_, GetActiveDataTypes()).
322        WillRepeatedly(Return(GetAllTypes()));
323    EXPECT_CALL(*mock_pss_, EncryptEverythingAllowed()).
324        WillRepeatedly(Return(true));
325    EXPECT_CALL(*mock_pss_, EncryptEverythingEnabled()).
326        WillRepeatedly(Return(false));
327  }
328
329  void SetupInitializedProfileSyncService() {
330    // An initialized ProfileSyncService will have already completed sync setup
331    // and will have an initialized sync backend.
332    ASSERT_TRUE(mock_signin_->IsInitialized());
333    EXPECT_CALL(*mock_pss_, sync_initialized()).WillRepeatedly(Return(true));
334  }
335
336  void ExpectConfig() {
337    ASSERT_EQ(1U, web_ui_.call_data().size());
338    const TestWebUI::CallData& data = web_ui_.call_data()[0];
339    EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name);
340    std::string page;
341    ASSERT_TRUE(data.arg1->GetAsString(&page));
342    EXPECT_EQ(page, "configure");
343  }
344
345  void ExpectDone() {
346    ASSERT_EQ(1U, web_ui_.call_data().size());
347    const TestWebUI::CallData& data = web_ui_.call_data()[0];
348    EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name);
349    std::string page;
350    ASSERT_TRUE(data.arg1->GetAsString(&page));
351    EXPECT_EQ(page, "done");
352  }
353
354  void ExpectSpinnerAndClose() {
355    // We expect a call to SyncSetupOverlay.showSyncSetupPage.
356    EXPECT_EQ(1U, web_ui_.call_data().size());
357    const TestWebUI::CallData& data = web_ui_.call_data()[0];
358    EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name);
359
360    std::string page;
361    ASSERT_TRUE(data.arg1->GetAsString(&page));
362    EXPECT_EQ(page, "spinner");
363    // Cancelling the spinner dialog will cause CloseSyncSetup().
364    handler_->CloseSyncSetup();
365    EXPECT_EQ(NULL,
366              LoginUIServiceFactory::GetForProfile(
367                  profile_.get())->current_login_ui());
368  }
369
370  // It's difficult to notify sync listeners when using a ProfileSyncServiceMock
371  // so this helper routine dispatches an OnStateChanged() notification to the
372  // SyncStartupTracker.
373  void NotifySyncListeners() {
374    if (handler_->sync_startup_tracker_)
375      handler_->sync_startup_tracker_->OnStateChanged();
376  }
377
378  virtual std::string GetTestUser() {
379    return std::string(kTestUser);
380  }
381
382  content::TestBrowserThreadBundle thread_bundle_;
383  scoped_ptr<Profile> profile_;
384  ProfileSyncServiceMock* mock_pss_;
385  GoogleServiceAuthError error_;
386  SigninManagerBase* mock_signin_;
387  TestWebUI web_ui_;
388  scoped_ptr<TestingSyncSetupHandler> handler_;
389};
390
391class SyncSetupHandlerFirstSigninTest : public SyncSetupHandlerTest {
392  virtual std::string GetTestUser() OVERRIDE { return std::string(); }
393};
394
395TEST_F(SyncSetupHandlerTest, Basic) {
396}
397
398#if !defined(OS_CHROMEOS)
399TEST_F(SyncSetupHandlerFirstSigninTest, DisplayBasicLogin) {
400  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
401      .WillRepeatedly(Return(false));
402  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
403      .WillRepeatedly(Return(false));
404  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
405      .WillRepeatedly(Return(false));
406  // Ensure that the user is not signed in before calling |HandleStartSignin()|.
407  SigninManager* manager = static_cast<SigninManager*>(mock_signin_);
408  manager->SignOut(signin_metrics::SIGNOUT_TEST);
409  handler_->HandleStartSignin(NULL);
410
411  // Sync setup hands off control to the gaia login tab.
412  EXPECT_EQ(NULL,
413            LoginUIServiceFactory::GetForProfile(
414                profile_.get())->current_login_ui());
415
416  ASSERT_FALSE(handler_->is_configuring_sync());
417
418  handler_->CloseSyncSetup();
419  EXPECT_EQ(NULL,
420            LoginUIServiceFactory::GetForProfile(
421                profile_.get())->current_login_ui());
422}
423
424TEST_F(SyncSetupHandlerTest, ShowSyncSetupWhenNotSignedIn) {
425  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
426      .WillRepeatedly(Return(false));
427  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
428      .WillRepeatedly(Return(false));
429  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
430      .WillRepeatedly(Return(false));
431  handler_->HandleShowSetupUI(NULL);
432
433  // We expect a call to SyncSetupOverlay.showSyncSetupPage.
434  ASSERT_EQ(1U, web_ui_.call_data().size());
435  const TestWebUI::CallData& data = web_ui_.call_data()[0];
436  EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name);
437
438  ASSERT_FALSE(handler_->is_configuring_sync());
439  EXPECT_EQ(NULL,
440            LoginUIServiceFactory::GetForProfile(
441                profile_.get())->current_login_ui());
442}
443#endif  // !defined(OS_CHROMEOS)
444
445// Verifies that the sync setup is terminated correctly when the
446// sync is disabled.
447TEST_F(SyncSetupHandlerTest, HandleSetupUIWhenSyncDisabled) {
448  EXPECT_CALL(*mock_pss_, IsManaged()).WillRepeatedly(Return(true));
449  handler_->HandleShowSetupUI(NULL);
450
451  // Sync setup is closed when sync is disabled.
452  EXPECT_EQ(NULL,
453            LoginUIServiceFactory::GetForProfile(
454                profile_.get())->current_login_ui());
455  ASSERT_FALSE(handler_->is_configuring_sync());
456}
457
458// Verifies that the handler correctly handles a cancellation when
459// it is displaying the spinner to the user.
460TEST_F(SyncSetupHandlerTest, DisplayConfigureWithBackendDisabledAndCancel) {
461  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
462      .WillRepeatedly(Return(true));
463  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
464      .WillRepeatedly(Return(true));
465  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
466      .WillRepeatedly(Return(false));
467  error_ = GoogleServiceAuthError::AuthErrorNone();
468  EXPECT_CALL(*mock_pss_, sync_initialized()).WillRepeatedly(Return(false));
469
470  // We're simulating a user setting up sync, which would cause the backend to
471  // kick off initialization, but not download user data types. The sync
472  // backend will try to download control data types (e.g encryption info), but
473  // that won't finish for this test as we're simulating cancelling while the
474  // spinner is showing.
475  handler_->HandleShowSetupUI(NULL);
476
477  EXPECT_EQ(handler_.get(),
478            LoginUIServiceFactory::GetForProfile(
479                profile_.get())->current_login_ui());
480
481  ExpectSpinnerAndClose();
482}
483
484// Verifies that the handler correctly transitions from showing the spinner
485// to showing a configuration page when sync setup completes successfully.
486TEST_F(SyncSetupHandlerTest,
487       DisplayConfigureWithBackendDisabledAndSyncStartupCompleted) {
488  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
489      .WillRepeatedly(Return(true));
490  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
491      .WillRepeatedly(Return(true));
492  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
493      .WillRepeatedly(Return(false));
494  error_ = GoogleServiceAuthError::AuthErrorNone();
495  // Sync backend is stopped initially, and will start up.
496  EXPECT_CALL(*mock_pss_, sync_initialized())
497      .WillRepeatedly(Return(false));
498  SetDefaultExpectationsForConfigPage();
499
500  handler_->OpenSyncSetup();
501
502  // We expect a call to SyncSetupOverlay.showSyncSetupPage.
503  EXPECT_EQ(1U, web_ui_.call_data().size());
504
505  const TestWebUI::CallData& data0 = web_ui_.call_data()[0];
506  EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data0.function_name);
507  std::string page;
508  ASSERT_TRUE(data0.arg1->GetAsString(&page));
509  EXPECT_EQ(page, "spinner");
510
511  Mock::VerifyAndClearExpectations(mock_pss_);
512  // Now, act as if the ProfileSyncService has started up.
513  SetDefaultExpectationsForConfigPage();
514  EXPECT_CALL(*mock_pss_, sync_initialized())
515      .WillRepeatedly(Return(true));
516  error_ = GoogleServiceAuthError::AuthErrorNone();
517  EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_));
518  NotifySyncListeners();
519
520  // We expect a second call to SyncSetupOverlay.showSyncSetupPage.
521  EXPECT_EQ(2U, web_ui_.call_data().size());
522  const TestWebUI::CallData& data1 = web_ui_.call_data().back();
523  EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data1.function_name);
524  ASSERT_TRUE(data1.arg1->GetAsString(&page));
525  EXPECT_EQ(page, "configure");
526  base::DictionaryValue* dictionary;
527  ASSERT_TRUE(data1.arg2->GetAsDictionary(&dictionary));
528  CheckBool(dictionary, "passphraseFailed", false);
529  CheckBool(dictionary, "showSyncEverythingPage", false);
530  CheckBool(dictionary, "syncAllDataTypes", true);
531  CheckBool(dictionary, "encryptAllDataAllowed", true);
532  CheckBool(dictionary, "encryptAllData", false);
533  CheckBool(dictionary, "usePassphrase", false);
534}
535
536// Verifies the case where the user cancels after the sync backend has
537// initialized (meaning it already transitioned from the spinner to a proper
538// configuration page, tested by
539// DisplayConfigureWithBackendDisabledAndSigninSuccess), but before the user
540// before the user has continued on.
541TEST_F(SyncSetupHandlerTest,
542       DisplayConfigureWithBackendDisabledAndCancelAfterSigninSuccess) {
543  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
544      .WillRepeatedly(Return(true));
545  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
546      .WillRepeatedly(Return(true));
547  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
548      .WillRepeatedly(Return(false));
549  error_ = GoogleServiceAuthError::AuthErrorNone();
550  EXPECT_CALL(*mock_pss_, sync_initialized())
551      .WillOnce(Return(false))
552      .WillRepeatedly(Return(true));
553  SetDefaultExpectationsForConfigPage();
554  handler_->OpenSyncSetup();
555
556  // It's important to tell sync the user cancelled the setup flow before we
557  // tell it we're through with the setup progress.
558  testing::InSequence seq;
559  EXPECT_CALL(*mock_pss_, DisableForUser());
560  EXPECT_CALL(*mock_pss_, SetSetupInProgress(false));
561
562  handler_->CloseSyncSetup();
563  EXPECT_EQ(NULL,
564            LoginUIServiceFactory::GetForProfile(
565                profile_.get())->current_login_ui());
566}
567
568TEST_F(SyncSetupHandlerTest,
569       DisplayConfigureWithBackendDisabledAndSigninFailed) {
570  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
571      .WillRepeatedly(Return(true));
572  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
573      .WillRepeatedly(Return(true));
574  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
575      .WillRepeatedly(Return(false));
576  error_ = GoogleServiceAuthError::AuthErrorNone();
577  EXPECT_CALL(*mock_pss_, sync_initialized()).WillRepeatedly(Return(false));
578
579  handler_->OpenSyncSetup();
580  const TestWebUI::CallData& data = web_ui_.call_data()[0];
581  EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name);
582  std::string page;
583  ASSERT_TRUE(data.arg1->GetAsString(&page));
584  EXPECT_EQ(page, "spinner");
585  Mock::VerifyAndClearExpectations(mock_pss_);
586  error_ = GoogleServiceAuthError(
587      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
588  EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_));
589  NotifySyncListeners();
590
591  // On failure, the dialog will be closed.
592  EXPECT_EQ(NULL,
593            LoginUIServiceFactory::GetForProfile(
594                profile_.get())->current_login_ui());
595}
596
597#if !defined(OS_CHROMEOS)
598
599class SyncSetupHandlerNonCrosTest : public SyncSetupHandlerTest {
600 public:
601  SyncSetupHandlerNonCrosTest() {}
602};
603
604TEST_F(SyncSetupHandlerNonCrosTest, HandleGaiaAuthFailure) {
605  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
606      .WillRepeatedly(Return(false));
607  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
608      .WillRepeatedly(Return(false));
609  EXPECT_CALL(*mock_pss_, HasUnrecoverableError())
610      .WillRepeatedly(Return(false));
611  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
612      .WillRepeatedly(Return(false));
613  // Open the web UI.
614  handler_->OpenSyncSetup();
615
616  ASSERT_FALSE(handler_->is_configuring_sync());
617}
618
619// TODO(kochi): We need equivalent tests for ChromeOS.
620TEST_F(SyncSetupHandlerNonCrosTest, UnrecoverableErrorInitializingSync) {
621  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
622      .WillRepeatedly(Return(false));
623  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
624      .WillRepeatedly(Return(false));
625  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
626      .WillRepeatedly(Return(false));
627  // Open the web UI.
628  handler_->OpenSyncSetup();
629
630  ASSERT_FALSE(handler_->is_configuring_sync());
631}
632
633TEST_F(SyncSetupHandlerNonCrosTest, GaiaErrorInitializingSync) {
634  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
635      .WillRepeatedly(Return(false));
636  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
637      .WillRepeatedly(Return(false));
638  EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
639      .WillRepeatedly(Return(false));
640  // Open the web UI.
641  handler_->OpenSyncSetup();
642
643  ASSERT_FALSE(handler_->is_configuring_sync());
644}
645
646#endif  // #if !defined(OS_CHROMEOS)
647
648TEST_F(SyncSetupHandlerTest, TestSyncEverything) {
649  std::string args = GetConfiguration(
650      NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
651  base::ListValue list_args;
652  list_args.Append(new base::StringValue(args));
653  EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
654      .WillRepeatedly(Return(false));
655  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
656      .WillRepeatedly(Return(false));
657  SetupInitializedProfileSyncService();
658  EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
659  handler_->HandleConfigure(&list_args);
660
661  // Ensure that we navigated to the "done" state since we don't need a
662  // passphrase.
663  ExpectDone();
664}
665
666TEST_F(SyncSetupHandlerTest, TestSyncNothing) {
667  std::string args = GetConfiguration(
668      NULL, SYNC_NOTHING, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
669  base::ListValue list_args;
670  list_args.Append(new base::StringValue(args));
671  EXPECT_CALL(*mock_pss_, DisableForUser());
672  SetupInitializedProfileSyncService();
673  handler_->HandleConfigure(&list_args);
674
675  // We expect a call to SyncSetupOverlay.showSyncSetupPage.
676  ASSERT_EQ(1U, web_ui_.call_data().size());
677  const TestWebUI::CallData& data = web_ui_.call_data()[0];
678  EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name);
679}
680
681TEST_F(SyncSetupHandlerTest, TurnOnEncryptAll) {
682  std::string args = GetConfiguration(
683      NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_ALL_DATA);
684  base::ListValue list_args;
685  list_args.Append(new base::StringValue(args));
686  EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
687      .WillRepeatedly(Return(false));
688  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
689      .WillRepeatedly(Return(false));
690  EXPECT_CALL(*mock_pss_, EncryptEverythingAllowed())
691      .WillRepeatedly(Return(true));
692  SetupInitializedProfileSyncService();
693  EXPECT_CALL(*mock_pss_, EnableEncryptEverything());
694  EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
695  handler_->HandleConfigure(&list_args);
696
697  // Ensure that we navigated to the "done" state since we don't need a
698  // passphrase.
699  ExpectDone();
700}
701
702TEST_F(SyncSetupHandlerTest, TestPassphraseStillRequired) {
703  std::string args = GetConfiguration(
704      NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
705  base::ListValue list_args;
706  list_args.Append(new base::StringValue(args));
707  EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
708      .WillRepeatedly(Return(true));
709  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
710      .WillRepeatedly(Return(true));
711  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
712      .WillRepeatedly(Return(false));
713  SetupInitializedProfileSyncService();
714  EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
715  SetDefaultExpectationsForConfigPage();
716
717  // We should navigate back to the configure page since we need a passphrase.
718  handler_->HandleConfigure(&list_args);
719
720  ExpectConfig();
721}
722
723TEST_F(SyncSetupHandlerTest, SuccessfullySetPassphrase) {
724  base::DictionaryValue dict;
725  dict.SetBoolean("isGooglePassphrase", true);
726  std::string args = GetConfiguration(&dict,
727                                      SYNC_ALL_DATA,
728                                      GetAllTypes(),
729                                      "gaiaPassphrase",
730                                      ENCRYPT_PASSWORDS);
731  base::ListValue list_args;
732  list_args.Append(new base::StringValue(args));
733  // Act as if an encryption passphrase is required the first time, then never
734  // again after that.
735  EXPECT_CALL(*mock_pss_, IsPassphraseRequired()).WillOnce(Return(true));
736  EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
737      .WillRepeatedly(Return(false));
738  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
739      .WillRepeatedly(Return(false));
740  SetupInitializedProfileSyncService();
741  EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
742  EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("gaiaPassphrase")).
743      WillOnce(Return(true));
744
745  handler_->HandleConfigure(&list_args);
746  // We should navigate to "done" page since we finished configuring.
747  ExpectDone();
748}
749
750TEST_F(SyncSetupHandlerTest, SelectCustomEncryption) {
751  base::DictionaryValue dict;
752  dict.SetBoolean("isGooglePassphrase", false);
753  std::string args = GetConfiguration(&dict,
754                                      SYNC_ALL_DATA,
755                                      GetAllTypes(),
756                                      "custom_passphrase",
757                                      ENCRYPT_PASSWORDS);
758  base::ListValue list_args;
759  list_args.Append(new base::StringValue(args));
760  EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
761      .WillRepeatedly(Return(false));
762  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
763      .WillRepeatedly(Return(false));
764  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
765      .WillRepeatedly(Return(false));
766  SetupInitializedProfileSyncService();
767  EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
768  EXPECT_CALL(*mock_pss_,
769              SetEncryptionPassphrase("custom_passphrase",
770                                      ProfileSyncService::EXPLICIT));
771
772  handler_->HandleConfigure(&list_args);
773  // We should navigate to "done" page since we finished configuring.
774  ExpectDone();
775}
776
777TEST_F(SyncSetupHandlerTest, UnsuccessfullySetPassphrase) {
778  base::DictionaryValue dict;
779  dict.SetBoolean("isGooglePassphrase", true);
780  std::string args = GetConfiguration(&dict,
781                                      SYNC_ALL_DATA,
782                                      GetAllTypes(),
783                                      "invalid_passphrase",
784                                      ENCRYPT_PASSWORDS);
785  base::ListValue list_args;
786  list_args.Append(new base::StringValue(args));
787  EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
788      .WillRepeatedly(Return(true));
789  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
790      .WillRepeatedly(Return(true));
791  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
792      .WillRepeatedly(Return(false));
793  SetupInitializedProfileSyncService();
794  EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _));
795  EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("invalid_passphrase")).
796      WillOnce(Return(false));
797
798  SetDefaultExpectationsForConfigPage();
799  // We should navigate back to the configure page since we need a passphrase.
800  handler_->HandleConfigure(&list_args);
801
802  ExpectConfig();
803
804  // Make sure we display an error message to the user due to the failed
805  // passphrase.
806  const TestWebUI::CallData& data = web_ui_.call_data()[0];
807  base::DictionaryValue* dictionary;
808  ASSERT_TRUE(data.arg2->GetAsDictionary(&dictionary));
809  CheckBool(dictionary, "passphraseFailed", true);
810}
811
812// Walks through each user selectable type, and tries to sync just that single
813// data type.
814TEST_F(SyncSetupHandlerTest, TestSyncIndividualTypes) {
815  syncer::ModelTypeSet user_selectable_types = GetAllTypes();
816  syncer::ModelTypeSet::Iterator it;
817  for (it = user_selectable_types.First(); it.Good(); it.Inc()) {
818    syncer::ModelTypeSet type_to_set;
819    type_to_set.Put(it.Get());
820    std::string args = GetConfiguration(NULL,
821                                        CHOOSE_WHAT_TO_SYNC,
822                                        type_to_set,
823                                        std::string(),
824                                        ENCRYPT_PASSWORDS);
825    base::ListValue list_args;
826    list_args.Append(new base::StringValue(args));
827    EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
828        .WillRepeatedly(Return(false));
829    EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
830        .WillRepeatedly(Return(false));
831    SetupInitializedProfileSyncService();
832    EXPECT_CALL(*mock_pss_,
833                OnUserChoseDatatypes(false, ModelTypeSetMatches(type_to_set)));
834    handler_->HandleConfigure(&list_args);
835
836    ExpectDone();
837    Mock::VerifyAndClearExpectations(mock_pss_);
838    web_ui_.ClearTrackedCalls();
839  }
840}
841
842TEST_F(SyncSetupHandlerTest, TestSyncAllManually) {
843  std::string args = GetConfiguration(NULL,
844                                      CHOOSE_WHAT_TO_SYNC,
845                                      GetAllTypes(),
846                                      std::string(),
847                                      ENCRYPT_PASSWORDS);
848  base::ListValue list_args;
849  list_args.Append(new base::StringValue(args));
850  EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
851      .WillRepeatedly(Return(false));
852  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
853      .WillRepeatedly(Return(false));
854  SetupInitializedProfileSyncService();
855  EXPECT_CALL(*mock_pss_,
856              OnUserChoseDatatypes(false, ModelTypeSetMatches(GetAllTypes())));
857  handler_->HandleConfigure(&list_args);
858
859  ExpectDone();
860}
861
862TEST_F(SyncSetupHandlerTest, ShowSyncSetup) {
863  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
864      .WillRepeatedly(Return(false));
865  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
866      .WillRepeatedly(Return(false));
867  SetupInitializedProfileSyncService();
868  // This should display the sync setup dialog (not login).
869  SetDefaultExpectationsForConfigPage();
870  handler_->OpenSyncSetup();
871
872  ExpectConfig();
873}
874
875// We do not display signin on chromeos in the case of auth error.
876TEST_F(SyncSetupHandlerTest, ShowSigninOnAuthError) {
877  // Initialize the system to a signed in state, but with an auth error.
878  error_ = GoogleServiceAuthError(
879      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
880
881  SetupInitializedProfileSyncService();
882  mock_signin_->SetAuthenticatedUsername(kTestUser);
883  FakeAuthStatusProvider provider(
884      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())->
885          signin_error_controller());
886  provider.SetAuthError(kTestUser, kTestUser, error_);
887  EXPECT_CALL(*mock_pss_, IsSyncEnabledAndLoggedIn())
888      .WillRepeatedly(Return(true));
889  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
890      .WillRepeatedly(Return(true));
891  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
892      .WillRepeatedly(Return(false));
893  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
894      .WillRepeatedly(Return(false));
895  EXPECT_CALL(*mock_pss_, sync_initialized()).WillRepeatedly(Return(false));
896
897#if defined(OS_CHROMEOS)
898  // On ChromeOS, auth errors are ignored - instead we just try to start the
899  // sync backend (which will fail due to the auth error). This should only
900  // happen if the user manually navigates to chrome://settings/syncSetup -
901  // clicking on the button in the UI will sign the user out rather than
902  // displaying a spinner. Should be no visible UI on ChromeOS in this case.
903  EXPECT_EQ(NULL, LoginUIServiceFactory::GetForProfile(
904      profile_.get())->current_login_ui());
905#else
906
907  // On ChromeOS, this should display the spinner while we try to startup the
908  // sync backend, and on desktop this displays the login dialog.
909  handler_->OpenSyncSetup();
910
911  // Sync setup is closed when re-auth is in progress.
912  EXPECT_EQ(NULL,
913            LoginUIServiceFactory::GetForProfile(
914                profile_.get())->current_login_ui());
915
916  ASSERT_FALSE(handler_->is_configuring_sync());
917#endif
918}
919
920TEST_F(SyncSetupHandlerTest, ShowSetupSyncEverything) {
921  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
922      .WillRepeatedly(Return(false));
923  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
924      .WillRepeatedly(Return(false));
925  SetupInitializedProfileSyncService();
926  SetDefaultExpectationsForConfigPage();
927  // This should display the sync setup dialog (not login).
928  handler_->OpenSyncSetup();
929
930  ExpectConfig();
931  const TestWebUI::CallData& data = web_ui_.call_data()[0];
932  base::DictionaryValue* dictionary;
933  ASSERT_TRUE(data.arg2->GetAsDictionary(&dictionary));
934  CheckBool(dictionary, "showSyncEverythingPage", false);
935  CheckBool(dictionary, "syncAllDataTypes", true);
936  CheckBool(dictionary, "appsRegistered", true);
937  CheckBool(dictionary, "autofillRegistered", true);
938  CheckBool(dictionary, "bookmarksRegistered", true);
939  CheckBool(dictionary, "extensionsRegistered", true);
940  CheckBool(dictionary, "passwordsRegistered", true);
941  CheckBool(dictionary, "preferencesRegistered", true);
942  CheckBool(dictionary, "tabsRegistered", true);
943  CheckBool(dictionary, "themesRegistered", true);
944  CheckBool(dictionary, "typedUrlsRegistered", true);
945  CheckBool(dictionary, "showPassphrase", false);
946  CheckBool(dictionary, "usePassphrase", false);
947  CheckBool(dictionary, "passphraseFailed", false);
948  CheckBool(dictionary, "encryptAllData", false);
949  CheckConfigDataTypeArguments(dictionary, SYNC_ALL_DATA, GetAllTypes());
950}
951
952TEST_F(SyncSetupHandlerTest, ShowSetupManuallySyncAll) {
953  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
954      .WillRepeatedly(Return(false));
955  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
956      .WillRepeatedly(Return(false));
957  SetupInitializedProfileSyncService();
958  sync_driver::SyncPrefs sync_prefs(profile_->GetPrefs());
959  sync_prefs.SetKeepEverythingSynced(false);
960  SetDefaultExpectationsForConfigPage();
961  // This should display the sync setup dialog (not login).
962  handler_->OpenSyncSetup();
963
964  ExpectConfig();
965  const TestWebUI::CallData& data = web_ui_.call_data()[0];
966  base::DictionaryValue* dictionary;
967  ASSERT_TRUE(data.arg2->GetAsDictionary(&dictionary));
968  CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, GetAllTypes());
969}
970
971TEST_F(SyncSetupHandlerTest, ShowSetupSyncForAllTypesIndividually) {
972  syncer::ModelTypeSet user_selectable_types = GetAllTypes();
973  syncer::ModelTypeSet::Iterator it;
974  for (it = user_selectable_types.First(); it.Good(); it.Inc()) {
975    EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
976        .WillRepeatedly(Return(false));
977    EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
978        .WillRepeatedly(Return(false));
979    SetupInitializedProfileSyncService();
980    sync_driver::SyncPrefs sync_prefs(profile_->GetPrefs());
981    sync_prefs.SetKeepEverythingSynced(false);
982    SetDefaultExpectationsForConfigPage();
983    syncer::ModelTypeSet types;
984    types.Put(it.Get());
985    EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()).
986        WillRepeatedly(Return(types));
987
988    // This should display the sync setup dialog (not login).
989    handler_->OpenSyncSetup();
990
991    ExpectConfig();
992    // Close the config overlay.
993    LoginUIServiceFactory::GetForProfile(profile_.get())->LoginUIClosed(
994        handler_.get());
995    const TestWebUI::CallData& data = web_ui_.call_data()[0];
996    base::DictionaryValue* dictionary;
997    ASSERT_TRUE(data.arg2->GetAsDictionary(&dictionary));
998    CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, types);
999    Mock::VerifyAndClearExpectations(mock_pss_);
1000    // Clean up so we can loop back to display the dialog again.
1001    web_ui_.ClearTrackedCalls();
1002  }
1003}
1004
1005TEST_F(SyncSetupHandlerTest, ShowSetupGaiaPassphraseRequired) {
1006  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
1007      .WillRepeatedly(Return(true));
1008  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
1009      .WillRepeatedly(Return(false));
1010  SetupInitializedProfileSyncService();
1011  SetDefaultExpectationsForConfigPage();
1012
1013  // This should display the sync setup dialog (not login).
1014  handler_->OpenSyncSetup();
1015
1016  ExpectConfig();
1017  const TestWebUI::CallData& data = web_ui_.call_data()[0];
1018  base::DictionaryValue* dictionary;
1019  ASSERT_TRUE(data.arg2->GetAsDictionary(&dictionary));
1020  CheckBool(dictionary, "showPassphrase", true);
1021  CheckBool(dictionary, "usePassphrase", false);
1022  CheckBool(dictionary, "passphraseFailed", false);
1023}
1024
1025TEST_F(SyncSetupHandlerTest, ShowSetupCustomPassphraseRequired) {
1026  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
1027      .WillRepeatedly(Return(true));
1028  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
1029      .WillRepeatedly(Return(true));
1030  EXPECT_CALL(*mock_pss_, GetPassphraseType())
1031      .WillRepeatedly(Return(syncer::CUSTOM_PASSPHRASE));
1032  SetupInitializedProfileSyncService();
1033  SetDefaultExpectationsForConfigPage();
1034
1035  // This should display the sync setup dialog (not login).
1036  handler_->OpenSyncSetup();
1037
1038  ExpectConfig();
1039  const TestWebUI::CallData& data = web_ui_.call_data()[0];
1040  base::DictionaryValue* dictionary;
1041  ASSERT_TRUE(data.arg2->GetAsDictionary(&dictionary));
1042  CheckBool(dictionary, "showPassphrase", true);
1043  CheckBool(dictionary, "usePassphrase", true);
1044  CheckBool(dictionary, "passphraseFailed", false);
1045}
1046
1047TEST_F(SyncSetupHandlerTest, ShowSetupEncryptAll) {
1048  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
1049      .WillRepeatedly(Return(false));
1050  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
1051      .WillRepeatedly(Return(false));
1052  SetupInitializedProfileSyncService();
1053  SetDefaultExpectationsForConfigPage();
1054  EXPECT_CALL(*mock_pss_, EncryptEverythingEnabled()).
1055      WillRepeatedly(Return(true));
1056
1057  // This should display the sync setup dialog (not login).
1058  handler_->OpenSyncSetup();
1059
1060  ExpectConfig();
1061  const TestWebUI::CallData& data = web_ui_.call_data()[0];
1062  base::DictionaryValue* dictionary;
1063  ASSERT_TRUE(data.arg2->GetAsDictionary(&dictionary));
1064  CheckBool(dictionary, "encryptAllData", true);
1065}
1066
1067TEST_F(SyncSetupHandlerTest, ShowSetupEncryptAllDisallowed) {
1068  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
1069      .WillRepeatedly(Return(false));
1070  EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
1071      .WillRepeatedly(Return(false));
1072  SetupInitializedProfileSyncService();
1073  SetDefaultExpectationsForConfigPage();
1074  EXPECT_CALL(*mock_pss_, EncryptEverythingAllowed()).
1075      WillRepeatedly(Return(false));
1076
1077  // This should display the sync setup dialog (not login).
1078  handler_->OpenSyncSetup();
1079
1080  ExpectConfig();
1081  const TestWebUI::CallData& data = web_ui_.call_data()[0];
1082  base::DictionaryValue* dictionary;
1083  ASSERT_TRUE(data.arg2->GetAsDictionary(&dictionary));
1084  CheckBool(dictionary, "encryptAllData", false);
1085  CheckBool(dictionary, "encryptAllDataAllowed", false);
1086}
1087
1088TEST_F(SyncSetupHandlerTest, TurnOnEncryptAllDisallowed) {
1089  std::string args = GetConfiguration(
1090      NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_ALL_DATA);
1091  base::ListValue list_args;
1092  list_args.Append(new base::StringValue(args));
1093  EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
1094      .WillRepeatedly(Return(false));
1095  EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
1096      .WillRepeatedly(Return(false));
1097  SetupInitializedProfileSyncService();
1098  EXPECT_CALL(*mock_pss_, EncryptEverythingAllowed()).
1099      WillRepeatedly(Return(false));
1100  EXPECT_CALL(*mock_pss_, EnableEncryptEverything()).Times(0);
1101  EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
1102  handler_->HandleConfigure(&list_args);
1103
1104  // Ensure that we navigated to the "done" state since we don't need a
1105  // passphrase.
1106  ExpectDone();
1107}
1108
1109