Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / sync / one_click_signin_helper_unittest.cc
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 "base/prefs/pref_service.h"
6 #include "base/prefs/scoped_user_pref_update.h"
7 #include "base/run_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/values.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/content_settings/cookie_settings.h"
12 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/profiles/profile_info_cache.h"
15 #include "chrome/browser/profiles/profile_io_data.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/signin/chrome_signin_client.h"
18 #include "chrome/browser/signin/chrome_signin_client_factory.h"
19 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
20 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
21 #include "chrome/browser/signin/fake_signin_manager.h"
22 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
23 #include "chrome/browser/signin/signin_manager_factory.h"
24 #include "chrome/browser/signin/signin_names_io_thread.h"
25 #include "chrome/browser/signin/signin_promo.h"
26 #include "chrome/browser/sync/profile_sync_service_factory.h"
27 #include "chrome/browser/sync/test_profile_sync_service.h"
28 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
29 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
30 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
33 #include "chrome/test/base/testing_browser_process.h"
34 #include "chrome/test/base/testing_pref_service_syncable.h"
35 #include "chrome/test/base/testing_profile.h"
36 #include "chrome/test/base/testing_profile_manager.h"
37 #include "components/autofill/core/common/password_form.h"
38 #include "components/signin/core/browser/profile_oauth2_token_service.h"
39 #include "components/signin/core/browser/signin_manager.h"
40 #include "components/sync_driver/pref_names.h"
41 #include "content/public/browser/browser_context.h"
42 #include "content/public/browser/navigation_details.h"
43 #include "content/public/browser/navigation_entry.h"
44 #include "content/public/browser/web_contents.h"
45 #include "content/public/browser/web_contents_delegate.h"
46 #include "content/public/common/frame_navigate_params.h"
47 #include "content/public/common/url_constants.h"
48 #include "content/public/test/mock_render_process_host.h"
49 #include "grit/chromium_strings.h"
50 #include "grit/generated_resources.h"
51 #include "testing/gmock/include/gmock/gmock.h"
52 #include "testing/gtest/include/gtest/gtest.h"
53 #include "ui/base/l10n/l10n_util.h"
54
55 using ::testing::_;
56 using ::testing::AtLeast;
57 using ::testing::Return;
58
59 namespace {
60
61 // Used to confirm OneClickSigninHelper does not trigger redirect when there is
62 // a pending navigation.
63 class MockWebContentsDelegate : public content::WebContentsDelegate {
64  public:
65    MOCK_METHOD2(OpenURLFromTab,
66                 content::WebContents*(content::WebContents* source,
67                                       const content::OpenURLParams& params));
68 };
69
70 class SigninManagerMock : public FakeSigninManager {
71  public:
72   explicit SigninManagerMock(Profile* profile) : FakeSigninManager(profile) {
73     Initialize(NULL);
74   }
75   MOCK_CONST_METHOD1(IsAllowedUsername, bool(const std::string& username));
76 };
77
78 static KeyedService* BuildSigninManagerMock(content::BrowserContext* profile) {
79   return new SigninManagerMock(static_cast<Profile*>(profile));
80 }
81
82 class TestProfileIOData : public ProfileIOData {
83  public:
84   TestProfileIOData(Profile::ProfileType profile_type,
85                     PrefService* pref_service, PrefService* local_state,
86                     CookieSettings* cookie_settings)
87       : ProfileIOData(profile_type) {
88     // Initialize the IO members required for these tests, but keep them on
89     // this thread since we don't use a background thread here.
90     google_services_username()->Init(prefs::kGoogleServicesUsername,
91                                      pref_service);
92     reverse_autologin_enabled()->Init(prefs::kReverseAutologinEnabled,
93                                       pref_service);
94     one_click_signin_rejected_email_list()->Init(
95         prefs::kReverseAutologinRejectedEmailList, pref_service);
96
97     google_services_username_pattern()->Init(
98         prefs::kGoogleServicesUsernamePattern, local_state);
99
100     sync_disabled()->Init(sync_driver::prefs::kSyncManaged, pref_service);
101
102     signin_allowed()->Init(prefs::kSigninAllowed, pref_service);
103
104     set_signin_names_for_testing(new SigninNamesOnIOThread());
105     SetCookieSettingsForTesting(cookie_settings);
106   }
107
108   virtual ~TestProfileIOData() {
109     signin_names()->ReleaseResourcesOnUIThread();
110   }
111
112   // ProfileIOData overrides:
113   virtual void InitializeInternal(
114       ProfileParams* profile_params,
115       content::ProtocolHandlerMap* protocol_handlers,
116       content::ProtocolHandlerScopedVector protocol_interceptors)
117       const OVERRIDE {
118     NOTREACHED();
119   }
120   virtual void InitializeExtensionsRequestContext(
121       ProfileParams* profile_params) const OVERRIDE {
122     NOTREACHED();
123   }
124   virtual ChromeURLRequestContext* InitializeAppRequestContext(
125       ChromeURLRequestContext* main_context,
126       const StoragePartitionDescriptor& details,
127       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
128           protocol_handler_interceptor,
129       content::ProtocolHandlerMap* protocol_handlers,
130       content::ProtocolHandlerScopedVector protocol_interceptors)
131       const OVERRIDE {
132     NOTREACHED();
133     return NULL;
134   }
135   virtual ChromeURLRequestContext* InitializeMediaRequestContext(
136       ChromeURLRequestContext* original_context,
137       const StoragePartitionDescriptor& details) const OVERRIDE {
138     NOTREACHED();
139     return NULL;
140   }
141   virtual ChromeURLRequestContext*
142       AcquireMediaRequestContext() const OVERRIDE {
143     NOTREACHED();
144     return NULL;
145   }
146   virtual ChromeURLRequestContext* AcquireIsolatedAppRequestContext(
147       ChromeURLRequestContext* main_context,
148       const StoragePartitionDescriptor& partition_descriptor,
149       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
150           protocol_handler_interceptor,
151       content::ProtocolHandlerMap* protocol_handlers,
152       content::ProtocolHandlerScopedVector protocol_interceptors)
153       const OVERRIDE {
154     NOTREACHED();
155     return NULL;
156   }
157   virtual ChromeURLRequestContext*
158       AcquireIsolatedMediaRequestContext(
159           ChromeURLRequestContext* app_context,
160           const StoragePartitionDescriptor& partition_descriptor)
161           const OVERRIDE {
162     NOTREACHED();
163     return NULL;
164   }
165 };
166
167 class TestURLRequest : public base::SupportsUserData {
168 public:
169   TestURLRequest() {}
170   virtual ~TestURLRequest() {}
171 };
172
173 class OneClickTestProfileSyncService : public TestProfileSyncService {
174  public:
175   virtual ~OneClickTestProfileSyncService() {}
176
177   // Helper routine to be used in conjunction with
178   // BrowserContextKeyedServiceFactory::SetTestingFactory().
179   static KeyedService* Build(content::BrowserContext* profile) {
180     return new OneClickTestProfileSyncService(static_cast<Profile*>(profile));
181   }
182
183   // Need to control this for certain tests.
184   virtual bool FirstSetupInProgress() const OVERRIDE {
185     return first_setup_in_progress_;
186   }
187
188   virtual bool sync_initialized() const OVERRIDE { return sync_initialized_; }
189
190   // Controls return value of FirstSetupInProgress. Because some bits
191   // of UI depend on that value, it's useful to control it separately
192   // from the internal work and components that are triggered (such as
193   // ReconfigureDataTypeManager) to facilitate unit tests.
194   void set_first_setup_in_progress(bool in_progress) {
195     first_setup_in_progress_ = in_progress;
196   }
197
198   void set_sync_initialized(bool initialized) {
199     sync_initialized_ = initialized;
200   }
201
202  private:
203   explicit OneClickTestProfileSyncService(Profile* profile)
204       : TestProfileSyncService(
205           NULL,
206           profile,
207           SigninManagerFactory::GetForProfile(profile),
208           ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
209           browser_sync::MANUAL_START),
210         first_setup_in_progress_(false),
211         sync_initialized_(false) {}
212
213   bool first_setup_in_progress_;
214   bool sync_initialized_;
215 };
216
217 }  // namespace
218
219 class OneClickSigninHelperTest : public ChromeRenderViewHostTestHarness {
220  public:
221   OneClickSigninHelperTest();
222
223   virtual void SetUp() OVERRIDE;
224   virtual void TearDown() OVERRIDE;
225
226   // Sets up the sign-in manager for tests.  If |username| is
227   // is not empty, the profile of the mock WebContents will be connected to
228   // the given account.
229   void SetUpSigninManager(const std::string& username);
230
231   // Set the ID of the signin process that the test will assume to be the
232   // only process allowed to sign the user in to Chrome.
233   void SetTrustedSigninProcessID(int id);
234
235   void AddEmailToOneClickRejectedList(const std::string& email);
236   void EnableOneClick(bool enable);
237   void AllowSigninCookies(bool enable);
238   void SetAllowedUsernamePattern(const std::string& pattern);
239   void SubmitGAIAPassword(OneClickSigninHelper* helper);
240
241   SigninManagerMock* signin_manager_;
242   FakeProfileOAuth2TokenService* fake_oauth2_token_service_;
243
244  protected:
245   GoogleServiceAuthError no_error_;
246
247  private:
248   // ChromeRenderViewHostTestHarness overrides:
249   virtual content::BrowserContext* CreateBrowserContext() OVERRIDE;
250
251   // The ID of the signin process the test will assume to be trusted.
252   // By default, set to the test RenderProcessHost's process ID, but
253   // overridden by SetTrustedSigninProcessID.
254   int trusted_signin_process_id_;
255
256   DISALLOW_COPY_AND_ASSIGN(OneClickSigninHelperTest);
257 };
258
259 OneClickSigninHelperTest::OneClickSigninHelperTest()
260     : signin_manager_(NULL),
261       fake_oauth2_token_service_(NULL),
262       no_error_(GoogleServiceAuthError::NONE),
263       trusted_signin_process_id_(-1) {
264 }
265
266 void OneClickSigninHelperTest::SetUp() {
267   signin::ForceWebBasedSigninFlowForTesting(true);
268   content::RenderViewHostTestHarness::SetUp();
269   SetTrustedSigninProcessID(process()->GetID());
270 }
271
272 void OneClickSigninHelperTest::TearDown() {
273   signin::ForceWebBasedSigninFlowForTesting(false);
274   content::RenderViewHostTestHarness::TearDown();
275 }
276
277 void OneClickSigninHelperTest::SetTrustedSigninProcessID(int id) {
278   trusted_signin_process_id_ = id;
279 }
280
281 void OneClickSigninHelperTest::SetUpSigninManager(const std::string& username) {
282   ChromeSigninClient* signin_client =
283       ChromeSigninClientFactory::GetForProfile(profile());
284   if (signin_client)
285     signin_client->SetSigninProcess(trusted_signin_process_id_);
286
287   signin_manager_ = static_cast<SigninManagerMock*>(
288       SigninManagerFactory::GetForProfile(profile()));
289   if (!username.empty()) {
290     ASSERT_TRUE(signin_manager_);
291     signin_manager_->SetAuthenticatedUsername(username);
292   }
293 }
294
295 void OneClickSigninHelperTest::EnableOneClick(bool enable) {
296   PrefService* pref_service = profile()->GetPrefs();
297   pref_service->SetBoolean(prefs::kReverseAutologinEnabled, enable);
298 }
299
300 void OneClickSigninHelperTest::AddEmailToOneClickRejectedList(
301     const std::string& email) {
302   PrefService* pref_service = profile()->GetPrefs();
303   ListPrefUpdate updater(pref_service,
304                          prefs::kReverseAutologinRejectedEmailList);
305   updater->AppendIfNotPresent(new base::StringValue(email));
306 }
307
308 void OneClickSigninHelperTest::AllowSigninCookies(bool enable) {
309   CookieSettings* cookie_settings =
310       CookieSettings::Factory::GetForProfile(profile()).get();
311   cookie_settings->SetDefaultCookieSetting(enable ? CONTENT_SETTING_ALLOW
312                                                   : CONTENT_SETTING_BLOCK);
313 }
314
315 void OneClickSigninHelperTest::SetAllowedUsernamePattern(
316     const std::string& pattern) {
317   PrefService* local_state = g_browser_process->local_state();
318   local_state->SetString(prefs::kGoogleServicesUsernamePattern, pattern);
319 }
320
321 void OneClickSigninHelperTest::SubmitGAIAPassword(
322     OneClickSigninHelper* helper) {
323   autofill::PasswordForm password_form;
324   password_form.origin = GURL("https://accounts.google.com");
325   password_form.signon_realm = "https://accounts.google.com";
326   password_form.password_value = base::UTF8ToUTF16("password");
327   helper->PasswordSubmitted(password_form);
328 }
329
330 content::BrowserContext* OneClickSigninHelperTest::CreateBrowserContext() {
331   TestingProfile::Builder builder;
332   builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
333                             BuildFakeProfileOAuth2TokenService);
334   builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
335                             BuildSigninManagerMock);
336   scoped_ptr<TestingProfile> profile = builder.Build();
337
338   fake_oauth2_token_service_ =
339       static_cast<FakeProfileOAuth2TokenService*>(
340           ProfileOAuth2TokenServiceFactory::GetForProfile(profile.get()));
341
342   return profile.release();
343 }
344
345 class OneClickSigninHelperIOTest : public OneClickSigninHelperTest {
346  public:
347   OneClickSigninHelperIOTest();
348
349   virtual void SetUp() OVERRIDE;
350
351   TestProfileIOData* CreateTestProfileIOData(Profile::ProfileType profile_type);
352
353  protected:
354   TestingProfileManager testing_profile_manager_;
355   TestURLRequest request_;
356   const GURL valid_gaia_url_;
357
358  private:
359   DISALLOW_COPY_AND_ASSIGN(OneClickSigninHelperIOTest);
360 };
361
362 OneClickSigninHelperIOTest::OneClickSigninHelperIOTest()
363     : testing_profile_manager_(
364           TestingBrowserProcess::GetGlobal()),
365       valid_gaia_url_("https://accounts.google.com/") {
366 }
367
368 void OneClickSigninHelperIOTest::SetUp() {
369   OneClickSigninHelperTest::SetUp();
370   ASSERT_TRUE(testing_profile_manager_.SetUp());
371 }
372
373 TestProfileIOData* OneClickSigninHelperIOTest::CreateTestProfileIOData(
374     Profile::ProfileType profile_type) {
375   PrefService* pref_service = profile()->GetPrefs();
376   PrefService* local_state = g_browser_process->local_state();
377   CookieSettings* cookie_settings =
378       CookieSettings::Factory::GetForProfile(profile()).get();
379   TestProfileIOData* io_data = new TestProfileIOData(
380       profile_type, pref_service, local_state, cookie_settings);
381   io_data->set_reverse_autologin_pending_email("user@gmail.com");
382   return io_data;
383 }
384
385 class OneClickSigninHelperIncognitoTest : public OneClickSigninHelperTest {
386  protected:
387   // content::RenderViewHostTestHarness.
388   virtual content::BrowserContext* CreateBrowserContext() OVERRIDE;
389 };
390
391 content::BrowserContext*
392 OneClickSigninHelperIncognitoTest::CreateBrowserContext() {
393   // Builds an incognito profile to run this test.
394   TestingProfile::Builder builder;
395   builder.SetIncognito();
396   return builder.Build().release();
397 }
398
399 TEST_F(OneClickSigninHelperTest, CanOfferNoContents) {
400   std::string error_message;
401   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
402       NULL, OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
403       "user@gmail.com", &error_message));
404   EXPECT_EQ("", error_message);
405   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
406       NULL, OneClickSigninHelper::CAN_OFFER_FOR_ALL,
407       "user@gmail.com", &error_message));
408   EXPECT_EQ("", error_message);
409   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
410       NULL,
411       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
412       std::string(),
413       &error_message));
414   EXPECT_EQ("", error_message);
415 }
416
417 TEST_F(OneClickSigninHelperTest, CanOffer) {
418   SetUpSigninManager(std::string());
419
420   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
421         WillRepeatedly(Return(true));
422
423   EnableOneClick(true);
424   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
425       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
426       "user@gmail.com", NULL));
427   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
428       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
429       "user@gmail.com", NULL));
430   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
431       web_contents(),
432       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
433       std::string(),
434       NULL));
435
436   EnableOneClick(false);
437
438   std::string error_message;
439   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
440       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
441       "user@gmail.com", &error_message));
442   EXPECT_EQ("", error_message);
443
444   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
445       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
446       "user@gmail.com", &error_message));
447   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
448       web_contents(),
449       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
450       std::string(),
451       &error_message));
452   EXPECT_EQ("", error_message);
453 }
454
455 TEST_F(OneClickSigninHelperTest, CanOfferFirstSetup) {
456   SetUpSigninManager(std::string());
457
458   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
459         WillRepeatedly(Return(true));
460
461   // Invoke OneClickTestProfileSyncService factory function and grab result.
462   OneClickTestProfileSyncService* sync =
463       static_cast<OneClickTestProfileSyncService*>(
464           ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
465               profile(), OneClickTestProfileSyncService::Build));
466   sync->set_sync_initialized(false);
467   sync->Initialize();
468   sync->set_sync_initialized(true);
469   sync->set_first_setup_in_progress(true);
470
471   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
472       web_contents(),
473       OneClickSigninHelper::CAN_OFFER_FOR_ALL,
474       "foo@gmail.com", NULL));
475   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
476       web_contents(),
477       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
478       "foo@gmail.com", NULL));
479   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
480       web_contents(),
481       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
482       std::string(),
483       NULL));
484 }
485
486 TEST_F(OneClickSigninHelperTest, CanOfferProfileConnected) {
487   SetUpSigninManager("foo@gmail.com");
488
489   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
490       WillRepeatedly(Return(true));
491
492   std::string error_message;
493   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
494       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
495       "foo@gmail.com", &error_message));
496   EXPECT_EQ("", error_message);
497   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
498       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
499       "foo", &error_message));
500   EXPECT_EQ("", error_message);
501   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
502       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
503       "user@gmail.com", &error_message));
504   EXPECT_EQ(l10n_util::GetStringFUTF8(IDS_SYNC_WRONG_EMAIL,
505                                       base::UTF8ToUTF16("foo@gmail.com")),
506             error_message);
507   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
508       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
509       "foo@gmail.com", &error_message));
510   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
511       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
512       "foo", &error_message));
513   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
514       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
515       "user@gmail.com", &error_message));
516   EXPECT_EQ(l10n_util::GetStringFUTF8(IDS_SYNC_WRONG_EMAIL,
517                                       base::UTF8ToUTF16("foo@gmail.com")),
518             error_message);
519   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
520       web_contents(),
521       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
522       std::string(),
523       &error_message));
524 }
525
526 TEST_F(OneClickSigninHelperTest, CanOfferUsernameNotAllowed) {
527   SetUpSigninManager(std::string());
528
529   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
530       WillRepeatedly(Return(false));
531
532   std::string error_message;
533   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
534       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
535       "foo@gmail.com", &error_message));
536   EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SYNC_LOGIN_NAME_PROHIBITED),
537             error_message);
538   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
539       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
540       "foo@gmail.com", &error_message));
541   EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SYNC_LOGIN_NAME_PROHIBITED),
542             error_message);
543   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
544       web_contents(),
545       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
546       std::string(),
547       &error_message));
548 }
549
550 TEST_F(OneClickSigninHelperTest, CanOfferWithRejectedEmail) {
551   SetUpSigninManager(std::string());
552
553   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
554         WillRepeatedly(Return(true));
555
556   AddEmailToOneClickRejectedList("foo@gmail.com");
557   AddEmailToOneClickRejectedList("user@gmail.com");
558
559   std::string error_message;
560   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
561       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
562       "foo@gmail.com", &error_message));
563   EXPECT_EQ("", error_message);
564   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
565       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
566       "user@gmail.com", &error_message));
567   EXPECT_EQ("", error_message);
568   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
569       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
570       "foo@gmail.com", &error_message));
571   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
572       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
573       "user@gmail.com", &error_message));
574   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
575       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
576       "john@gmail.com", &error_message));
577 }
578
579 TEST_F(OneClickSigninHelperIncognitoTest, CanOfferIncognito) {
580   SetUpSigninManager(std::string());
581
582   std::string error_message;
583   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
584       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
585       "user@gmail.com", &error_message));
586   EXPECT_EQ("", error_message);
587   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
588       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
589       "user@gmail.com", &error_message));
590   EXPECT_EQ("", error_message);
591   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
592       web_contents(),
593       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
594       std::string(),
595       &error_message));
596   EXPECT_EQ("", error_message);
597 }
598
599 TEST_F(OneClickSigninHelperTest, CanOfferNoSigninCookies) {
600   SetUpSigninManager(std::string());
601   AllowSigninCookies(false);
602
603   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
604         WillRepeatedly(Return(true));
605
606   std::string error_message;
607   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
608       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
609       "user@gmail.com", &error_message));
610   EXPECT_EQ("", error_message);
611   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
612       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
613       "user@gmail.com", &error_message));
614   EXPECT_EQ("", error_message);
615   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
616       web_contents(),
617       OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY,
618       std::string(),
619       &error_message));
620   EXPECT_EQ("", error_message);
621 }
622
623 TEST_F(OneClickSigninHelperTest, CanOfferDisabledByPolicy) {
624   SetUpSigninManager(std::string());
625
626   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
627         WillRepeatedly(Return(true));
628
629   EnableOneClick(true);
630   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
631       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
632       "user@gmail.com", NULL));
633
634   // Simulate a policy disabling signin by writing kSigninAllowed directly.
635   profile()->GetTestingPrefService()->SetManagedPref(
636       prefs::kSigninAllowed, base::Value::CreateBooleanValue(false));
637
638   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
639       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
640       "user@gmail.com", NULL));
641
642   // Reset the preference value to true.
643   profile()->GetTestingPrefService()->SetManagedPref(
644       prefs::kSigninAllowed, base::Value::CreateBooleanValue(true));
645
646   // Simulate a policy disabling sync by writing kSyncManaged directly.
647   profile()->GetTestingPrefService()->SetManagedPref(
648       sync_driver::prefs::kSyncManaged, base::Value::CreateBooleanValue(true));
649
650   // Should still offer even if sync is disabled by policy.
651   EXPECT_TRUE(OneClickSigninHelper::CanOffer(
652       web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL,
653       "user@gmail.com", NULL));
654 }
655
656 // Should not crash if a helper instance is not associated with an incognito
657 // web contents.
658 TEST_F(OneClickSigninHelperIncognitoTest, ShowInfoBarUIThreadIncognito) {
659   SetUpSigninManager(std::string());
660   OneClickSigninHelper* helper =
661       OneClickSigninHelper::FromWebContents(web_contents());
662   EXPECT_EQ(NULL, helper);
663
664   OneClickSigninHelper::ShowInfoBarUIThread(
665       "session_index", "email", OneClickSigninHelper::AUTO_ACCEPT_ACCEPTED,
666       signin::SOURCE_UNKNOWN, GURL(), process()->GetID(),
667       rvh()->GetRoutingID());
668 }
669
670 // If Chrome signin is triggered from a webstore install, and user chooses to
671 // config sync, then Chrome should redirect immediately to sync settings page,
672 // and upon successful setup, redirect back to webstore.
673 TEST_F(OneClickSigninHelperTest, SigninFromWebstoreWithConfigSyncfirst) {
674   SetUpSigninManager(std::string());
675   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_))
676       .WillRepeatedly(Return(true));
677
678   OneClickTestProfileSyncService* sync_service =
679       static_cast<OneClickTestProfileSyncService*>(
680           ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
681               profile(), OneClickTestProfileSyncService::Build));
682   sync_service->set_sync_initialized(true);
683
684   content::WebContents* contents = web_contents();
685
686   OneClickSigninHelper::CreateForWebContentsWithPasswordManager(contents, NULL);
687   OneClickSigninHelper* helper =
688       OneClickSigninHelper::FromWebContents(contents);
689   helper->SetDoNotClearPendingEmailForTesting();
690   helper->set_do_not_start_sync_for_testing();
691
692   GURL continueUrl("https://chrome.google.com/webstore?source=5");
693   OneClickSigninHelper::ShowInfoBarUIThread(
694       "session_index", "user@gmail.com",
695       OneClickSigninHelper::AUTO_ACCEPT_EXPLICIT,
696       signin::SOURCE_WEBSTORE_INSTALL,
697       continueUrl, process()->GetID(), rvh()->GetRoutingID());
698
699   SubmitGAIAPassword(helper);
700
701   NavigateAndCommit(GURL("https://chrome.google.com/webstore?source=3"));
702   helper->DidStopLoading(rvh());
703   sync_service->NotifyObservers();
704   EXPECT_EQ(GURL(continueUrl), contents->GetVisibleURL());
705 }
706
707 // Checks that the state of OneClickSigninHelper is cleaned when there is a
708 // navigation away from the sign in flow that is not triggered by the
709 // web contents.
710 TEST_F(OneClickSigninHelperTest, CleanTransientStateOnNavigate) {
711   content::WebContents* contents = web_contents();
712
713   OneClickSigninHelper::CreateForWebContentsWithPasswordManager(contents, NULL);
714   OneClickSigninHelper* helper =
715       OneClickSigninHelper::FromWebContents(contents);
716   helper->SetDoNotClearPendingEmailForTesting();
717   helper->auto_accept_ = OneClickSigninHelper::AUTO_ACCEPT_EXPLICIT;
718
719   content::LoadCommittedDetails details;
720   content::FrameNavigateParams params;
721   params.url = GURL("http://crbug.com");
722   params.transition = content::PAGE_TRANSITION_TYPED;
723   helper->DidNavigateMainFrame(details, params);
724
725   EXPECT_EQ(OneClickSigninHelper::AUTO_ACCEPT_NONE, helper->auto_accept_);
726 }
727
728 TEST_F(OneClickSigninHelperTest, NoRedirectToNTPWithPendingEntry) {
729   content::NavigationController& controller = web_contents()->GetController();
730   EXPECT_FALSE(controller.GetPendingEntry());
731
732   const GURL fooWebUIURL("chrome://foo");
733   controller.LoadURL(fooWebUIURL, content::Referrer(),
734                      content::PAGE_TRANSITION_TYPED, std::string());
735   EXPECT_EQ(fooWebUIURL, controller.GetPendingEntry()->GetURL());
736
737   MockWebContentsDelegate delegate;
738   EXPECT_CALL(delegate, OpenURLFromTab(_, _)).Times(0);
739   web_contents()->SetDelegate(&delegate);
740   OneClickSigninHelper::RedirectToNtpOrAppsPage(
741       web_contents(), signin::SOURCE_UNKNOWN);
742
743   EXPECT_EQ(fooWebUIURL, controller.GetPendingEntry()->GetURL());
744 }
745
746 // I/O thread tests
747
748 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThread) {
749   scoped_ptr<TestProfileIOData> io_data(
750       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
751   EXPECT_EQ(OneClickSigninHelper::CAN_OFFER,
752             OneClickSigninHelper::CanOfferOnIOThreadImpl(
753                 valid_gaia_url_, &request_, io_data.get()));
754 }
755
756 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadIncognito) {
757   scoped_ptr<TestProfileIOData> io_data(
758       CreateTestProfileIOData(Profile::INCOGNITO_PROFILE));
759   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
760             OneClickSigninHelper::CanOfferOnIOThreadImpl(
761                 valid_gaia_url_, &request_, io_data.get()));
762 }
763
764 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadNoIOData) {
765   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
766             OneClickSigninHelper::CanOfferOnIOThreadImpl(
767                 valid_gaia_url_, &request_, NULL));
768 }
769
770 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadBadURL) {
771   scoped_ptr<TestProfileIOData> io_data(
772       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
773   EXPECT_EQ(
774       OneClickSigninHelper::IGNORE_REQUEST,
775       OneClickSigninHelper::CanOfferOnIOThreadImpl(
776           GURL("https://foo.com/"), &request_, io_data.get()));
777   EXPECT_EQ(OneClickSigninHelper::IGNORE_REQUEST,
778             OneClickSigninHelper::CanOfferOnIOThreadImpl(
779                 GURL("http://accounts.google.com/"),
780                 &request_,
781                 io_data.get()));
782 }
783
784 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadDisabled) {
785   EnableOneClick(false);
786   scoped_ptr<TestProfileIOData> io_data(
787       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
788   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
789             OneClickSigninHelper::CanOfferOnIOThreadImpl(
790                 valid_gaia_url_, &request_, io_data.get()));
791 }
792
793 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadSignedIn) {
794   PrefService* pref_service = profile()->GetPrefs();
795   pref_service->SetString(prefs::kGoogleServicesUsername, "user@gmail.com");
796
797   scoped_ptr<TestProfileIOData> io_data(
798       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
799   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
800             OneClickSigninHelper::CanOfferOnIOThreadImpl(
801                 valid_gaia_url_, &request_, io_data.get()));
802 }
803
804 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadEmailNotAllowed) {
805   SetAllowedUsernamePattern("*@example.com");
806   scoped_ptr<TestProfileIOData> io_data(
807       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
808   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
809             OneClickSigninHelper::CanOfferOnIOThreadImpl(
810                 valid_gaia_url_,  &request_, io_data.get()));
811 }
812
813 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadEmailAlreadyUsed) {
814   ProfileInfoCache* cache = testing_profile_manager_.profile_info_cache();
815   const base::FilePath& user_data_dir = cache->GetUserDataDir();
816   cache->AddProfileToCache(user_data_dir.Append(FILE_PATH_LITERAL("user")),
817                            base::UTF8ToUTF16("user"),
818                            base::UTF8ToUTF16("user@gmail.com"), 0,
819                            std::string());
820
821   scoped_ptr<TestProfileIOData> io_data(
822       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
823   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
824             OneClickSigninHelper::CanOfferOnIOThreadImpl(
825                 valid_gaia_url_, &request_, io_data.get()));
826 }
827
828 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadWithRejectedEmail) {
829   AddEmailToOneClickRejectedList("user@gmail.com");
830   scoped_ptr<TestProfileIOData> io_data(
831       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
832   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
833             OneClickSigninHelper::CanOfferOnIOThreadImpl(
834                 valid_gaia_url_, &request_, io_data.get()));
835 }
836
837 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadNoSigninCookies) {
838   AllowSigninCookies(false);
839   scoped_ptr<TestProfileIOData> io_data(
840       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
841   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
842             OneClickSigninHelper::CanOfferOnIOThreadImpl(
843                 valid_gaia_url_, &request_, io_data.get()));
844 }
845
846 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadDisabledByPolicy) {
847   scoped_ptr<TestProfileIOData> io_data(
848       CreateTestProfileIOData(Profile::REGULAR_PROFILE));
849   EXPECT_EQ(OneClickSigninHelper::CAN_OFFER,
850             OneClickSigninHelper::CanOfferOnIOThreadImpl(
851                 valid_gaia_url_, &request_, io_data.get()));
852
853   // Simulate a policy disabling signin by writing kSigninAllowed directly.
854   // We should not offer to sign in the browser.
855   profile()->GetTestingPrefService()->SetManagedPref(
856       prefs::kSigninAllowed, base::Value::CreateBooleanValue(false));
857   EXPECT_EQ(OneClickSigninHelper::DONT_OFFER,
858             OneClickSigninHelper::CanOfferOnIOThreadImpl(
859                 valid_gaia_url_, &request_, io_data.get()));
860
861   // Reset the preference.
862   profile()->GetTestingPrefService()->SetManagedPref(
863       prefs::kSigninAllowed, base::Value::CreateBooleanValue(true));
864
865   // Simulate a policy disabling sync by writing kSyncManaged directly.
866   // We should still offer to sign in the browser.
867   profile()->GetTestingPrefService()->SetManagedPref(
868       sync_driver::prefs::kSyncManaged, base::Value::CreateBooleanValue(true));
869   EXPECT_EQ(OneClickSigninHelper::CAN_OFFER,
870             OneClickSigninHelper::CanOfferOnIOThreadImpl(
871                 valid_gaia_url_, &request_, io_data.get()));
872 }
873
874
875 class MockStarterWrapper
876     : public testing::StrictMock<OneClickSigninHelper::SyncStarterWrapper> {
877  public:
878   MockStarterWrapper(
879       const OneClickSigninHelper::StartSyncArgs& args,
880       OneClickSigninSyncStarter::StartSyncMode start_mode);
881
882   MOCK_METHOD1(DisplayErrorBubble, void(const std::string& error_message));
883   MOCK_METHOD0(StartSigninOAuthHelper, void());
884   MOCK_METHOD2(StartOneClickSigninSyncStarter,
885                void(const std::string& email,
886                     const std::string& refresh_token));
887 };
888
889 MockStarterWrapper::MockStarterWrapper(
890     const OneClickSigninHelper::StartSyncArgs& args,
891     OneClickSigninSyncStarter::StartSyncMode start_mode)
892     : testing::StrictMock<OneClickSigninHelper::SyncStarterWrapper>(
893           args, start_mode) {
894 }
895
896 class OneClickSyncStarterWrapperTest : public testing::Test {
897  public:
898   virtual void SetUp() OVERRIDE {
899     TestingProfile::Builder builder;
900     profile_ = builder.Build();
901   }
902
903   virtual void TearDown() OVERRIDE {
904     // Let the SyncStarterWrapper delete itself.
905     base::RunLoop().RunUntilIdle();
906   }
907
908   void SetCookie(const std::string& value) {
909     // Set a valid LSID cookie in the test cookie store.
910     scoped_refptr<net::CookieMonster> cookie_monster =
911         profile()->GetCookieMonster();
912     net::CookieOptions options;
913     options.set_include_httponly();
914     cookie_monster->SetCookieWithOptionsAsync(
915           GURL("https://accounts.google.com"),
916           value, options,
917           net::CookieMonster::SetCookiesCallback());
918   }
919
920   void SimulateRefreshTokenFetched(
921       SigninOAuthHelper::Consumer* consumer,
922       const std::string& email,
923       const std::string& display_email,
924       const std::string& refresh_token) {
925     consumer->OnSigninOAuthInformationAvailable(
926         email, display_email, refresh_token);
927   }
928
929   TestingProfile* profile() { return profile_.get(); }
930
931  private:
932   content::TestBrowserThreadBundle thread_bundle_;
933   scoped_ptr<TestingProfile> profile_;
934 };
935
936 TEST_F(OneClickSyncStarterWrapperTest, SignInWithRefreshToken) {
937   OneClickSigninHelper::StartSyncArgs args;
938   args.email = "foo@gmail.com";
939   args.password = "password";
940   args.refresh_token = "refresh_token";
941   MockStarterWrapper* wrapper = new MockStarterWrapper(
942       args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
943
944   EXPECT_CALL(*wrapper,
945               StartOneClickSigninSyncStarter("foo@gmail.com",
946                                              "refresh_token"));
947   wrapper->Start();
948 }
949
950 TEST_F(OneClickSyncStarterWrapperTest, SignInWithPasswordNoRefreshToken) {
951   OneClickSigninHelper::StartSyncArgs args;
952   args.email = "foo@gmail.com";
953   args.password = "password";
954   MockStarterWrapper* wrapper = new MockStarterWrapper(
955       args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
956
957   EXPECT_CALL(*wrapper, StartSigninOAuthHelper());
958   EXPECT_CALL(*wrapper,
959               StartOneClickSigninSyncStarter("foo@gmail.com",
960                                              "refresh_token"));
961   wrapper->Start();
962   SimulateRefreshTokenFetched(wrapper, "foo@gmail.com", "foo@gmail.com",
963                               "refresh_token");
964 }
965
966 TEST_F(OneClickSyncStarterWrapperTest, SignInWithWrongEmail) {
967   OneClickSigninHelper::StartSyncArgs args;
968   args.email = "foo@gmail.com";
969   args.password = "password";
970   MockStarterWrapper* wrapper = new MockStarterWrapper(
971       args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
972
973   EXPECT_CALL(*wrapper, StartSigninOAuthHelper());
974   EXPECT_CALL(*wrapper, DisplayErrorBubble(_));
975   wrapper->Start();
976   SimulateRefreshTokenFetched(wrapper, "bar@gmail.com", "bar@gmail.com",
977                               "refresh_token");
978 }
979
980 TEST_F(OneClickSyncStarterWrapperTest, SignInWithEmptyPasswordValidCookie) {
981   OneClickSigninHelper::StartSyncArgs args;
982   args.email = "foo@gmail.com";
983   args.profile = profile();
984   MockStarterWrapper* wrapper = new MockStarterWrapper(
985       args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
986   SetCookie("LSID=1234; secure; httponly");
987
988   EXPECT_CALL(*wrapper, StartSigninOAuthHelper());
989   EXPECT_CALL(*wrapper,
990               StartOneClickSigninSyncStarter("foo@gmail.com",
991                                              "refresh_token"));
992   wrapper->Start();
993   base::RunLoop().RunUntilIdle();
994   SimulateRefreshTokenFetched(wrapper, "foo@gmail.com", "foo@gmail.com",
995                               "refresh_token");
996 }
997
998 TEST_F(OneClickSyncStarterWrapperTest, SignInWithEmptyPasswordNoCookie) {
999   OneClickSigninHelper::StartSyncArgs args;
1000   args.email = "foo@gmail.com";
1001   args.profile = profile();
1002   MockStarterWrapper* wrapper = new MockStarterWrapper(
1003       args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
1004
1005   EXPECT_CALL(*wrapper, DisplayErrorBubble(_));
1006   wrapper->Start();
1007   base::RunLoop().RunUntilIdle();
1008 }
1009
1010 TEST_F(OneClickSyncStarterWrapperTest, SignInWithEmptyPasswordInvalidCookie) {
1011   OneClickSigninHelper::StartSyncArgs args;
1012   args.email = "foo@gmail.com";
1013   args.profile = profile();
1014   MockStarterWrapper* wrapper = new MockStarterWrapper(
1015       args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
1016   SetCookie("LSID=1234; domain=google.com; secure; httponly");
1017
1018   EXPECT_CALL(*wrapper, DisplayErrorBubble(_));
1019   wrapper->Start();
1020   base::RunLoop().RunUntilIdle();
1021 }