blob: aebd1f8432b38552bc9996a62147aea1a1247eb8 [file] [log] [blame]
// 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/signin_manager.h"
#include "chrome/browser/signin/signin_manager_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/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"
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);
}
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);
fake_factory_->SetFakeResponse(GURL(kNonSigninURL),
std::string(),
net::HTTP_OK);
// 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) {
SigninManager* signin = SigninManagerFactory::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::kChromeUINewTabURL));
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(kNonSigninURL));
EXPECT_FALSE(signin->IsSigninProcess(
active_tab->GetRenderProcessHost()->GetID()));
}
IN_PROC_BROWSER_TEST_F(SigninBrowserTest, NotTrustedAfterRedirect) {
SigninManager* signin = SigninManagerFactory::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 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)) {
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, true);
GURL skip_url = signin::GetLandingURL("ntp", 1);
SigninManager* signin = SigninManagerFactory::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 the navigation to the blank URL is monitored for, the
// OneClickSigninHelper initiates immediately a navigation to the NTP.
// Thus, we expect the visible URL to be the NTP.
EXPECT_EQ(skip_url, web_contents->GetLastCommittedURL());
EXPECT_EQ(ntp_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_