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 "base/run_loop.h"
6#include "base/time/time.h"
7#include "chrome/browser/chromeos/login/signin/merge_session_load_page.h"
8#include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
9#include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
10#include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
11#include "chrome/browser/chromeos/settings/cros_settings.h"
12#include "chrome/browser/chromeos/settings/device_settings_service.h"
13#include "chrome/test/base/chrome_render_view_host_test_harness.h"
14#include "content/public/browser/interstitial_page.h"
15#include "content/public/browser/navigation_controller.h"
16#include "content/public/browser/web_contents.h"
17#include "content/public/test/web_contents_tester.h"
18
19using content::InterstitialPage;
20using content::WebContents;
21using content::WebContentsTester;
22
23namespace {
24
25const char kURL1[] = "http://www.google.com/";
26const char kURL2[] = "http://mail.google.com/";
27
28const int64 kSessionMergeTimeout = 60;
29
30}  // namespace
31
32namespace chromeos {
33
34class MergeSessionLoadPageTest;
35
36// An MergeSessionLoadPage class that does not create windows.
37class TestMergeSessionLoadPage :  public MergeSessionLoadPage {
38 public:
39  TestMergeSessionLoadPage(WebContents* web_contents,
40                           const GURL& url,
41                           MergeSessionLoadPageTest* test_page)
42    : MergeSessionLoadPage(web_contents,
43                           url,
44                           MergeSessionThrottle::CompletionCallback()),
45      test_page_(test_page) {
46    interstitial_page_->DontCreateViewForTesting();
47  }
48
49 private:
50  MergeSessionLoadPageTest* test_page_;
51
52  DISALLOW_COPY_AND_ASSIGN(TestMergeSessionLoadPage);
53};
54
55class MergeSessionLoadPageTest : public ChromeRenderViewHostTestHarness {
56 protected:
57  virtual void SetUp() OVERRIDE {
58    ChromeRenderViewHostTestHarness::SetUp();
59#if defined OS_CHROMEOS
60  test_user_manager_.reset(new chromeos::ScopedTestUserManager());
61#endif
62  }
63
64  virtual void TearDown() OVERRIDE {
65#if defined OS_CHROMEOS
66    // Clean up pending tasks that might depend on the user manager.
67    base::RunLoop().RunUntilIdle();
68    test_user_manager_.reset();
69#endif
70    ChromeRenderViewHostTestHarness::TearDown();
71  }
72
73  void Navigate(const char* url, int page_id) {
74    WebContentsTester::For(web_contents())->TestDidNavigate(
75        web_contents()->GetMainFrame(), page_id, GURL(url),
76        ui::PAGE_TRANSITION_TYPED);
77  }
78
79  void ShowInterstitial(const char* url) {
80    (new TestMergeSessionLoadPage(web_contents(), GURL(url), this))->Show();
81  }
82
83  // Returns the MergeSessionLoadPage currently showing or NULL if none is
84  // showing.
85  InterstitialPage* GetMergeSessionLoadPage() {
86    return InterstitialPage::GetInterstitialPage(web_contents());
87  }
88
89  OAuth2LoginManager* GetOAuth2LoginManager() {
90    content::BrowserContext* browser_context =
91        web_contents()->GetBrowserContext();
92    if (!browser_context)
93      return NULL;
94
95    Profile* profile = Profile::FromBrowserContext(browser_context);
96    if (!profile)
97      return NULL;
98
99    OAuth2LoginManager* login_manager =
100        OAuth2LoginManagerFactory::GetInstance()->GetForProfile(
101            profile);
102    return login_manager;
103  }
104
105  void SetMergeSessionState(OAuth2LoginManager::SessionRestoreState state) {
106    OAuth2LoginManager* login_manager = GetOAuth2LoginManager();
107    ASSERT_TRUE(login_manager);
108    login_manager->SetSessionRestoreState(state);
109  }
110
111  void SetSessionRestoreStart(const base::Time& time) {
112    OAuth2LoginManager* login_manager = GetOAuth2LoginManager();
113    ASSERT_TRUE(login_manager);
114    login_manager->SetSessionRestoreStartForTesting(time);
115  }
116
117 private:
118  ScopedTestDeviceSettingsService test_device_settings_service_;
119  ScopedTestCrosSettings test_cros_settings_;
120  scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
121};
122
123TEST_F(MergeSessionLoadPageTest, MergeSessionPageNotShown) {
124  SetMergeSessionState(OAuth2LoginManager::SESSION_RESTORE_DONE);
125  // Start a load.
126  Navigate(kURL1, 1);
127  // Load next page.
128  controller().LoadURL(GURL(kURL2), content::Referrer(),
129                       ui::PAGE_TRANSITION_TYPED, std::string());
130
131  // Simulate the load causing an merge session interstitial page
132  // to be shown.
133  InterstitialPage* interstitial = GetMergeSessionLoadPage();
134  EXPECT_FALSE(interstitial);
135}
136
137TEST_F(MergeSessionLoadPageTest, MergeSessionPageNotShownOnTimeout) {
138  SetMergeSessionState(OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS);
139  SetSessionRestoreStart(
140      base::Time::Now() +
141      base::TimeDelta::FromSeconds(kSessionMergeTimeout + 1));
142
143  // Start a load.
144  Navigate(kURL1, 1);
145  // Load next page.
146  controller().LoadURL(GURL(kURL2), content::Referrer(),
147                       ui::PAGE_TRANSITION_TYPED, std::string());
148
149  // Simulate the load causing an merge session interstitial page
150  // to be shown.
151  InterstitialPage* interstitial = GetMergeSessionLoadPage();
152  EXPECT_FALSE(interstitial);
153}
154
155TEST_F(MergeSessionLoadPageTest, MergeSessionPageShown) {
156  SetMergeSessionState(OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS);
157
158  // Start a load.
159  Navigate(kURL1, 1);
160  // Load next page.
161  controller().LoadURL(GURL(kURL2), content::Referrer(),
162                       ui::PAGE_TRANSITION_TYPED, std::string());
163
164  // Simulate the load causing an merge session interstitial page
165  // to be shown.
166  ShowInterstitial(kURL2);
167  InterstitialPage* interstitial = GetMergeSessionLoadPage();
168  ASSERT_TRUE(interstitial);
169  base::RunLoop().RunUntilIdle();
170
171  // Simulate merge session completion.
172  SetMergeSessionState(OAuth2LoginManager::SESSION_RESTORE_DONE);
173  base::RunLoop().RunUntilIdle();
174
175  // The URL remains to be URL2.
176  EXPECT_EQ(kURL2, web_contents()->GetVisibleURL().spec());
177
178  // Commit navigation and the interstitial page is gone.
179  Navigate(kURL2, 2);
180  EXPECT_FALSE(GetMergeSessionLoadPage());
181}
182
183}  // namespace chromeos
184