root/chrome/browser/signin/signin_browsertest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SetUpCommandLine
  2. SetUp
  3. TearDown
  4. IN_PROC_BROWSER_TEST_F
  5. IN_PROC_BROWSER_TEST_F
  6. DidCommitProvisionalLoadForFrame
  7. IN_PROC_BROWSER_TEST_F

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
#define CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_

#include "base/command_line.h"
#include "chrome/browser/signin/chrome_signin_client.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/http/http_status_code.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_status.h"

namespace {
const char kNonSigninURL[] = "www.google.com";
}

class SigninBrowserTest : public InProcessBrowserTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    https_server_.reset(new net::SpawnedTestServer(
        net::SpawnedTestServer::TYPE_HTTPS,
        net::SpawnedTestServer::kLocalhost,
        base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
    ASSERT_TRUE(https_server_->Start());

    // Add a host resolver rule to map all outgoing requests to the test server.
    // This allows us to use "real" hostnames in URLs, which we can use to
    // create arbitrary SiteInstances.
    command_line->AppendSwitchASCII(
        switches::kHostResolverRules,
        "MAP * " + https_server_->host_port_pair().ToString() +
            ",EXCLUDE localhost");
    command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
    // All tests in this file are for the web based sign in flows.
    // TODO(guohui): fix tests for inline sign in flows.
    command_line->AppendSwitch(switches::kEnableWebBasedSignin);
  }

  virtual void SetUp() OVERRIDE {
    factory_.reset(new net::URLFetcherImplFactory());
    fake_factory_.reset(new net::FakeURLFetcherFactory(factory_.get()));
    fake_factory_->SetFakeResponse(
        GaiaUrls::GetInstance()->service_login_url(), std::string(),
        net::HTTP_OK, net::URLRequestStatus::SUCCESS);
    fake_factory_->SetFakeResponse(
        GURL(kNonSigninURL), std::string(), net::HTTP_OK,
        net::URLRequestStatus::SUCCESS);
    // Yield control back to the InProcessBrowserTest framework.
    InProcessBrowserTest::SetUp();
  }

  virtual void TearDown() OVERRIDE {
    if (fake_factory_.get()) {
      fake_factory_->ClearFakeResponses();
      fake_factory_.reset();
    }

    // Cancel any outstanding URL fetches and destroy the URLFetcherImplFactory
    // we created.
    net::URLFetcher::CancelAll();
    factory_.reset();
    InProcessBrowserTest::TearDown();
  }

 private:
  // Fake URLFetcher factory used to mock out GAIA signin.
  scoped_ptr<net::FakeURLFetcherFactory> fake_factory_;

  // The URLFetcherImplFactory instance used to instantiate |fake_factory_|.
  scoped_ptr<net::URLFetcherImplFactory> factory_;

  scoped_ptr<net::SpawnedTestServer> https_server_;
};

// If the one-click-signin feature is not enabled (e.g Chrome OS), we
// never grant signin privileges to any renderer processes.
#if defined(ENABLE_ONE_CLICK_SIGNIN)
const bool kOneClickSigninEnabled = true;
#else
const bool kOneClickSigninEnabled = false;
#endif

// Disabled on Windows due to flakiness. http://crbug.com/249055
#if defined(OS_WIN)
#define MAYBE_ProcessIsolation DISABLED_ProcessIsolation
#else
#define MAYBE_ProcessIsolation ProcessIsolation
#endif
IN_PROC_BROWSER_TEST_F(SigninBrowserTest, MAYBE_ProcessIsolation) {
  ChromeSigninClient* signin =
      ChromeSigninClientFactory::GetForProfile(browser()->profile());
  EXPECT_FALSE(signin->HasSigninProcess());

  ui_test_utils::NavigateToURL(browser(), signin::GetPromoURL(
      signin::SOURCE_NTP_LINK, true));
  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());

  // Navigating away should change the process.
  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIOmniboxURL));
  EXPECT_FALSE(signin->HasSigninProcess());

  ui_test_utils::NavigateToURL(browser(), signin::GetPromoURL(
      signin::SOURCE_NTP_LINK, true));
  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());

  content::WebContents* active_tab =
      browser()->tab_strip_model()->GetActiveWebContents();
  int active_tab_process_id =
      active_tab->GetRenderProcessHost()->GetID();
  EXPECT_EQ(kOneClickSigninEnabled,
            signin->IsSigninProcess(active_tab_process_id));
  EXPECT_EQ(0, active_tab->GetRenderViewHost()->GetEnabledBindings());

  // Entry points to signin request "SINGLETON_TAB" mode, so a new request
  // shouldn't change anything.
  chrome::NavigateParams params(chrome::GetSingletonTabNavigateParams(
      browser(),
      GURL(signin::GetPromoURL(signin::SOURCE_NTP_LINK, false))));
  params.path_behavior = chrome::NavigateParams::IGNORE_AND_NAVIGATE;
  ShowSingletonTabOverwritingNTP(browser(), params);
  EXPECT_EQ(active_tab, browser()->tab_strip_model()->GetActiveWebContents());
  EXPECT_EQ(kOneClickSigninEnabled,
            signin->IsSigninProcess(active_tab_process_id));

  // Navigating away should change the process.
  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
  EXPECT_FALSE(signin->IsSigninProcess(
      active_tab->GetRenderProcessHost()->GetID()));
}

