signin_browsertest.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
1// Copyright 2013 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#ifndef CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
6#define CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
7
8#include "base/command_line.h"
9#include "chrome/browser/signin/signin_manager.h"
10#include "chrome/browser/signin/signin_manager_factory.h"
11#include "chrome/browser/signin/signin_promo.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/singleton_tabs.h"
14#include "chrome/browser/ui/tabs/tab_strip_model.h"
15#include "chrome/browser/ui/webui/signin/login_ui_service.h"
16#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
17#include "chrome/common/url_constants.h"
18#include "chrome/test/base/in_process_browser_test.h"
19#include "chrome/test/base/ui_test_utils.h"
20#include "content/public/browser/notification_service.h"
21#include "content/public/browser/notification_types.h"
22#include "content/public/browser/render_process_host.h"
23#include "content/public/browser/render_view_host.h"
24#include "content/public/browser/web_contents.h"
25#include "content/public/browser/web_contents_observer.h"
26#include "content/public/common/content_switches.h"
27#include "google_apis/gaia/gaia_urls.h"
28#include "net/url_request/test_url_fetcher_factory.h"
29
30namespace {
31  const char kNonSigninURL[] = "www.google.com";
32}
33
34class SigninBrowserTest : public InProcessBrowserTest {
35 public:
36  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
37    https_server_.reset(new net::SpawnedTestServer(
38        net::SpawnedTestServer::TYPE_HTTPS,
39        net::SpawnedTestServer::kLocalhost,
40        base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
41    ASSERT_TRUE(https_server_->Start());
42
43    // Add a host resolver rule to map all outgoing requests to the test server.
44    // This allows us to use "real" hostnames in URLs, which we can use to
45    // create arbitrary SiteInstances.
46    command_line->AppendSwitchASCII(
47        switches::kHostResolverRules,
48        "MAP * " + https_server_->host_port_pair().ToString() +
49            ",EXCLUDE localhost");
50    command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
51  }
52
53  virtual void SetUp() OVERRIDE {
54    factory_.reset(new net::URLFetcherImplFactory());
55    fake_factory_.reset(new net::FakeURLFetcherFactory(factory_.get()));
56    fake_factory_->SetFakeResponse(
57        GaiaUrls::GetInstance()->service_login_url(),
58        std::string(),
59        true);
60    fake_factory_->SetFakeResponse(kNonSigninURL, std::string(), true);
61    // Yield control back to the InProcessBrowserTest framework.
62    InProcessBrowserTest::SetUp();
63  }
64
65  virtual void TearDown() OVERRIDE {
66    if (fake_factory_.get()) {
67      fake_factory_->ClearFakeResponses();
68      fake_factory_.reset();
69    }
70
71    // Cancel any outstanding URL fetches and destroy the URLFetcherImplFactory
72    // we created.
73    net::URLFetcher::CancelAll();
74    factory_.reset();
75    InProcessBrowserTest::TearDown();
76  }
77
78 private:
79  // Fake URLFetcher factory used to mock out GAIA signin.
80  scoped_ptr<net::FakeURLFetcherFactory> fake_factory_;
81
82  // The URLFetcherImplFactory instance used to instantiate |fake_factory_|.
83  scoped_ptr<net::URLFetcherImplFactory> factory_;
84
85  scoped_ptr<net::SpawnedTestServer> https_server_;
86};
87
88// If the one-click-signin feature is not enabled (e.g Chrome OS), we
89// never grant signin privileges to any renderer processes.
90#if defined(ENABLE_ONE_CLICK_SIGNIN)
91const bool kOneClickSigninEnabled = true;
92#else
93const bool kOneClickSigninEnabled = false;
94#endif
95
96// Disabled on Windows due to flakiness. http://crbug.com/249055
97#if defined(OS_WIN)
98#define MAYBE_ProcessIsolation DISABLED_ProcessIsolation
99#else
100#define MAYBE_ProcessIsolation ProcessIsolation
101#endif
102IN_PROC_BROWSER_TEST_F(SigninBrowserTest, MAYBE_ProcessIsolation) {
103  SigninManager* signin = SigninManagerFactory::GetForProfile(
104      browser()->profile());
105  EXPECT_FALSE(signin->HasSigninProcess());
106
107  ui_test_utils::NavigateToURL(browser(), signin::GetPromoURL(
108      signin::SOURCE_NTP_LINK, true));
109  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());
110
111  // Navigating away should change the process.
112  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
113  EXPECT_FALSE(signin->HasSigninProcess());
114
115  ui_test_utils::NavigateToURL(browser(), signin::GetPromoURL(
116      signin::SOURCE_NTP_LINK, true));
117  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());
118
119  content::WebContents* active_tab =
120      browser()->tab_strip_model()->GetActiveWebContents();
121  int active_tab_process_id =
122      active_tab->GetRenderProcessHost()->GetID();
123  EXPECT_EQ(kOneClickSigninEnabled,
124            signin->IsSigninProcess(active_tab_process_id));
125  EXPECT_EQ(0, active_tab->GetRenderViewHost()->GetEnabledBindings());
126
127  // Entry points to signin request "SINGLETON_TAB" mode, so a new request
128  // shouldn't change anything.
129  chrome::NavigateParams params(chrome::GetSingletonTabNavigateParams(
130      browser(),
131      GURL(signin::GetPromoURL(signin::SOURCE_NTP_LINK, false))));
132  params.path_behavior = chrome::NavigateParams::IGNORE_AND_NAVIGATE;
133  ShowSingletonTabOverwritingNTP(browser(), params);
134  EXPECT_EQ(active_tab, browser()->tab_strip_model()->GetActiveWebContents());
135  EXPECT_EQ(kOneClickSigninEnabled,
136            signin->IsSigninProcess(active_tab_process_id));
137
138  // Navigating away should change the process.
139  ui_test_utils::NavigateToURL(browser(), GURL(kNonSigninURL));
140  EXPECT_FALSE(signin->IsSigninProcess(
141      active_tab->GetRenderProcessHost()->GetID()));
142}
143
144IN_PROC_BROWSER_TEST_F(SigninBrowserTest, NotTrustedAfterRedirect) {
145  SigninManager* signin = SigninManagerFactory::GetForProfile(
146      browser()->profile());
147  EXPECT_FALSE(signin->HasSigninProcess());
148
149  GURL url = signin::GetPromoURL(signin::SOURCE_NTP_LINK, true);
150  ui_test_utils::NavigateToURL(browser(), url);
151  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());
152
153  // Navigating in a different tab should not affect the sign-in process.
154  ui_test_utils::NavigateToURLWithDisposition(
155      browser(), GURL(kNonSigninURL), NEW_BACKGROUND_TAB,
156      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
157  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());
158
159  // Navigating away should clear the sign-in process.
160  GURL redirect_url("https://accounts.google.com/server-redirect?"
161      "https://foo.com?service=chromiumsync");
162  ui_test_utils::NavigateToURL(browser(), redirect_url);
163  EXPECT_FALSE(signin->HasSigninProcess());
164}
165
166class BackOnNTPCommitObserver : public content::WebContentsObserver {
167 public:
168  explicit BackOnNTPCommitObserver(content::WebContents* web_contents)
169      : content::WebContentsObserver(web_contents) {
170  }
171
172  virtual void DidCommitProvisionalLoadForFrame(
173      int64 frame_id,
174      bool is_main_frame,
175      const GURL& url,
176      content::PageTransition transition_type,
177      content::RenderViewHost* render_view_host) OVERRIDE {
178    if (url == GURL(chrome::kChromeUINewTabURL)) {
179      content::WindowedNotificationObserver observer(
180          content::NOTIFICATION_NAV_ENTRY_COMMITTED,
181          content::NotificationService::AllSources());
182      web_contents()->GetController().GoBack();
183      observer.Wait();
184    }
185  }
186
187 private:
188  DISALLOW_COPY_AND_ASSIGN(BackOnNTPCommitObserver);
189};
190
191// This is a test for http://crbug.com/257277. It simulates the navigations
192// that occur if the user clicks on the "Skip for now" link at the signin page
193// and initiates a back navigation between the point of Commit and
194// DidStopLoading of the NTP.
195IN_PROC_BROWSER_TEST_F(SigninBrowserTest, SigninSkipForNowAndGoBack) {
196  GURL ntp_url(chrome::kChromeUINewTabURL);
197  GURL start_url = signin::GetPromoURL(signin::SOURCE_START_PAGE, true);
198  GURL skip_url = signin::GetLandingURL("ntp", 1);
199
200  SigninManager* signin = SigninManagerFactory::GetForProfile(
201      browser()->profile());
202  EXPECT_FALSE(signin->HasSigninProcess());
203
204  ui_test_utils::NavigateToURL(browser(), start_url);
205  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());
206
207  content::WebContents* web_contents =
208      browser()->tab_strip_model()->GetActiveWebContents();
209
210  // Simulate clicking on the Skip for now link by navigating to the URL.
211  ui_test_utils::NavigateToURL(browser(), skip_url);
212
213  // Register an observer that will navigate back immediately on the commit of
214  // the NTP. This will allow us to hit the race condition of navigating back
215  // before the DidStopLoading message of NTP gets delivered. This must be
216  // created after the navigation to the skip_url has finished loading,
217  // otherwise this observer will navigate back, before the history cleaner
218  // has had a chance to remove the navigation entry.
219  BackOnNTPCommitObserver commit_observer(web_contents);
220
221  // Since the navigation to the blank URL is monitored for, the
222  // OneClickSigninHelper initiates immediately a navigation to the NTP.
223  // Thus, we expect the visible URL to be the NTP.
224  EXPECT_EQ(skip_url, web_contents->GetLastCommittedURL());
225  EXPECT_EQ(ntp_url, web_contents->GetVisibleURL());
226
227  content::WindowedNotificationObserver observer(
228      content::NOTIFICATION_LOAD_STOP,
229      content::NotificationService::AllSources());
230  observer.Wait();
231  EXPECT_EQ(start_url, web_contents->GetLastCommittedURL());
232}
233#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
234