This source file includes following definitions.
- RequestBeginning
- SetTrackedURL
- WaitForTrackedURLAndGetCompleted
- tracker_
- GetNameForLogging
- SetTrackedURLOnIOThread
- OnTrackedRequestDestroyed
- OpenURLFromTab
- SetUpOnMainThread
- TearDownOnMainThread
- NavigateToURLContentInitiated
- SetUpCommandLine
- InjectResourceDisptcherHostDelegate
- RestoreResourceDisptcherHostDelegate
- tracking_delegate
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
#include "net/base/escape.h"
#include "net/dns/mock_host_resolver.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"
namespace content {
class TrackingResourceDispatcherHostDelegate
: public ShellResourceDispatcherHostDelegate {
public:
TrackingResourceDispatcherHostDelegate() : throttle_created_(false) {
}
virtual void RequestBeginning(
net::URLRequest* request,
ResourceContext* resource_context,
appcache::AppCacheService* appcache_service,
ResourceType::Type resource_type,
int child_id,
int route_id,
ScopedVector<ResourceThrottle>* throttles) OVERRIDE {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ShellResourceDispatcherHostDelegate::RequestBeginning(
request, resource_context, appcache_service, resource_type, child_id,
route_id, throttles);
ASSERT_FALSE(throttle_created_);
if (request->url() == tracked_url_)
throttles->push_back(new TrackingThrottle(request, this));
}
void SetTrackedURL(const GURL& tracked_url) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ASSERT_FALSE(run_loop_);
run_loop_.reset(new base::RunLoop());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(
&TrackingResourceDispatcherHostDelegate::SetTrackedURLOnIOThread,
base::Unretained(this),
tracked_url));
}
bool WaitForTrackedURLAndGetCompleted() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
run_loop_->Run();
run_loop_.reset();
return tracked_request_completed_;
}
private:
class TrackingThrottle : public ResourceThrottle {
public:
TrackingThrottle(net::URLRequest* request,
TrackingResourceDispatcherHostDelegate* tracker)
: request_(request), tracker_(tracker) {
}
virtual ~TrackingThrottle() {
tracker_->OnTrackedRequestDestroyed(
!request_->is_pending() && request_->status().is_success());
}
virtual const char* GetNameForLogging() const OVERRIDE {
return "TrackingThrottle";
}
private:
net::URLRequest* request_;
TrackingResourceDispatcherHostDelegate* tracker_;
DISALLOW_COPY_AND_ASSIGN(TrackingThrottle);
};
void SetTrackedURLOnIOThread(const GURL& tracked_url) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
throttle_created_ = false;
tracked_url_ = tracked_url;
}
void OnTrackedRequestDestroyed(bool completed) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
tracked_request_completed_ = completed;
tracked_url_ = GURL();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, run_loop_->QuitClosure());
}
GURL tracked_url_;
bool throttle_created_;
scoped_ptr<base::RunLoop> run_loop_;
bool tracked_request_completed_;
DISALLOW_COPY_AND_ASSIGN(TrackingResourceDispatcherHostDelegate);
};
class NoTransferRequestDelegate : public WebContentsDelegate {
public:
NoTransferRequestDelegate() {}
virtual WebContents* OpenURLFromTab(WebContents* source,
const OpenURLParams& params) OVERRIDE {
bool is_transfer =
(params.transferred_global_request_id != GlobalRequestID());
if (is_transfer)
return NULL;
NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
load_url_params.frame_tree_node_id = params.frame_tree_node_id;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
load_url_params.is_renderer_initiated = true;
source->GetController().LoadURLWithParams(load_url_params);
return source;
}
private:
DISALLOW_COPY_AND_ASSIGN(NoTransferRequestDelegate);
};
class CrossSiteTransferTest : public ContentBrowserTest {
public:
CrossSiteTransferTest() : old_delegate_(NULL) {
}
virtual void SetUpOnMainThread() OVERRIDE {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(
&CrossSiteTransferTest::InjectResourceDisptcherHostDelegate,
base::Unretained(this)));
}
virtual void TearDownOnMainThread() OVERRIDE {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(
&CrossSiteTransferTest::RestoreResourceDisptcherHostDelegate,
base::Unretained(this)));
}
protected:
void NavigateToURLContentInitiated(Shell* window,
const GURL& url,
bool should_replace_current_entry,
bool should_wait_for_navigation) {
std::string script;
if (should_replace_current_entry)
script = base::StringPrintf("location.replace('%s')", url.spec().c_str());
else
script = base::StringPrintf("location.href = '%s'", url.spec().c_str());
TestNavigationObserver load_observer(shell()->web_contents(), 1);
bool result = ExecuteScript(window->web_contents(), script);
EXPECT_TRUE(result);
if (should_wait_for_navigation)
load_observer.Wait();
}
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(switches::kSitePerProcess);
}
void InjectResourceDisptcherHostDelegate() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
old_delegate_ = ResourceDispatcherHostImpl::Get()->delegate();
ResourceDispatcherHostImpl::Get()->SetDelegate(&tracking_delegate_);
}
void RestoreResourceDisptcherHostDelegate() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate_);
old_delegate_ = NULL;
}
TrackingResourceDispatcherHostDelegate& tracking_delegate() {
return tracking_delegate_;
}
private:
TrackingResourceDispatcherHostDelegate tracking_delegate_;
ResourceDispatcherHostDelegate* old_delegate_;
};
#if defined(THREAD_SANITIZER)
#define MAYBE_ReplaceEntryCrossProcessThenTransfer \
DISABLED_ReplaceEntryCrossProcessThenTransfer
#define MAYBE_ReplaceEntryCrossProcessTwice \
DISABLED_ReplaceEntryCrossProcessTwice
#else
#define MAYBE_ReplaceEntryCrossProcessThenTransfer \
ReplaceEntryCrossProcessThenTransfer
#define MAYBE_ReplaceEntryCrossProcessTwice ReplaceEntryCrossProcessTwice
#endif
IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
MAYBE_ReplaceEntryCrossProcessThenTransfer) {
const NavigationController& controller =
shell()->web_contents()->GetController();
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(test_server()->Start());
GURL::Replacements replace_host;
std::string a_com("A.com");
std::string b_com("B.com");
GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
NavigateToURL(shell(), url1);
ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
replace_host.SetHostStr(a_com);
url2 = url2.ReplaceComponents(replace_host);
tracking_delegate().SetTrackedURL(url2);
NavigateToURLContentInitiated(shell(), url2, true, true);
EXPECT_TRUE(controller.GetPendingEntry() == NULL);
EXPECT_EQ(1, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetCurrentEntryIndex());
EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted());
GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
replace_host.SetHostStr(b_com);
url3 = url3.ReplaceComponents(replace_host);
tracking_delegate().SetTrackedURL(url3);
NavigateToURLContentInitiated(shell(), url3, false, true);
EXPECT_TRUE(controller.GetPendingEntry() == NULL);
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetCurrentEntryIndex());
EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL());
EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted());
}
IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
ReplaceEntryInProcessThenTranfers) {
const NavigationController& controller =
shell()->web_contents()->GetController();
ASSERT_TRUE(test_server()->Start());
GURL url = test_server()->GetURL("files/site_isolation/blank.html?1");
NavigateToURL(shell(), url);
ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
NavigateToURLContentInitiated(shell(), url2, true, true);
EXPECT_TRUE(controller.GetPendingEntry() == NULL);
EXPECT_EQ(1, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetCurrentEntryIndex());
EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
NavigateToURLContentInitiated(shell(), url3, false, true);
EXPECT_TRUE(controller.GetPendingEntry() == NULL);
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetCurrentEntryIndex());
EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL());
}
IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
MAYBE_ReplaceEntryCrossProcessTwice) {
const NavigationController& controller =
shell()->web_contents()->GetController();
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(test_server()->Start());
GURL::Replacements replace_host;
std::string a_com("A.com");
std::string b_com("B.com");
GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
NavigateToURL(shell(), url1);
GURL url2b = test_server()->GetURL("files/site_isolation/blank.html?2");
replace_host.SetHostStr(b_com);
url2b = url2b.ReplaceComponents(replace_host);
GURL url2a = test_server()->GetURL(
"server-redirect?" + net::EscapeQueryParamValue(url2b.spec(), false));
replace_host.SetHostStr(a_com);
url2a = url2a.ReplaceComponents(replace_host);
NavigateToURLContentInitiated(shell(), url2a, true, true);
EXPECT_TRUE(controller.GetPendingEntry() == NULL);
EXPECT_EQ(1, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetCurrentEntryIndex());
EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL());
GURL url3b = test_server()->GetURL("files/site_isolation/blank.html?3");
replace_host.SetHostStr(b_com);
url3b = url3b.ReplaceComponents(replace_host);
GURL url3a = test_server()->GetURL(
"server-redirect?" + net::EscapeQueryParamValue(url3b.spec(), false));
replace_host.SetHostStr(a_com);
url3a = url3a.ReplaceComponents(replace_host);
NavigateToURLContentInitiated(shell(), url3a, false, true);
EXPECT_TRUE(controller.GetPendingEntry() == NULL);
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetCurrentEntryIndex());
EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL());
}
IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, NoLeakOnCrossSiteCancel) {
const NavigationController& controller =
shell()->web_contents()->GetController();
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(test_server()->Start());
GURL::Replacements replace_host;
std::string a_com("A.com");
std::string b_com("B.com");
GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
NavigateToURL(shell(), url1);
ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
NoTransferRequestDelegate no_transfer_request_delegate;
WebContentsDelegate* old_delegate = shell()->web_contents()->GetDelegate();
shell()->web_contents()->SetDelegate(&no_transfer_request_delegate);
GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
replace_host.SetHostStr(a_com);
url2 = url2.ReplaceComponents(replace_host);
tracking_delegate().SetTrackedURL(url2);
NavigateToURLContentInitiated(shell(), url2, false, false);
EXPECT_EQ(1, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetCurrentEntryIndex());
EXPECT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL());
EXPECT_FALSE(tracking_delegate().WaitForTrackedURLAndGetCompleted());
shell()->web_contents()->SetDelegate(old_delegate);
}
}