diff options
Diffstat (limited to 'content/browser')
-rw-r--r-- | content/browser/renderer_host/global_request_id.h | 10 | ||||
-rw-r--r-- | content/browser/renderer_host/render_view_host_delegate.h | 8 | ||||
-rw-r--r-- | content/browser/renderer_host/resource_dispatcher_host.cc | 92 | ||||
-rw-r--r-- | content/browser/renderer_host/resource_dispatcher_host.h | 11 | ||||
-rw-r--r-- | content/browser/tab_contents/navigation_controller.cc | 19 | ||||
-rw-r--r-- | content/browser/tab_contents/navigation_controller.h | 15 | ||||
-rw-r--r-- | content/browser/tab_contents/navigation_entry.h | 19 | ||||
-rw-r--r-- | content/browser/tab_contents/page_navigator.h | 6 | ||||
-rw-r--r-- | content/browser/tab_contents/tab_contents.cc | 29 | ||||
-rw-r--r-- | content/browser/tab_contents/tab_contents.h | 6 |
10 files changed, 192 insertions, 23 deletions
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, |