Commit 053a1db4 authored by jam@chromium.org's avatar jam@chromium.org

Add back the code to PrerenderManager::PendingSwap to handle RenderViewCreated...

Add back the code to PrerenderManager::PendingSwap to handle RenderViewCreated being called for a cross-site navigation.

The two tests are from David's https://codereview.chromium.org/140073003.

BUG=330735
R=davidben@chromium.org, tburkard@chromium.org

Review URL: https://codereview.chromium.org/138583003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245386 0039d316-1c4b-4281-b951-d872f2087c98
parent 918b1d33
......@@ -787,6 +787,87 @@ void CreateHangingFirstRequestProtocolHandlerOnIO(const GURL& url,
url, never_respond_handler.Pass());
}
// Wrapper over URLRequestMockHTTPJob that exposes extra callbacks.
class MockHTTPJob : public content::URLRequestMockHTTPJob {
public:
MockHTTPJob(net::URLRequest* request,
net::NetworkDelegate* delegate,
const base::FilePath& file)
: content::URLRequestMockHTTPJob(request, delegate, file) {
}
void set_start_callback(const base::Closure& start_callback) {
start_callback_ = start_callback;
}
virtual void Start() OVERRIDE {
if (!start_callback_.is_null())
start_callback_.Run();
content::URLRequestMockHTTPJob::Start();
}
private:
virtual ~MockHTTPJob() {}
base::Closure start_callback_;
};
// Dummy counter class to live on the UI thread for counting requests.
class RequestCounter : public base::SupportsWeakPtr<RequestCounter> {
public:
RequestCounter() : count_(0) {}
int count() const { return count_; }
void RequestStarted() { count_++; }
private:
int count_;
};
// Protocol handler which counts the number of requests that start.
class CountingProtocolHandler
: public net::URLRequestJobFactory::ProtocolHandler {
public:
CountingProtocolHandler(const base::FilePath& file,
const base::WeakPtr<RequestCounter>& counter)
: file_(file),
counter_(counter),
weak_factory_(this) {
}
virtual ~CountingProtocolHandler() {}
virtual net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const OVERRIDE {
MockHTTPJob* job = new MockHTTPJob(request, network_delegate, file_);
job->set_start_callback(base::Bind(&CountingProtocolHandler::RequestStarted,
weak_factory_.GetWeakPtr()));
return job;
}
void RequestStarted() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&RequestCounter::RequestStarted, counter_));
}
private:
base::FilePath file_;
base::WeakPtr<RequestCounter> counter_;
mutable base::WeakPtrFactory<CountingProtocolHandler> weak_factory_;
};
// Makes |url| respond to requests with the contents of |file|, counting the
// number that start in |counter|.
void CreateCountingProtocolHandlerOnIO(
const GURL& url,
const base::FilePath& file,
const base::WeakPtr<RequestCounter>& counter) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> protocol_handler(
new CountingProtocolHandler(file, counter));
net::URLRequestFilter::GetInstance()->AddUrlProtocolHandler(
url, protocol_handler.Pass());
}
// Makes |url| respond to requests with the contents of |file|.
void CreateMockProtocolHandlerOnIO(const GURL& url,
const base::FilePath& file) {
......@@ -869,6 +950,12 @@ class NeverRunsExternalProtocolHandlerDelegate
}
};
base::FilePath GetTestPath(const std::string& file_name) {
return ui_test_utils::GetTestFilePath(
base::FilePath(FILE_PATH_LITERAL("prerender")),
base::FilePath().AppendASCII(file_name));
}
} // namespace
// Many of these tests are flaky. See http://crbug.com/249179
......@@ -1711,8 +1798,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap) {
// Navigate to a page that triggers a prerender for a URL that never commits.
const GURL kNoCommitUrl("http://never-respond.example.com");
base::FilePath file(FILE_PATH_LITERAL(
"chrome/test/data/prerender/prerender_page.html"));
base::FilePath file(GetTestPath("prerender_page.html"));
base::RunLoop prerender_start_loop;
BrowserThread::PostTask(
......@@ -1734,8 +1820,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap) {
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap2) {
// Navigate to a page that then navigates to a URL that never commits.
const GURL kNoCommitUrl("http://never-respond.example.com");
base::FilePath file(FILE_PATH_LITERAL(
"chrome/test/data/prerender/prerender_page.html"));
base::FilePath file(GetTestPath("prerender_page.html"));
base::RunLoop prerender_start_loop;
BrowserThread::PostTask(
......@@ -3409,8 +3494,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
std::string webstore_url = extension_urls::GetWebstoreLaunchURL();
// Mock out requests to the Web Store.
base::FilePath file(FILE_PATH_LITERAL(
"chrome/test/data/prerender/prerender_page.html"));
base::FilePath file(GetTestPath("prerender_page.html"));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&CreateMockProtocolHandlerOnIO,
......@@ -3578,16 +3662,81 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNewNavigationEntry) {
// Attempt a swap-in in a new tab, verifying that session storage namespace
// merging works.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageNewTab) {
PrerenderTestURL("files/prerender/prerender_session_storage.html",
FINAL_STATUS_USED, 1);
// Mock out some URLs and count the number of requests to one of them. Both
// prerender_session_storage.html and init_session_storage.html need to be
// mocked so they are same-origin.
const GURL kInitURL("http://prerender.test/init_session_storage.html");
base::FilePath init_file = GetTestPath("init_session_storage.html");
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&CreateMockProtocolHandlerOnIO, kInitURL, init_file));
const GURL kTestURL("http://prerender.test/prerender_session_storage.html");
base::FilePath test_file = GetTestPath("prerender_session_storage.html");
RequestCounter counter;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&CreateCountingProtocolHandlerOnIO,
kTestURL, test_file, counter.AsWeakPtr()));
PrerenderTestURL(kTestURL, FINAL_STATUS_USED, 1);
// Open a new tab to navigate in.
ui_test_utils::NavigateToURLWithDisposition(
current_browser(),
test_server()->GetURL("files/prerender/init_session_storage.html"),
NEW_FOREGROUND_TAB,
current_browser(), kInitURL, NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
// Now navigate in the new tab. Set expect_swap_to_succeed to false because
// the swap does not occur synchronously.
//
// TODO(davidben): When all swaps become asynchronous, remove the OpenURL
// return value assertion and let this go through the usual successful-swap
// codepath.
NavigateToDestURLWithDisposition(CURRENT_TAB, false);
// Verify DidDisplayPass manually since the previous call skipped it.
EXPECT_TRUE(DidDisplayPass(
current_browser()->tab_strip_model()->GetActiveWebContents()));
// Only one request to the test URL started.
EXPECT_EQ(1, counter.count());
}
// Attempt a swap-in in a new tab, verifying that session storage namespace
// merging works. Unlike the above test, the swap is for a navigation that would
// normally be cross-process.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageNewTabCrossProcess) {
base::FilePath test_data_dir;
ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
// Mock out some URLs and count the number of requests to one of them. Both
// prerender_session_storage.html and init_session_storage.html need to be
// mocked so they are same-origin.
const GURL kInitURL("http://prerender.test/init_session_storage.html");
base::FilePath init_file = GetTestPath("init_session_storage.html");
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&CreateMockProtocolHandlerOnIO, kInitURL, init_file));
const GURL kTestURL("http://prerender.test/prerender_session_storage.html");
base::FilePath test_file = GetTestPath("prerender_session_storage.html");
RequestCounter counter;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&CreateCountingProtocolHandlerOnIO,
kTestURL, test_file, counter.AsWeakPtr()));
PrerenderTestURL(kTestURL, FINAL_STATUS_USED, 1);
// Open a new tab to navigate in.
ui_test_utils::NavigateToURLWithDisposition(
current_browser(), kInitURL, NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
// Navigate to about:blank so the next navigation is cross-process.
ui_test_utils::NavigateToURL(current_browser(),
GURL(content::kAboutBlankURL));
// Now navigate in the new tab. Set expect_swap_to_succeed to false because
// the swap does not occur synchronously.
//
......@@ -3599,6 +3748,9 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageNewTab) {
// Verify DidDisplayPass manually since the previous call skipped it.
EXPECT_TRUE(DidDisplayPass(
current_browser()->tab_strip_model()->GetActiveWebContents()));
// Only one request to the test URL started.
EXPECT_EQ(1, counter.count());
}
// Verify that session storage conflicts don't merge.
......
......@@ -1127,20 +1127,14 @@ PrerenderManager::PendingSwap::PendingSwap(
start_time_(base::TimeTicks::Now()),
swap_successful_(false),
weak_factory_(this) {
// Record the RFH id in the tracker to install throttles on MAIN_FRAME
// requests from that route.
int render_process_id =
target_contents->GetMainFrame()->GetProcess()->GetID();
int render_frame_id = target_contents->GetMainFrame()->GetRoutingID();
render_frame_route_id_pair_ = PrerenderTracker::ChildRouteIdPair(
render_process_id, render_frame_id);
manager_->prerender_tracker()->AddPrerenderPendingSwap(
render_frame_route_id_pair_, url_);
RenderViewCreated(target_contents->GetRenderViewHost());
}
PrerenderManager::PendingSwap::~PendingSwap() {
manager_->prerender_tracker()->RemovePrerenderPendingSwap(
render_frame_route_id_pair_, swap_successful_);
for (size_t i = 0; i < main_rfh_ids_.size(); i++) {
manager_->prerender_tracker()->RemovePrerenderPendingSwap(
main_rfh_ids_[i], swap_successful_);
}
}
void PrerenderManager::PendingSwap::BeginSwap() {
......@@ -1185,6 +1179,20 @@ void PrerenderManager::PendingSwap::DidCommitProvisionalLoadForFrame(
prerender_data_->ClearPendingSwap();
}
void PrerenderManager::PendingSwap::RenderViewCreated(
content::RenderViewHost* render_view_host) {
// Record the RFH id in the tracker to install throttles on MAIN_FRAME
// requests from that route.
int render_process_id =
render_view_host->GetMainFrame()->GetProcess()->GetID();
int render_frame_id = render_view_host->GetMainFrame()->GetRoutingID();
PrerenderTracker::ChildRouteIdPair render_frame_route_id_pair(
render_process_id, render_frame_id);
main_rfh_ids_.push_back(render_frame_route_id_pair);
manager_->prerender_tracker()->AddPrerenderPendingSwap(
render_frame_route_id_pair, url_);
}
void PrerenderManager::PendingSwap::DidFailProvisionalLoad(
int64 frame_id,
const base::string16& frame_unique_name,
......
......@@ -454,6 +454,8 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
const GURL& validated_url,
content::PageTransition transition_type,
content::RenderViewHost* render_view_host) OVERRIDE;
virtual void RenderViewCreated(
content::RenderViewHost* render_view_host) OVERRIDE;
virtual void DidFailProvisionalLoad(
int64 frame_id,
const base::string16& frame_unique_name,
......@@ -479,7 +481,7 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
bool should_replace_current_entry_;
base::TimeTicks start_time_;
PrerenderTracker::ChildRouteIdPair render_frame_route_id_pair_;
std::vector<PrerenderTracker::ChildRouteIdPair> main_rfh_ids_;
base::OneShotTimer<PendingSwap> merge_timeout_;
bool swap_successful_;
......
......@@ -118,6 +118,7 @@ void PrerenderTracker::AddPendingSwapThrottleOnIOThread(
DCHECK(it != pending_swap_throttle_map_.end());
if (it == pending_swap_throttle_map_.end())
return;
CHECK(!it->second.throttle);
it->second.throttle = throttle;
}
......
......@@ -469,7 +469,7 @@ void ChromeResourceDispatcherHostDelegate::AppendStandardResourceThrottles(
request, prerender_tracker_));
}
if (prerender_tracker_->IsPendingSwapRequestOnIOThread(
info->GetChildID(), info->GetRouteID(), request->url())) {
info->GetChildID(), info->GetRenderFrameID(), request->url())) {
throttles->push_back(new prerender::PrerenderPendingSwapThrottle(
request, prerender_tracker_));
}
......
......@@ -58,6 +58,7 @@
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/bindings_policy.h"
......@@ -1059,6 +1060,10 @@ void RenderViewHostImpl::DragSourceSystemDragEnded() {
Send(new DragMsg_SourceSystemDragEnded(GetRoutingID()));
}
RenderFrameHost* RenderViewHostImpl::GetMainFrame() {
return RenderFrameHost::FromID(GetProcess()->GetID(), main_frame_routing_id_);
}
void RenderViewHostImpl::AllowBindings(int bindings_flags) {
// Never grant any bindings to browser plugin guests.
if (GetProcess()->IsGuest()) {
......
......@@ -124,6 +124,7 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual ~RenderViewHostImpl();
// RenderViewHost implementation.
virtual RenderFrameHost* GetMainFrame() OVERRIDE;
virtual void AllowBindings(int binding_flags) OVERRIDE;
virtual void ClearFocusedNode() OVERRIDE;
virtual void ClosePage() OVERRIDE;
......
......@@ -42,6 +42,7 @@ struct WebPluginAction;
namespace content {
class ChildProcessSecurityPolicy;
class RenderFrameHost;
class RenderViewHostDelegate;
class SessionStorageNamespace;
class SiteInstance;
......@@ -71,6 +72,9 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
virtual ~RenderViewHost() {}
// Returns the main frame for this render view.
virtual RenderFrameHost* GetMainFrame() = 0;
// Tell the render view to enable a set of javascript bindings. The argument
// should be a combination of values from BindingsPolicy.
virtual void AllowBindings(int binding_flags) = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment