diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-03 02:00:48 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-03 02:00:48 +0000 |
commit | 4ad5d77d96dfc6f08a845b6871ecbffa64d6f6e2 (patch) | |
tree | 269f9c3132012cea865b9630082ba9009d08f8df | |
parent | 143ee25a94004844d0edc8ab5c57913af5d2056f (diff) | |
download | chromium_src-4ad5d77d96dfc6f08a845b6871ecbffa64d6f6e2.zip chromium_src-4ad5d77d96dfc6f08a845b6871ecbffa64d6f6e2.tar.gz chromium_src-4ad5d77d96dfc6f08a845b6871ecbffa64d6f6e2.tar.bz2 |
Fix a bug where redirect chain gets lost on process swap.
BUG=79520
TEST=
Review URL: http://codereview.chromium.org/8669014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112847 0039d316-1c4b-4281-b951-d872f2087c98
32 files changed, 583 insertions, 60 deletions
diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc index 8c89736..d6bf4d6 100644 --- a/chrome/browser/extensions/app_process_apitest.cc +++ b/chrome/browser/extensions/app_process_apitest.cc @@ -348,9 +348,26 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, MAYBE_AppProcessRedirectBack) { browser()->NewTab(); ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html")); browser()->NewTab(); - // Wait until the second tab finishes its redirect train (2 hops). + // Wait until the second tab finishes its redirect train (3 hops). + // 1. We navigate to redirect.html + // 2. Renderer navigates and finishes, counting as a load stop. + // 3. Renderer issues the meta refresh to navigate to server-redirect. + // 4. Renderer is now in a "provisional load", waiting for navigation to + // complete. + // 5. Browser sees a redirect response from server-redirect to empty.html, and + // transfers that to a new navigation, using RequestTransferURL. + // 6. We navigate to empty.html. + // 7. Renderer is still in a provisional load to server-redirect, so that is + // cancelled, and counts as a load stop + // 8. Renderer navigates to empty.html, and finishes loading, counting as the + // third load stop +#if defined(TRANSFER_REDIRECTS_BUG79520) + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), base_url.Resolve("path1/redirect.html"), 3); +#else ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( browser(), base_url.Resolve("path1/redirect.html"), 2); +#endif // 3 tabs, including the initial about:blank. The last 2 should be the same // process. @@ -358,8 +375,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, MAYBE_AppProcessRedirectBack) { EXPECT_EQ("/files/extensions/api_test/app_process/path1/empty.html", browser()->GetTabContentsAt(2)->controller(). GetLastCommittedEntry()->url().path()); - RenderViewHost* host = browser()->GetTabContentsAt(1)->render_view_host(); - EXPECT_EQ(host->process(), + EXPECT_EQ(browser()->GetTabContentsAt(1)->render_view_host()->process(), browser()->GetTabContentsAt(2)->render_view_host()->process()); } diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc index 9f9bb41f..b2f096e 100644 --- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc @@ -19,6 +19,7 @@ #include "chrome/browser/profiles/profile_io_data.h" #include "chrome/browser/renderer_host/chrome_url_request_user_data.h" #include "chrome/browser/renderer_host/safe_browsing_resource_handler.h" +#include "chrome/browser/renderer_host/transfer_navigation_resource_handler.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/ui/auto_login_prompter.h" #include "chrome/browser/ui/login/login_prompt.h" @@ -151,7 +152,11 @@ ResourceHandler* ChromeResourceDispatcherHostDelegate::RequestBeginning( const content::ResourceContext& resource_context, bool is_subresource, int child_id, - int route_id) { + int route_id, + bool is_continuation_of_transferred_request) { + if (is_continuation_of_transferred_request) + ChromeURLRequestUserData::Delete(request); + ChromeURLRequestUserData* user_data = ChromeURLRequestUserData::Create(request); if (prerender_tracker_->IsPrerenderingOnIOThread(child_id, route_id)) { @@ -177,6 +182,14 @@ ResourceHandler* ChromeResourceDispatcherHostDelegate::RequestBeginning( handler, child_id, route_id, resource_dispatcher_host_, request, resource_context.appcache_service()); #endif + + // TODO(mpcomplete): Leaving disabled for now, since I'm checking this in + // close to the branch point. +#if defined(TRANSFER_REDIRECTS_BUG79520) + handler = new TransferNavigationResourceHandler( + handler, resource_dispatcher_host_, request); +#endif + return handler; } diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h index 0fc5cb6..d8e4e28 100644 --- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h +++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h @@ -47,7 +47,8 @@ class ChromeResourceDispatcherHostDelegate const content::ResourceContext& resource_context, bool is_subresource, int child_id, - int route_id) OVERRIDE; + int route_id, + bool is_continuation_of_transferred_request) OVERRIDE; virtual ResourceHandler* DownloadStarting( ResourceHandler* handler, const content::ResourceContext& resource_context, diff --git a/chrome/browser/renderer_host/chrome_url_request_user_data.cc b/chrome/browser/renderer_host/chrome_url_request_user_data.cc index aeabcd1..511cbf1 100644 --- a/chrome/browser/renderer_host/chrome_url_request_user_data.cc +++ b/chrome/browser/renderer_host/chrome_url_request_user_data.cc @@ -30,3 +30,9 @@ ChromeURLRequestUserData* ChromeURLRequestUserData::Create( request->SetUserData(kKeyName, user_data); return user_data; } + +// static +void ChromeURLRequestUserData::Delete(net::URLRequest* request) { + DCHECK(request); + request->SetUserData(kKeyName, NULL); +} diff --git a/chrome/browser/renderer_host/chrome_url_request_user_data.h b/chrome/browser/renderer_host/chrome_url_request_user_data.h index 4f356ea..5acc9bd 100644 --- a/chrome/browser/renderer_host/chrome_url_request_user_data.h +++ b/chrome/browser/renderer_host/chrome_url_request_user_data.h @@ -19,6 +19,10 @@ class ChromeURLRequestUserData : public net::URLRequest::UserData { // is owned by |request|. static ChromeURLRequestUserData* Create(net::URLRequest* request); + // Delete the ChromeURLRequestUserData from a |request|. |request| must be + // non-NULL. + static void Delete(net::URLRequest* request); + // Gets the ChromeURLRequestUserData instance attached to |request|, or // returns NULL if one is not attached. |request| must be non-NULL. static ChromeURLRequestUserData* Get(const net::URLRequest* request); diff --git a/chrome/browser/renderer_host/transfer_navigation_resource_handler.cc b/chrome/browser/renderer_host/transfer_navigation_resource_handler.cc new file mode 100644 index 0000000..e0e80ad --- /dev/null +++ b/chrome/browser/renderer_host/transfer_navigation_resource_handler.cc @@ -0,0 +1,169 @@ +// Copyright (c) 2011 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. + +#include "chrome/browser/renderer_host/transfer_navigation_resource_handler.h" + +#include "base/bind.h" +#include "chrome/browser/profiles/profile_io_data.h" +#include "chrome/browser/extensions/extension_info_map.h" +#include "content/browser/renderer_host/render_view_host.h" +#include "content/browser/renderer_host/render_view_host_delegate.h" +#include "content/browser/renderer_host/resource_dispatcher_host.h" +#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" + +namespace { + +// This code is borrowed from ChromeContentRendererClient. We want to mimic +// the logic used by the renderer. +// TODO(mpcomplete): move to common and share with the renderer logic. +// http://crbug.com/79520 +const Extension* GetNonBookmarkAppExtension( + const ExtensionSet& extensions, const GURL& url) { + // Exclude bookmark apps, which do not use the app process model. + const Extension* extension = extensions.GetByURL(ExtensionURLInfo(url)); + if (extension && extension->from_bookmark()) + extension = NULL; + return extension; +} + +bool CrossesExtensionExtents( + const ExtensionSet& extensions, + const GURL& old_url, + const GURL& new_url) { + const Extension* new_url_extension = GetNonBookmarkAppExtension(extensions, + new_url); + const Extension* old_url_extension = GetNonBookmarkAppExtension(extensions, + old_url); + + // TODO(creis): Temporary workaround for crbug.com/59285: Only return true if + // we would enter an extension app's extent from a non-app, or if we leave an + // extension with no web extent. We avoid swapping processes to exit a hosted + // app for now, since we do not yet support postMessage calls from outside the + // app back into it (e.g., as in Facebook OAuth 2.0). + bool old_url_is_hosted_app = old_url_extension && + !old_url_extension->web_extent().is_empty(); + if (old_url_is_hosted_app) + return false; + + return old_url_extension != new_url_extension; +} + +void RequestTransferURLOnUIThread(int render_process_id, + int render_view_id, + GURL new_url, + GURL referrer, + WindowOpenDisposition window_open_disposition, + int64 frame_id, + const GlobalRequestID& request_id) { + RenderViewHost* rvh = RenderViewHost::FromID(render_process_id, + render_view_id); + if (!rvh) + return; + + RenderViewHostDelegate* delegate = rvh->delegate(); + if (!delegate) + return; + + delegate->RequestTransferURL(new_url, referrer, window_open_disposition, + frame_id, request_id); +} + +} // namespace + +TransferNavigationResourceHandler::TransferNavigationResourceHandler( + ResourceHandler* handler, + ResourceDispatcherHost* resource_dispatcher_host, + net::URLRequest* request) + : next_handler_(handler), + rdh_(resource_dispatcher_host), + request_(request) { +} + +TransferNavigationResourceHandler::~TransferNavigationResourceHandler() { +} + +bool TransferNavigationResourceHandler::OnUploadProgress(int request_id, + uint64 position, + uint64 size) { + return next_handler_->OnUploadProgress(request_id, position, size); +} + +bool TransferNavigationResourceHandler::OnRequestRedirected( + int request_id, + const GURL& new_url, + content::ResourceResponse* response, + bool* defer) { + + ResourceDispatcherHostRequestInfo* info = + ResourceDispatcherHost::InfoForRequest(request_); + + // If a toplevel request is redirecting across extension extents, we want to + // switch processes. We do this by deferring the redirect and resuming the + // request once the navigation controller properly assigns the right process + // to host the new URL. + // TODO(mpcomplete): handle for cases other than extensions (e.g. WebUI). + const content::ResourceContext& resource_context = *info->context(); + ProfileIOData* io_data = + reinterpret_cast<ProfileIOData*>(resource_context.GetUserData(NULL)); + + if (info->resource_type() == ResourceType::MAIN_FRAME && + CrossesExtensionExtents(io_data->GetExtensionInfoMap()->extensions(), + request_->url(), new_url)) { + int render_process_id, render_view_id; + if (ResourceDispatcherHost::RenderViewForRequest( + request_, &render_process_id, &render_view_id)) { + + GlobalRequestID global_id(info->child_id(), info->request_id()); + rdh_->MarkAsTransferredNavigation(global_id, request_); + + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::Bind(&RequestTransferURLOnUIThread, + render_process_id, render_view_id, + new_url, GURL(request_->referrer()), CURRENT_TAB, + info->frame_id(), global_id)); + + *defer = true; + return true; + } + } + + return next_handler_->OnRequestRedirected( + request_id, new_url, response, defer); +} + +bool TransferNavigationResourceHandler::OnResponseStarted( + int request_id, content::ResourceResponse* response) { + return next_handler_->OnResponseStarted(request_id, response); +} + +bool TransferNavigationResourceHandler::OnWillStart(int request_id, + const GURL& url, + bool* defer) { + return next_handler_->OnWillStart(request_id, url, defer); +} + +bool TransferNavigationResourceHandler::OnWillRead(int request_id, + net::IOBuffer** buf, + int* buf_size, + int min_size) { + return next_handler_->OnWillRead(request_id, buf, buf_size, min_size); +} + +bool TransferNavigationResourceHandler::OnReadCompleted(int request_id, + int* bytes_read) { + return next_handler_->OnReadCompleted(request_id, bytes_read); +} + +bool TransferNavigationResourceHandler::OnResponseCompleted( + int request_id, + const net::URLRequestStatus& status, + const std::string& security_info) { + return next_handler_->OnResponseCompleted(request_id, status, security_info); +} + +void TransferNavigationResourceHandler::OnRequestClosed() { + next_handler_->OnRequestClosed(); +} diff --git a/chrome/browser/renderer_host/transfer_navigation_resource_handler.h b/chrome/browser/renderer_host/transfer_navigation_resource_handler.h new file mode 100644 index 0000000..2943de3 --- /dev/null +++ b/chrome/browser/renderer_host/transfer_navigation_resource_handler.h @@ -0,0 +1,69 @@ +// Copyright (c) 2011 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_RENDERER_HOST_TRANSFER_NAVIGATION_RESOURCE_HANDLER_H_ +#define CHROME_BROWSER_RENDERER_HOST_TRANSFER_NAVIGATION_RESOURCE_HANDLER_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/memory/ref_counted.h" +#include "base/time.h" +#include "base/timer.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "content/browser/renderer_host/resource_handler.h" + +namespace content { +struct ResourceResponse; +} + +namespace net { +class URLRequest; +} + +class ResourceDispatcherHost; + +// This ResourceHandler checks whether a navigation redirect will cause a +// renderer process swap. When that happens, we remember the request so +// that we can transfer it to be handled by the new renderer. This fixes +// http://crbug.com/79520 +class TransferNavigationResourceHandler : public ResourceHandler { + public: + TransferNavigationResourceHandler( + ResourceHandler* handler, + ResourceDispatcherHost* resource_dispatcher_host, + net::URLRequest* request); + + // ResourceHandler implementation: + virtual bool OnUploadProgress( + int request_id, uint64 position, uint64 size) OVERRIDE; + virtual bool OnRequestRedirected( + int request_id, const GURL& new_url, content::ResourceResponse* response, + bool* defer) OVERRIDE; + virtual bool OnResponseStarted( + int request_id, content::ResourceResponse* response) OVERRIDE; + virtual bool OnWillStart( + int request_id, const GURL& url, bool* defer) OVERRIDE; + virtual bool OnWillRead( + int request_id, net::IOBuffer** buf, int* buf_size, + int min_size) OVERRIDE; + virtual bool OnReadCompleted(int request_id, int* bytes_read) OVERRIDE; + virtual bool OnResponseCompleted(int request_id, + const net::URLRequestStatus& status, + const std::string& security_info) OVERRIDE; + virtual void OnRequestClosed() OVERRIDE; + + private: + virtual ~TransferNavigationResourceHandler(); + + scoped_refptr<ResourceHandler> next_handler_; + ResourceDispatcherHost* rdh_; + net::URLRequest* request_; + + DISALLOW_COPY_AND_ASSIGN(TransferNavigationResourceHandler); +}; + + +#endif // CHROME_BROWSER_RENDERER_HOST_TRANSFER_NAVIGATION_RESOURCE_HANDLER_H_ diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index a333ef8..cd45080 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -2969,9 +2969,8 @@ TabContents* Browser::OpenURL(const GURL& url, content::PageTransition transition) { // For specifying a referrer, use the version of OpenURL taking OpenURLParams. DCHECK(referrer.is_empty()); - return OpenURLFromTab(NULL, - OpenURLParams(url, referrer, disposition, transition, - false)); + return OpenURLFromTab(NULL, OpenURLParams(url, referrer, disposition, + transition, false)); } TabContents* Browser::OpenURL(const OpenURLParams& params) { @@ -3389,6 +3388,8 @@ TabContents* Browser::OpenURLFromTab(TabContents* source, nav_params.user_gesture = true; nav_params.override_encoding = params.override_encoding; nav_params.is_renderer_initiated = params.is_renderer_initiated; + nav_params.transferred_global_request_id = + params.transferred_global_request_id; browser::Navigate(&nav_params); return nav_params.target_contents ? diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc index 9c92019..ac4f2ef 100644 --- a/chrome/browser/ui/browser_navigator.cc +++ b/chrome/browser/ui/browser_navigator.cc @@ -242,6 +242,24 @@ Profile* GetSourceProfile(browser::NavigateParams* params, return params->browser->profile(); } +void LoadURLInContents(TabContents* target_contents, + const GURL& url, + browser::NavigateParams* params, + const std::string& extra_headers) { + if (params->transferred_global_request_id != GlobalRequestID()) { + target_contents->controller().TransferURL( + url, params->referrer, params->transition, extra_headers, + params->transferred_global_request_id, + params->is_renderer_initiated); + } else if (params->is_renderer_initiated) { + target_contents->controller().LoadURLFromRenderer( + url, params->referrer, params->transition, extra_headers); + } else { + target_contents->controller().LoadURL( + url, params->referrer, params->transition, extra_headers); + } + +} // This class makes sure the Browser object held in |params| is made visible // by the time it goes out of scope, provided |params| wants it to be shown. @@ -499,13 +517,9 @@ void Navigate(NavigateParams* params) { if (!HandleNonNavigationAboutURL(url)) { // Perform the actual navigation, tracking whether it came from the // renderer. - if (params->is_renderer_initiated) { - params->target_contents->controller().LoadURLFromRenderer( - url, params->referrer, params->transition, extra_headers); - } else { - params->target_contents->controller().LoadURL( - url, params->referrer, params->transition, extra_headers); - } + + LoadURLInContents(params->target_contents->tab_contents(), + url, params, extra_headers); } } else { // |target_contents| was specified non-NULL, and so we assume it has already @@ -553,13 +567,7 @@ void Navigate(NavigateParams* params) { } else if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE && target->GetURL() != params->url) { InitializeExtraHeaders(params, NULL, &extra_headers); - if (params->is_renderer_initiated) { - target->controller().LoadURLFromRenderer( - params->url, params->referrer, params->transition, extra_headers); - } else { - target->controller().LoadURL( - params->url, params->referrer, params->transition, extra_headers); - } + LoadURLInContents(target, params->url, params, extra_headers); } // If the singleton tab isn't already selected, select it. diff --git a/chrome/browser/ui/browser_navigator.h b/chrome/browser/ui/browser_navigator.h index da7c01c..9f40509 100644 --- a/chrome/browser/ui/browser_navigator.h +++ b/chrome/browser/ui/browser_navigator.h @@ -8,6 +8,7 @@ #include <string> +#include "content/browser/renderer_host/global_request_id.h" #include "content/public/common/page_transition_types.h" #include "googleurl/src/gurl.h" #include "ui/gfx/rect.h" @@ -180,6 +181,11 @@ struct NavigateParams { // creating a Browser. Profile* profile; + // Refers to a navigation that was parked in the browser in order to be + // transferred to another RVH. Only used in case of a redirection of a request + // to a different site that created a new RVH. + GlobalRequestID transferred_global_request_id; + private: NavigateParams(); }; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index cf42538..548183a 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2030,6 +2030,8 @@ 'browser/renderer_host/plugin_info_message_filter.h', 'browser/renderer_host/safe_browsing_resource_handler.cc', 'browser/renderer_host/safe_browsing_resource_handler.h', + 'browser/renderer_host/transfer_navigation_resource_handler.cc', + 'browser/renderer_host/transfer_navigation_resource_handler.h', 'browser/renderer_host/web_cache_manager.cc', 'browser/renderer_host/web_cache_manager.h', 'browser/renderer_preferences_util.cc', diff --git a/chrome/test/data/extensions/api_test/webrequest/framework.js b/chrome/test/data/extensions/api_test/webrequest/framework.js index 5cbbdb7..e2a0bc1 100644 --- a/chrome/test/data/extensions/api_test/webrequest/framework.js +++ b/chrome/test/data/extensions/api_test/webrequest/framework.js @@ -215,8 +215,10 @@ function captureEvent(name, details, callback) { } }); if (!found) { + console.log("Expected events: " + + JSON.stringify(expectedEventData, null, 2)); chrome.test.fail("Received unexpected event '" + name + "':" + - JSON.stringify(details)); + JSON.stringify(details, null, 2)); } capturedEventData.push({label: label, event: name, details: details}); diff --git a/content/browser/renderer_host/global_request_id.h b/content/browser/renderer_host/global_request_id.h index 031026f..f9a87db 100644 --- a/content/browser/renderer_host/global_request_id.h +++ b/content/browser/renderer_host/global_request_id.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -27,6 +27,14 @@ struct GlobalRequestID { return request_id < other.request_id; return child_id < other.child_id; } + bool operator==(const GlobalRequestID& other) const { + return child_id == other.child_id && + request_id == other.request_id; + } + bool operator!=(const GlobalRequestID& other) const { + return child_id != other.child_id || + request_id != other.request_id; + } }; #endif // CHROME_BROWSER_RENDERER_HOST_GLOBAL_REQUEST_ID_H_ diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index 8a4bb7f..e0faaa3 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h @@ -27,6 +27,7 @@ class SkBitmap; class TabContents; class WebKeyboardEvent; struct ContextMenuParams; +struct GlobalRequestID; struct NativeWebKeyboardEvent; struct ViewHostMsg_CreateWindow_Params; struct ViewHostMsg_FrameNavigate_Params; @@ -276,6 +277,13 @@ class CONTENT_EXPORT RenderViewHostDelegate : public IPC::Channel::Listener { WindowOpenDisposition disposition, int64 source_frame_id) {} + // The page wants to transfer the request to a new renderer. + virtual void RequestTransferURL(const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + int64 source_frame_id, + const GlobalRequestID& old_request_id) {} + // A javascript message, confirmation or prompt should be shown. virtual void RunJavaScriptMessage(const RenderViewHost* rvh, const string16& message, diff --git a/content/browser/renderer_host/resource_dispatcher_host.cc b/content/browser/renderer_host/resource_dispatcher_host.cc index fb0f1c3..1bd30fc 100644 --- a/content/browser/renderer_host/resource_dispatcher_host.cc +++ b/content/browser/renderer_host/resource_dispatcher_host.cc @@ -312,7 +312,12 @@ ResourceDispatcherHost::ResourceDispatcherHost( ResourceDispatcherHost::~ResourceDispatcherHost() { AsyncResourceHandler::GlobalCleanup(); + for (PendingRequestList::const_iterator i = pending_requests_.begin(); + i != pending_requests_.end(); ++i) { + transferred_navigations_.erase(i->first); + } STLDeleteValues(&pending_requests_); + DCHECK(transferred_navigations_.empty()); } void ResourceDispatcherHost::Initialize() { @@ -340,6 +345,10 @@ void ResourceDispatcherHost::OnShutdown() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); is_shutdown_ = true; resource_queue_.Shutdown(); + for (PendingRequestList::const_iterator i = pending_requests_.begin(); + i != pending_requests_.end(); ++i) { + transferred_navigations_.erase(i->first); + } STLDeleteValues(&pending_requests_); // Make sure we shutdown the timer now, otherwise by the time our destructor // runs if the timer is still running the Task is deleted twice (once by @@ -457,6 +466,20 @@ void ResourceDispatcherHost::BeginRequest( base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf)); base::debug::Alias(url_buf); + // If the request that's coming in is being transferred from another process, + // we want to reuse and resume the old request rather than start a new one. + net::URLRequest* deferred_request = NULL; + + GlobalRequestID old_request_id(request_data.transferred_request_child_id, + request_data.transferred_request_request_id); + TransferredNavigations::iterator iter = + transferred_navigations_.find(old_request_id); + if (iter != transferred_navigations_.end()) { + deferred_request = iter->second; + pending_requests_.erase(old_request_id); + transferred_navigations_.erase(iter); + } + const content::ResourceContext& resource_context = filter_->resource_context(); @@ -508,13 +531,18 @@ void ResourceDispatcherHost::BeginRequest( } // Construct the request. - net::URLRequest* request = new net::URLRequest(request_data.url, this); - request->set_method(request_data.method); - request->set_first_party_for_cookies(request_data.first_party_for_cookies); - request->set_referrer(referrer.spec()); - net::HttpRequestHeaders headers; - headers.AddHeadersFromString(request_data.headers); - request->SetExtraRequestHeaders(headers); + net::URLRequest* request; + if (deferred_request) { + request = deferred_request; + } else { + request = new net::URLRequest(request_data.url, this); + request->set_method(request_data.method); + request->set_first_party_for_cookies(request_data.first_party_for_cookies); + request->set_referrer(referrer.spec()); + net::HttpRequestHeaders headers; + headers.AddHeadersFromString(request_data.headers); + request->SetExtraRequestHeaders(headers); + } int load_flags = request_data.load_flags; // Although EV status is irrelevant to sub-frames and sub-resources, we have @@ -543,15 +571,16 @@ void ResourceDispatcherHost::BeginRequest( net::LOAD_DO_NOT_SAVE_COOKIES); } - // Raw headers are sensitive, as they inclide Cookie/Set-Cookie, so only - // allow requesting them if requestor has ReadRawCookies permission. + // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only + // allow requesting them if requester has ReadRawCookies permission. if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) && !policy->CanReadRawCookies(child_id)) { - VLOG(1) << "Denied unathorized request for raw headers"; + VLOG(1) << "Denied unauthorized request for raw headers"; load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; } request->set_load_flags(load_flags); + request->set_context( filter_->GetURLRequestContext(request_data.resource_type)); request->set_priority(DetermineRequestPriority(request_data.resource_type)); @@ -584,8 +613,11 @@ void ResourceDispatcherHost::BeginRequest( if (delegate_) { bool sub = request_data.resource_type != ResourceType::MAIN_FRAME; - handler = delegate_->RequestBeginning(handler, request, resource_context, - sub, child_id, route_id); + bool is_continuation_of_transferred_request = + (deferred_request != NULL); + handler = delegate_->RequestBeginning( + handler, request, resource_context, sub, child_id, route_id, + is_continuation_of_transferred_request); } // Make extra info and read footer (contains request ID). @@ -624,7 +656,16 @@ void ResourceDispatcherHost::BeginRequest( request, resource_context.appcache_service(), child_id, request_data.appcache_host_id, request_data.resource_type); - BeginRequestInternal(request); + if (deferred_request) { + // This is a request that has been transferred from another process, so + // resume it rather than continuing the regular procedure for starting a + // request. Currently this is only done for redirects. + GlobalRequestID global_id(extra_info->child_id(), extra_info->request_id()); + pending_requests_[global_id] = request; + request->FollowDeferredRedirect(); + } else { + BeginRequestInternal(request); + } } void ResourceDispatcherHost::OnReleaseDownloadedFile(int request_id) { @@ -1039,7 +1080,13 @@ void ResourceDispatcherHost::CancelRequestsForRoute(int child_id, i != pending_requests_.end(); ++i) { if (i->first.child_id == child_id) { ResourceDispatcherHostRequestInfo* info = InfoForRequest(i->second); + GlobalRequestID id(child_id, i->first.request_id); + DCHECK(id == i->first); + // Don't cancel navigations that are transferring to another process, + // since they belong to another process now. if (!info->is_download() && + (transferred_navigations_.find(id) == + transferred_navigations_.end()) && (route_id == -1 || route_id == info->route_id())) { matching_requests.push_back( GlobalRequestID(child_id, i->first.request_id)); @@ -1418,8 +1465,15 @@ bool ResourceDispatcherHost::CompleteResponseStarted(net::URLRequest* request) { void ResourceDispatcherHost::CancelRequest(int child_id, int request_id, bool from_renderer) { - PendingRequestList::iterator i = pending_requests_.find( - GlobalRequestID(child_id, request_id)); + GlobalRequestID id(child_id, request_id); + if (from_renderer) { + // When the old renderer dies, it sends a message to us to cancel its + // requests. + if (transferred_navigations_.find(id) != transferred_navigations_.end()) + return; + } + + PendingRequestList::iterator i = pending_requests_.find(id); if (i == pending_requests_.end()) { // We probably want to remove this warning eventually, but I wanted to be // able to notice when this happens during initial development since it @@ -1481,7 +1535,7 @@ int ResourceDispatcherHost::IncrementOutstandingRequestsMemoryCost( new_cost += cost; CHECK(new_cost >= 0); if (new_cost == 0) - outstanding_requests_memory_cost_map_.erase(prev_entry); + outstanding_requests_memory_cost_map_.erase(child_id); else outstanding_requests_memory_cost_map_[child_id] = new_cost; @@ -2179,3 +2233,9 @@ bool ResourceDispatcherHost::allow_cross_origin_auth_prompt() { void ResourceDispatcherHost::set_allow_cross_origin_auth_prompt(bool value) { allow_cross_origin_auth_prompt_ = value; } + +void ResourceDispatcherHost::MarkAsTransferredNavigation( + const GlobalRequestID& transferred_request_id, + net::URLRequest* ransferred_request) { + transferred_navigations_[transferred_request_id] = ransferred_request; +} diff --git a/content/browser/renderer_host/resource_dispatcher_host.h b/content/browser/renderer_host/resource_dispatcher_host.h index 21be2a3..cdf30b3 100644 --- a/content/browser/renderer_host/resource_dispatcher_host.h +++ b/content/browser/renderer_host/resource_dispatcher_host.h @@ -264,6 +264,12 @@ class CONTENT_EXPORT ResourceDispatcherHost : public net::URLRequest::Delegate { return delegate_; } + // Marks the request as "parked". This happens if a request is + // redirected cross-site and needs to be resumed by a new render view. + void MarkAsTransferredNavigation( + const GlobalRequestID& transferred_request_id, + net::URLRequest* transferred_request); + private: FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies); @@ -500,6 +506,11 @@ class CONTENT_EXPORT ResourceDispatcherHost : public net::URLRequest::Delegate { static bool is_prefetch_enabled_; bool allow_cross_origin_auth_prompt_; + // Maps the request ID of request that is being transferred to a new RVH + // to the respective request. + typedef std::map<GlobalRequestID, net::URLRequest*> TransferredNavigations; + TransferredNavigations transferred_navigations_; + DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHost); }; diff --git a/content/browser/tab_contents/navigation_controller.cc b/content/browser/tab_contents/navigation_controller.cc index 383a1ec..21582ab 100644 --- a/content/browser/tab_contents/navigation_controller.cc +++ b/content/browser/tab_contents/navigation_controller.cc @@ -497,6 +497,25 @@ void NavigationController::AddTransientEntry(NavigationEntry* entry) { tab_contents_->NotifyNavigationStateChanged(kInvalidateAll); } +void NavigationController::TransferURL( + const GURL& url, + const GURL& referrer, + content::PageTransition transition, + const std::string& extra_headers, + const GlobalRequestID& transferred_global_request_id, + bool is_renderer_initiated) { + // The user initiated a load, we don't need to reload anymore. + needs_reload_ = false; + + NavigationEntry* entry = CreateNavigationEntry(url, referrer, transition, + is_renderer_initiated, + extra_headers, + browser_context_); + entry->set_transferred_global_request_id(transferred_global_request_id); + + LoadEntry(entry); +} + void NavigationController::LoadURL( const GURL& url, const GURL& referrer, diff --git a/content/browser/tab_contents/navigation_controller.h b/content/browser/tab_contents/navigation_controller.h index 5d99842..1e8096d 100644 --- a/content/browser/tab_contents/navigation_controller.h +++ b/content/browser/tab_contents/navigation_controller.h @@ -14,6 +14,7 @@ #include "base/memory/linked_ptr.h" #include "base/time.h" #include "googleurl/src/gurl.h" +#include "content/browser/renderer_host/global_request_id.h" #include "content/browser/ssl/ssl_manager.h" #include "content/common/content_export.h" #include "content/public/browser/navigation_type.h" @@ -187,6 +188,20 @@ class CONTENT_EXPORT NavigationController { content::PageTransition type, const std::string& extra_headers); + // Behaves like LoadURL() and LoadURLFromRenderer() but marks the new + // navigation as being transferred from one RVH to another. In this case the + // browser can recycle the old request once the new renderer wants to + // navigate. + // |transferred_global_request_id| identifies the request ID of the old + // request. + void TransferURL( + const GURL& url, + const GURL& referrer, + content::PageTransition transition, + const std::string& extra_headers, + const GlobalRequestID& transferred_global_request_id, + bool is_renderer_initiated); + // Loads the current page if this NavigationController was restored from // history and the current page has not loaded yet. void LoadIfNecessary(); diff --git a/content/browser/tab_contents/navigation_entry.h b/content/browser/tab_contents/navigation_entry.h index eea3f35..8648ebb 100644 --- a/content/browser/tab_contents/navigation_entry.h +++ b/content/browser/tab_contents/navigation_entry.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" +#include "content/browser/renderer_host/global_request_id.h" #include "content/common/content_export.h" #include "content/public/common/page_transition_types.h" #include "content/public/common/page_type.h" @@ -412,6 +413,15 @@ class CONTENT_EXPORT NavigationEntry { return restore_type_; } + void set_transferred_global_request_id( + const GlobalRequestID& transferred_global_request_id) { + transferred_global_request_id_ = transferred_global_request_id; + } + + GlobalRequestID transferred_global_request_id() const { + return transferred_global_request_id_; + } + private: // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING // Session/Tab restore save portions of this class so that it can be recreated @@ -451,6 +461,15 @@ class CONTENT_EXPORT NavigationEntry { // cleared to force a refresh. mutable string16 cached_display_title_; + // In case a navigation is transferred to a new RVH but the request has + // been generated in the renderer already, this identifies the old request so + // that it can be resumed. The old request is stored until the + // ResourceDispatcher receives the navigation from the renderer which + // carries this |transferred_global_request_id_| annotation. Once the request + // is transferred to the new process, this is cleared and the request + // continues as normal. + GlobalRequestID transferred_global_request_id_; + // Copy and assignment is explicitly allowed for this class. }; diff --git a/content/browser/tab_contents/page_navigator.h b/content/browser/tab_contents/page_navigator.h index 9369a7a..98bafd3 100644 --- a/content/browser/tab_contents/page_navigator.h +++ b/content/browser/tab_contents/page_navigator.h @@ -12,6 +12,7 @@ #include <string> +#include "content/browser/renderer_host/global_request_id.h" #include "content/common/content_export.h" #include "content/public/common/page_transition_types.h" #include "googleurl/src/gurl.h" @@ -26,7 +27,6 @@ struct CONTENT_EXPORT OpenURLParams { content::PageTransition transition, bool is_renderer_initiated); ~OpenURLParams(); -class TabContents; // The URL/referrer to be opened. GURL url; @@ -44,6 +44,10 @@ class TabContents; // The override encoding of the URL contents to be opened. std::string override_encoding; + // Reference to the old request id in case this is a navigation that is being + // transferred to a new renderer. + GlobalRequestID transferred_global_request_id; + private: OpenURLParams(); }; diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc index 284ea26..bfdbd979 100644 --- a/content/browser/tab_contents/tab_contents.cc +++ b/content/browser/tab_contents/tab_contents.cc @@ -167,6 +167,10 @@ void MakeNavigateParams(const NavigationEntry& entry, GetNavigationType(controller.browser_context(), entry, reload_type); params->request_time = base::Time::Now(); params->extra_headers = entry.extra_headers(); + params->transferred_request_child_id = + entry.transferred_global_request_id().child_id; + params->transferred_request_request_id = + entry.transferred_global_request_id().request_id; if (delegate) delegate->AddNavigationHeaders(params->url, ¶ms->extra_headers); @@ -1750,6 +1754,17 @@ void TabContents::RequestOpenURL(const GURL& url, const GURL& referrer, WindowOpenDisposition disposition, int64 source_frame_id) { + // Delegate to RequestTransferURL because this is just the generic + // case where |old_request_id| is empty. + RequestTransferURL(url, referrer, disposition, source_frame_id, + GlobalRequestID()); +} + +void TabContents::RequestTransferURL(const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + int64 source_frame_id, + const GlobalRequestID& old_request_id) { TabContents* new_contents = NULL; content::PageTransition transition_type = content::PAGE_TRANSITION_LINK; if (render_manager_.web_ui()) { @@ -1761,13 +1776,17 @@ void TabContents::RequestOpenURL(const GURL& url, // want web sites to see a referrer of "chrome://blah" (and some // chrome: URLs might have search terms or other stuff we don't want to // send to the site), so we send no referrer. - new_contents = OpenURL(url, GURL(), disposition, - render_manager_.web_ui()->link_transition_type()); + OpenURLParams params(url, GURL(), disposition, + render_manager_.web_ui()->link_transition_type(), + false /* is_renderer_initiated */); + params.transferred_global_request_id = old_request_id; + new_contents = OpenURL(params); transition_type = render_manager_.web_ui()->link_transition_type(); } else { - new_contents = OpenURL(OpenURLParams( - url, referrer, disposition, content::PAGE_TRANSITION_LINK, - true /* is_renderer_initiated */)); + OpenURLParams params(url, referrer, disposition, + content::PAGE_TRANSITION_LINK, true /* is_renderer_initiated */); + params.transferred_global_request_id = old_request_id; + new_contents = OpenURL(params); } if (new_contents) { // Notify observers. diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h index 0473b7d..46120ed 100644 --- a/content/browser/tab_contents/tab_contents.h +++ b/content/browser/tab_contents/tab_contents.h @@ -513,6 +513,12 @@ class CONTENT_EXPORT TabContents : public PageNavigator, const GURL& referrer, WindowOpenDisposition disposition, int64 source_frame_id) OVERRIDE; + virtual void RequestTransferURL( + const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + int64 source_frame_id, + const GlobalRequestID& transferred_global_request_id) OVERRIDE; virtual void RunJavaScriptMessage(const RenderViewHost* rvh, const string16& message, const string16& default_prompt, diff --git a/content/common/request_extra_data.cc b/content/common/request_extra_data.cc index a079a39..ab9ee91 100644 --- a/content/common/request_extra_data.cc +++ b/content/common/request_extra_data.cc @@ -11,13 +11,17 @@ RequestExtraData::RequestExtraData(WebReferrerPolicy referrer_policy, int64 frame_id, bool parent_is_main_frame, int64 parent_frame_id, - content::PageTransition transition_type) + content::PageTransition transition_type, + int transferred_request_child_id, + int transferred_request_request_id) : webkit_glue::WebURLRequestExtraDataImpl(referrer_policy), is_main_frame_(is_main_frame), frame_id_(frame_id), parent_is_main_frame_(parent_is_main_frame), parent_frame_id_(parent_frame_id), - transition_type_(transition_type) { + transition_type_(transition_type), + transferred_request_child_id_(transferred_request_child_id), + transferred_request_request_id_(transferred_request_request_id) { } RequestExtraData::~RequestExtraData() { diff --git a/content/common/request_extra_data.h b/content/common/request_extra_data.h index 2dc1b2a..b7ca525 100644 --- a/content/common/request_extra_data.h +++ b/content/common/request_extra_data.h @@ -21,7 +21,9 @@ class CONTENT_EXPORT RequestExtraData int64 frame_id, bool parent_is_main_frame, int64 parent_frame_id, - content::PageTransition transition_type); + content::PageTransition transition_type, + int transferred_request_child_id, + int transferred_request_request_id); virtual ~RequestExtraData(); bool is_main_frame() const { return is_main_frame_; } @@ -29,6 +31,12 @@ class CONTENT_EXPORT RequestExtraData bool parent_is_main_frame() const { return parent_is_main_frame_; } int64 parent_frame_id() const { return parent_frame_id_; } content::PageTransition transition_type() const { return transition_type_; } + int transferred_request_child_id() const { + return transferred_request_child_id_; + } + int transferred_request_request_id() const { + return transferred_request_request_id_; + } private: bool is_main_frame_; @@ -36,6 +44,8 @@ class CONTENT_EXPORT RequestExtraData bool parent_is_main_frame_; int64 parent_frame_id_; content::PageTransition transition_type_; + int transferred_request_child_id_; + int transferred_request_request_id_; DISALLOW_COPY_AND_ASSIGN(RequestExtraData); }; diff --git a/content/common/resource_dispatcher.cc b/content/common/resource_dispatcher.cc index fdce5c9..2983302 100644 --- a/content/common/resource_dispatcher.cc +++ b/content/common/resource_dispatcher.cc @@ -106,12 +106,18 @@ IPCResourceLoaderBridge::IPCResourceLoaderBridge( request_.parent_is_main_frame = extra_data->parent_is_main_frame(); request_.parent_frame_id = extra_data->parent_frame_id(); request_.transition_type = extra_data->transition_type(); + request_.transferred_request_child_id = + extra_data->transferred_request_child_id(); + request_.transferred_request_request_id = + extra_data->transferred_request_request_id(); } else { request_.is_main_frame = false; request_.frame_id = -1; request_.parent_is_main_frame = false; request_.parent_frame_id = -1; request_.transition_type = content::PAGE_TRANSITION_LINK; + request_.transferred_request_child_id = -1; + request_.transferred_request_request_id = -1; } } diff --git a/content/common/resource_dispatcher_unittest.cc b/content/common/resource_dispatcher_unittest.cc index e5c8a08..d133bc1 100644 --- a/content/common/resource_dispatcher_unittest.cc +++ b/content/common/resource_dispatcher_unittest.cc @@ -173,7 +173,7 @@ class ResourceDispatcherTest : public testing::Test, request_info.routing_id = 0; RequestExtraData extra_data(WebKit::WebReferrerPolicyDefault, true, 0, false, -1, - content::PAGE_TRANSITION_LINK); + content::PAGE_TRANSITION_LINK, -1, -1); request_info.extra_data = &extra_data; return dispatcher_->CreateBridge(request_info); diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h index 854290a..5230206 100644 --- a/content/common/resource_messages.h +++ b/content/common/resource_messages.h @@ -111,6 +111,13 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request) IPC_STRUCT_MEMBER(int64, parent_frame_id) IPC_STRUCT_MEMBER(content::PageTransition, transition_type) + + // The following two members identify a previous request that has been + // created before this navigation has been transferred to a new render view. + // This serves the purpose of recycling the old request. + // Unless this refers to a transferred navigation, these values are -1 and -1. + IPC_STRUCT_MEMBER(int, transferred_request_child_id) + IPC_STRUCT_MEMBER(int, transferred_request_request_id) IPC_STRUCT_END() // Resource messages sent from the browser to the renderer. diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 45aa69e..ff07616 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -591,6 +591,13 @@ IPC_STRUCT_BEGIN(ViewMsg_Navigate_Params) // Extra headers (separated by \n) to send during the request. IPC_STRUCT_MEMBER(std::string, extra_headers) + + // The following two members identify a previous request that has been + // created before this navigation is being transferred to a new render view. + // This serves the purpose of recycling the old request. + // Unless this refers to a transferred navigation, these values are -1 and -1. + IPC_STRUCT_MEMBER(int, transferred_request_child_id) + IPC_STRUCT_MEMBER(int, transferred_request_request_id) IPC_STRUCT_END() IPC_STRUCT_BEGIN(ViewMsg_New_Params) diff --git a/content/public/browser/resource_dispatcher_host_delegate.h b/content/public/browser/resource_dispatcher_host_delegate.h index 50ed0a4..64fc497 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.h +++ b/content/public/browser/resource_dispatcher_host_delegate.h @@ -53,7 +53,8 @@ class ResourceDispatcherHostDelegate { const content::ResourceContext& resource_context, bool is_subresource, int child_id, - int route_id) = 0; + int route_id, + bool is_continuation_of_transferred_request) = 0; // Allows an embedder to add additional resource handlers for a download. // |is_new_request| is true if this is a request that is just starting, i.e. diff --git a/content/public/renderer/navigation_state.cc b/content/public/renderer/navigation_state.cc index b69518f..2c70bb7 100644 --- a/content/public/renderer/navigation_state.cc +++ b/content/public/renderer/navigation_state.cc @@ -15,7 +15,9 @@ NavigationState::NavigationState(content::PageTransition transition_type, is_content_initiated_(is_content_initiated), pending_page_id_(pending_page_id), pending_history_list_offset_(pending_history_list_offset), - was_within_same_page_(false) { + was_within_same_page_(false), + transferred_request_child_id_(-1), + transferred_request_request_id_(-1) { } NavigationState::~NavigationState() {} diff --git a/content/public/renderer/navigation_state.h b/content/public/renderer/navigation_state.h index efdcac1..cb6bc64 100644 --- a/content/public/renderer/navigation_state.h +++ b/content/public/renderer/navigation_state.h @@ -57,6 +57,23 @@ class NavigationState { void set_was_within_same_page(bool value) { was_within_same_page_ = value; } bool was_within_same_page() const { return was_within_same_page_; } + // transferred_request_child_id and transferred_request_request_id identify + // a request that has been created before the navigation is being transferred + // to a new renderer. This is used to recycle the old request once the new + // renderer tries to pick up the navigation of the old one. + void set_transferred_request_child_id(int value) { + transferred_request_child_id_ = value; + } + int transferred_request_child_id() const { + return transferred_request_child_id_; + } + void set_transferred_request_request_id(int value) { + transferred_request_request_id_ = value; + } + int transferred_request_request_id() const { + return transferred_request_request_id_; + } + private: NavigationState(content::PageTransition transition_type, bool is_content_initiated, @@ -70,6 +87,8 @@ class NavigationState { int pending_history_list_offset_; bool was_within_same_page_; + int transferred_request_child_id_; + int transferred_request_request_id_; DISALLOW_COPY_AND_ASSIGN(NavigationState); }; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 62e2589..12c7ead 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -2052,13 +2052,8 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( // issue a special POST navigation in WebKit (via // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl // for examples of how to send the httpBody data. - // Note2: We normally don't do this for browser-initiated navigations, since - // it's pointless to tell the browser about navigations it gave us. But - // we do potentially ask the browser to handle a redirect that was originally - // initiated by the browser. See http://crbug.com/70943 - // - // TODO(creis): Move this redirect check to the browser process to avoid - // ping-ponging. See http://crbug.com/72380. + // TODO(mpcomplete): remove is_redirect clause when http://crbug.com/79520 is + // fixed. if (!frame->parent() && (is_content_initiated || is_redirect) && default_policy == WebKit::WebNavigationPolicyCurrentTab && request.httpMethod() == "GET" && !url.SchemeIs(chrome::kAboutScheme)) { @@ -2332,6 +2327,10 @@ void RenderViewImpl::PopulateStateFromPendingNavigationParams( params.page_id, params.pending_history_list_offset, params.transition); + navigation_state->set_transferred_request_child_id( + params.transferred_request_child_id); + navigation_state->set_transferred_request_request_id( + params.transferred_request_request_id); if (params.navigation_type == ViewMsg_Navigate_Type::RESTORE) { // We're doing a load of a page that was restored from the last session. // By default this prefers the cache over loading (LOAD_PREFERRING_CACHE) @@ -2732,7 +2731,9 @@ void RenderViewImpl::willSendRequest(WebFrame* frame, frame->identifier(), frame->parent() == top_frame, frame->parent() ? frame->parent()->identifier() : -1, - transition_type)); + transition_type, + navigation_state->transferred_request_child_id(), + navigation_state->transferred_request_request_id())); DocumentState* top_document_state = DocumentState::FromDataSource(top_data_source); |