Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / sync / one_click_signin_sync_observer_unittest.cc
1 // Copyright 2014 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/sync/one_click_signin_sync_observer.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
10 #include "chrome/browser/signin/signin_manager_factory.h"
11 #include "chrome/browser/signin/signin_promo.h"
12 #include "chrome/browser/sync/profile_sync_service_factory.h"
13 #include "chrome/browser/sync/startup_controller.h"
14 #include "chrome/browser/sync/test_profile_sync_service.h"
15 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "components/signin/core/browser/signin_manager.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/test/test_utils.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using testing::_;
25
26 namespace {
27
28 const char kContinueUrl[] = "https://www.example.com/";
29
30 class MockWebContentsObserver : public content::WebContentsObserver {
31  public:
32   explicit MockWebContentsObserver(content::WebContents* web_contents)
33       : content::WebContentsObserver(web_contents) {}
34   virtual ~MockWebContentsObserver() {}
35
36   // A hook to verify that the OneClickSigninSyncObserver initiated a redirect
37   // to the continue URL. Navigations in unit_tests never complete, but a
38   // navigation start is a sufficient signal for the purposes of this test.
39   // Listening for this call also has the advantage of being synchronous.
40   MOCK_METHOD1(AboutToNavigateRenderView, void(content::RenderViewHost*));
41 };
42
43 class OneClickTestProfileSyncService : public TestProfileSyncService {
44  public:
45   virtual ~OneClickTestProfileSyncService() {}
46
47   // Helper routine to be used in conjunction with
48   // BrowserContextKeyedServiceFactory::SetTestingFactory().
49   static KeyedService* Build(content::BrowserContext* profile) {
50     return new OneClickTestProfileSyncService(static_cast<Profile*>(profile));
51   }
52
53   virtual bool FirstSetupInProgress() const OVERRIDE {
54     return first_setup_in_progress_;
55   }
56
57   virtual bool sync_initialized() const OVERRIDE { return sync_initialized_; }
58
59   void set_first_setup_in_progress(bool in_progress) {
60     first_setup_in_progress_ = in_progress;
61   }
62
63   void set_sync_initialized(bool initialized) {
64     sync_initialized_ = initialized;
65   }
66
67  private:
68   explicit OneClickTestProfileSyncService(Profile* profile)
69       : TestProfileSyncService(
70           NULL,
71           profile,
72           SigninManagerFactory::GetForProfile(profile),
73           ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
74           browser_sync::MANUAL_START),
75         first_setup_in_progress_(false),
76         sync_initialized_(false) {}
77
78   bool first_setup_in_progress_;
79   bool sync_initialized_;
80 };
81
82 class TestOneClickSigninSyncObserver : public OneClickSigninSyncObserver {
83  public:
84   typedef base::Callback<void(TestOneClickSigninSyncObserver*)>
85       DestructionCallback;
86
87   TestOneClickSigninSyncObserver(content::WebContents* web_contents,
88                                  const GURL& continue_url,
89                                  const DestructionCallback& callback)
90       : OneClickSigninSyncObserver(web_contents, continue_url),
91         destruction_callback_(callback) {}
92   virtual ~TestOneClickSigninSyncObserver() { destruction_callback_.Run(this); }
93
94  private:
95   DestructionCallback destruction_callback_;
96
97   DISALLOW_COPY_AND_ASSIGN(TestOneClickSigninSyncObserver);
98 };
99
100 // A trivial factory to build a null service.
101 KeyedService* BuildNullService(content::BrowserContext* context) {
102   return NULL;
103 }
104
105 }  // namespace
106
107 class OneClickSigninSyncObserverTest : public ChromeRenderViewHostTestHarness {
108  public:
109   OneClickSigninSyncObserverTest()
110       : sync_service_(NULL),
111         sync_observer_(NULL),
112         sync_observer_destroyed_(true) {}
113
114   virtual void SetUp() OVERRIDE {
115     ChromeRenderViewHostTestHarness::SetUp();
116     web_contents_observer_.reset(new MockWebContentsObserver(web_contents()));
117     sync_service_ =
118         static_cast<OneClickTestProfileSyncService*>(
119             ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
120                 profile(), OneClickTestProfileSyncService::Build));
121   }
122
123   virtual void TearDown() OVERRIDE {
124     // Verify that the |sync_observer_| unregistered as an observer from the
125     // sync service and freed its memory.
126     EXPECT_TRUE(sync_observer_destroyed_);
127     if (sync_service_)
128       EXPECT_FALSE(sync_service_->HasObserver(sync_observer_));
129     ChromeRenderViewHostTestHarness::TearDown();
130   }
131
132  protected:
133   void CreateSyncObserver(const std::string& url) {
134     sync_observer_ = new TestOneClickSigninSyncObserver(
135       web_contents(), GURL(url),
136       base::Bind(&OneClickSigninSyncObserverTest::OnSyncObserverDestroyed,
137                  base::Unretained(this)));
138     if (sync_service_)
139       EXPECT_TRUE(sync_service_->HasObserver(sync_observer_));
140     EXPECT_TRUE(sync_observer_destroyed_);
141     sync_observer_destroyed_ = false;
142   }
143
144   OneClickTestProfileSyncService* sync_service_;
145   scoped_ptr<MockWebContentsObserver> web_contents_observer_;
146
147  private:
148   void OnSyncObserverDestroyed(TestOneClickSigninSyncObserver* observer) {
149     EXPECT_EQ(sync_observer_, observer);
150     EXPECT_FALSE(sync_observer_destroyed_);
151     sync_observer_destroyed_ = true;
152   }
153
154   TestOneClickSigninSyncObserver* sync_observer_;
155   bool sync_observer_destroyed_;
156 };
157
158 // Verify that if no Sync service is present, e.g. because Sync is disabled, the
159 // observer immediately loads the continue URL.
160 TEST_F(OneClickSigninSyncObserverTest, NoSyncService_RedirectsImmediately) {
161   // Simulate disabling Sync.
162   sync_service_ =
163       static_cast<OneClickTestProfileSyncService*>(
164           ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
165               profile(), BuildNullService));
166
167   // The observer should immediately redirect to the continue URL.
168   EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderView(_));
169   CreateSyncObserver(kContinueUrl);
170   EXPECT_EQ(GURL(kContinueUrl), web_contents()->GetVisibleURL());
171
172   // The |sync_observer_| will be destroyed asynchronously, so manually pump
173   // the message loop to wait for the destruction.
174   content::RunAllPendingInMessageLoop();
175 }
176
177 // Verify that when the WebContents is destroyed without any Sync notifications
178 // firing, the observer cleans up its memory without loading the continue URL.
179 TEST_F(OneClickSigninSyncObserverTest, WebContentsDestroyed) {
180   EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderView(_)).Times(0);
181   CreateSyncObserver(kContinueUrl);
182   SetContents(NULL);
183 }
184
185 // Verify that when Sync is configured successfully, the observer loads the
186 // continue URL and cleans up after itself.
187 TEST_F(OneClickSigninSyncObserverTest,
188        OnSyncStateChanged_SyncConfiguredSuccessfully) {
189   CreateSyncObserver(kContinueUrl);
190   sync_service_->set_first_setup_in_progress(false);
191   sync_service_->set_sync_initialized(true);
192
193   EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderView(_));
194   sync_service_->NotifyObservers();
195   EXPECT_EQ(GURL(kContinueUrl), web_contents()->GetVisibleURL());
196 }
197
198 // Verify that when Sync configuration fails, the observer does not load the
199 // continue URL, but still cleans up after itself.
200 TEST_F(OneClickSigninSyncObserverTest,
201        OnSyncStateChanged_SyncConfigurationFailed) {
202   CreateSyncObserver(kContinueUrl);
203   sync_service_->set_first_setup_in_progress(false);
204   sync_service_->set_sync_initialized(false);
205
206   EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderView(_)).Times(0);
207   sync_service_->NotifyObservers();
208   EXPECT_NE(GURL(kContinueUrl), web_contents()->GetVisibleURL());
209 }
210
211 // Verify that when Sync sends a notification while setup is not yet complete,
212 // the observer does not load the continue URL, and continues to wait.
213 TEST_F(OneClickSigninSyncObserverTest,
214        OnSyncStateChanged_SyncConfigurationInProgress) {
215   CreateSyncObserver(kContinueUrl);
216   sync_service_->set_first_setup_in_progress(true);
217   sync_service_->set_sync_initialized(false);
218
219   EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderView(_)).Times(0);
220   sync_service_->NotifyObservers();
221   EXPECT_NE(GURL(kContinueUrl), web_contents()->GetVisibleURL());
222
223   // Trigger an event to force state to be cleaned up.
224   SetContents(NULL);
225 }
226
227 // Verify that if the continue_url is to the settings page, no navigation is
228 // triggered, since it would be redundant.
229 TEST_F(OneClickSigninSyncObserverTest,
230        OnSyncStateChanged_SyncConfiguredSuccessfully_SourceIsSettings) {
231   GURL continue_url = signin::GetPromoURL(signin::SOURCE_SETTINGS, false);
232   CreateSyncObserver(continue_url.spec());
233   sync_service_->set_first_setup_in_progress(false);
234   sync_service_->set_sync_initialized(true);
235
236   EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderView(_)).Times(0);
237   sync_service_->NotifyObservers();
238   EXPECT_NE(GURL(kContinueUrl), web_contents()->GetVisibleURL());
239 }