IN_PROC_BROWSER_TEST_F(SigninBrowserTest, NotTrustedAfterRedirect) {
  ChromeSigninClient* signin =
      ChromeSigninClientFactory::GetForProfile(browser()->profile());
  EXPECT_FALSE(signin->HasSigninProcess());

  GURL url = signin::GetPromoURL(signin::SOURCE_NTP_LINK, true);
  ui_test_utils::NavigateToURL(browser(), url);
  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());

  // Navigating in a different tab should not affect the sign-in process.
  ui_test_utils::NavigateToURLWithDisposition(
      browser(), GURL(kNonSigninURL), NEW_BACKGROUND_TAB,
      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());

  // Navigating away should clear the sign-in process.
  GURL redirect_url("https://accounts.google.com/server-redirect?"
      "https://foo.com?service=chromiumsync");
  ui_test_utils::NavigateToURL(browser(), redirect_url);
  EXPECT_FALSE(signin->HasSigninProcess());
}

class BackOnNTPCommitObserver : public content::WebContentsObserver {
 public:
  explicit BackOnNTPCommitObserver(content::WebContents* web_contents)
      : content::WebContentsObserver(web_contents) {
  }

  virtual void DidCommitProvisionalLoadForFrame(
      int64 frame_id,
      const base::string16& frame_unique_name,
      bool is_main_frame,
      const GURL& url,
      content::PageTransition transition_type,
      content::RenderViewHost* render_view_host) OVERRIDE {
    if (url == GURL(chrome::kChromeUINewTabURL) ||
        url == GURL(chrome::kChromeSearchLocalNtpUrl)) {
      content::WindowedNotificationObserver observer(
          content::NOTIFICATION_NAV_ENTRY_COMMITTED,
          content::NotificationService::AllSources());
      web_contents()->GetController().GoBack();
      observer.Wait();
    }
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(BackOnNTPCommitObserver);
};

// This is a test for http://crbug.com/257277. It simulates the navigations
// that occur if the user clicks on the "Skip for now" link at the signin page
// and initiates a back navigation between the point of Commit and
// DidStopLoading of the NTP.
IN_PROC_BROWSER_TEST_F(SigninBrowserTest, SigninSkipForNowAndGoBack) {
  GURL ntp_url(chrome::kChromeUINewTabURL);
  GURL start_url = signin::GetPromoURL(signin::SOURCE_START_PAGE, false);
  GURL skip_url = signin::GetLandingURL("ntp", 1);

  ChromeSigninClient* signin =
      ChromeSigninClientFactory::GetForProfile(browser()->profile());
  EXPECT_FALSE(signin->HasSigninProcess());

  ui_test_utils::NavigateToURL(browser(), start_url);
  EXPECT_EQ(kOneClickSigninEnabled, signin->HasSigninProcess());

  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();

  // Simulate clicking on the Skip for now link. It's important to have a
  // link transition so that OneClickSigninHelper removes the blank page
  // from the history.
  chrome::NavigateParams navigate_params(browser(),
                                         skip_url,
                                         content::PAGE_TRANSITION_LINK);
  ui_test_utils::NavigateToURL(&navigate_params);

  // Register an observer that will navigate back immediately on the commit of
  // the NTP. This will allow us to hit the race condition of navigating back
  // before the DidStopLoading message of NTP gets delivered. This must be
  // created after the navigation to the skip_url has finished loading,
  // otherwise this observer will navigate back, before the history cleaner
  // has had a chance to remove the navigation entry.
  BackOnNTPCommitObserver commit_observer(web_contents);

  // Since OneClickSigninHelper aborts redirect to NTP, thus we expect the
  // visible URL to be the starting URL.
  EXPECT_EQ(skip_url, web_contents->GetLastCommittedURL());
  EXPECT_EQ(start_url, web_contents->GetVisibleURL());

  content::WindowedNotificationObserver observer(
      content::NOTIFICATION_LOAD_STOP,
      content::NotificationService::AllSources());
  observer.Wait();
  EXPECT_EQ(start_url, web_contents->GetLastCommittedURL());
}
#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_

/* [<][>][^][v][top][bottom][index][help] */