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