Home | History | Annotate | Download | only in signin
      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