diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-21 21:32:42 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-21 21:32:42 +0000 |
commit | 3b2c4f541ddf9c3787774ec9e6f4aacd5ca85d3f (patch) | |
tree | 787bf1b1f30b12b48dc06c007ad04ef98a4a143b | |
parent | 1b553c993c7776ff7c4591e533b0ed6737a57048 (diff) | |
download | chromium_src-3b2c4f541ddf9c3787774ec9e6f4aacd5ca85d3f.zip chromium_src-3b2c4f541ddf9c3787774ec9e6f4aacd5ca85d3f.tar.gz chromium_src-3b2c4f541ddf9c3787774ec9e6f4aacd5ca85d3f.tar.bz2 |
Revert r143341 and r142979.
Some web pages are failing to load, and these patches seem to be the likely
cause.
BUG=133808
TBR=jam@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10636005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@143458 0039d316-1c4b-4281-b951-d872f2087c98
13 files changed, 192 insertions, 183 deletions
diff --git a/content/browser/renderer_host/async_resource_handler.cc b/content/browser/renderer_host/async_resource_handler.cc index 859f9a82..ac70a18 100644 --- a/content/browser/renderer_host/async_resource_handler.cc +++ b/content/browser/renderer_host/async_resource_handler.cc @@ -15,12 +15,12 @@ #include "content/browser/host_zoom_map_impl.h" #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" #include "content/browser/renderer_host/resource_message_filter.h" -#include "content/browser/renderer_host/resource_request_info_impl.h" #include "content/browser/resource_context_impl.h" #include "content/common/resource_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/resource_dispatcher_host_delegate.h" +#include "content/public/browser/resource_request_info.h" #include "content/public/common/resource_response.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" @@ -44,10 +44,6 @@ const int kInitialReadBufSize = 32768; // The maximum size of the shared memory buffer. (512 kilobytes). const int kMaxReadBufSize = 524288; -// Maximum number of pending data messages sent to the renderer at any -// given time for a given request. -const int kMaxPendingDataMessages = 20; - } // namespace // Our version of IOBuffer that uses shared memory. @@ -85,46 +81,16 @@ class SharedIOBuffer : public net::IOBuffer { AsyncResourceHandler::AsyncResourceHandler( ResourceMessageFilter* filter, int routing_id, - net::URLRequest* request, + const GURL& url, ResourceDispatcherHostImpl* rdh) : filter_(filter), routing_id_(routing_id), - request_(request), rdh_(rdh), next_buffer_size_(kInitialReadBufSize), - pending_data_count_(0), - did_defer_(false) { + url_(url) { } AsyncResourceHandler::~AsyncResourceHandler() { - // Cleanup back-pointer stored on the request info. - ResourceRequestInfoImpl::ForRequest(request_)->set_async_handler(NULL); -} - -void AsyncResourceHandler::OnFollowRedirect( - bool has_new_first_party_for_cookies, - const GURL& new_first_party_for_cookies) { - if (!request_->status().is_success()) { - DVLOG(1) << "OnFollowRedirect for invalid request"; - return; - } - - if (has_new_first_party_for_cookies) - request_->set_first_party_for_cookies(new_first_party_for_cookies); - - ResumeIfDeferred(); -} - -void AsyncResourceHandler::OnDataReceivedACK() { - // If the pending data count was higher than the max, resume the request. - if (--pending_data_count_ == kMaxPendingDataMessages) { - // Decrement the pending data count one more time because we also - // incremented it before deferring the request. - --pending_data_count_; - - // Resume the request. - ResumeIfDeferred(); - } } bool AsyncResourceHandler::OnUploadProgress(int request_id, @@ -139,13 +105,13 @@ bool AsyncResourceHandler::OnRequestRedirected(int request_id, ResourceResponse* response, bool* defer) { *defer = true; - MarkAsDeferred(true); - + net::URLRequest* request = rdh_->GetURLRequest( + GlobalRequestID(filter_->child_id(), request_id)); if (rdh_->delegate()) - rdh_->delegate()->OnRequestRedirected(request_, response); + rdh_->delegate()->OnRequestRedirected(request, response); - DevToolsNetLogObserver::PopulateResponseInfo(request_, response); - response->request_start = request_->creation_time(); + DevToolsNetLogObserver::PopulateResponseInfo(request, response); + response->request_start = request->creation_time(); response->response_start = TimeTicks::Now(); return filter_->Send(new ResourceMsg_ReceivedRedirect( routing_id_, request_id, new_url, *response)); @@ -159,34 +125,36 @@ bool AsyncResourceHandler::OnResponseStarted(int request_id, // renderer will be able to set these precisely at the time the // request commits, avoiding the possibility of e.g. zooming the old content // or of having to layout the new content twice. + net::URLRequest* request = rdh_->GetURLRequest( + GlobalRequestID(filter_->child_id(), request_id)); if (rdh_->delegate()) - rdh_->delegate()->OnResponseStarted(request_, response, filter_); + rdh_->delegate()->OnResponseStarted(request, response, filter_); - DevToolsNetLogObserver::PopulateResponseInfo(request_, response); + DevToolsNetLogObserver::PopulateResponseInfo(request, response); ResourceContext* resource_context = filter_->resource_context(); HostZoomMap* host_zoom_map = GetHostZoomMapForResourceContext(resource_context); - const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); + const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); if (info->GetResourceType() == ResourceType::MAIN_FRAME && host_zoom_map) { - const GURL& request_url = request_->url(); + GURL request_url(request->url()); filter_->Send(new ViewMsg_SetZoomLevelForLoadingURL( info->GetRouteID(), request_url, host_zoom_map->GetZoomLevel(net::GetHostOrSpecFromURL( request_url)))); } - response->request_start = request_->creation_time(); + response->request_start = request->creation_time(); response->response_start = TimeTicks::Now(); filter_->Send(new ResourceMsg_ReceivedResponse( routing_id_, request_id, *response)); - if (request_->response_info().metadata) { - std::vector<char> copy(request_->response_info().metadata->data(), - request_->response_info().metadata->data() + - request_->response_info().metadata->size()); + if (request->response_info().metadata) { + std::vector<char> copy(request->response_info().metadata->data(), + request->response_info().metadata->data() + + request->response_info().metadata->size()); filter_->Send(new ResourceMsg_ReceivedCachedMetadata( routing_id_, request_id, copy)); } @@ -239,7 +207,7 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int* bytes_read, next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize); } - if (!WillSendData(defer)) { + if (!rdh_->WillSendData(filter_->child_id(), request_id, defer)) { // We should not send this data now, we have too many pending requests. return true; } @@ -251,8 +219,7 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int* bytes_read, // to fix this. We can't move this call above the WillSendData because // it's killing our read_buffer_, and we don't want that when we pause // the request. - OnDataReceivedACK(); - + rdh_->DataReceivedACK(filter_->child_id(), request_id); // We just unmapped the memory. read_buffer_ = NULL; return false; @@ -260,8 +227,10 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int* bytes_read, // We just unmapped the memory. read_buffer_ = NULL; + net::URLRequest* request = rdh_->GetURLRequest( + GlobalRequestID(filter_->child_id(), request_id)); int encoded_data_length = - DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_); + DevToolsNetLogObserver::GetAndResetEncodedDataLength(request); filter_->Send(new ResourceMsg_DataReceived( routing_id_, request_id, handle, *bytes_read, encoded_data_length)); @@ -281,7 +250,7 @@ bool AsyncResourceHandler::OnResponseCompleted( // If we crash here, figure out what URL the renderer was requesting. // http://crbug.com/107692 char url_buf[128]; - base::strlcpy(url_buf, request_->url().spec().c_str(), arraysize(url_buf)); + base::strlcpy(url_buf, url_.spec().c_str(), arraysize(url_buf)); base::debug::Alias(url_buf); TimeTicks completion_time = TimeTicks::Now(); @@ -314,37 +283,4 @@ void AsyncResourceHandler::GlobalCleanup() { } } -bool AsyncResourceHandler::WillSendData(bool* defer) { - if (++pending_data_count_ > kMaxPendingDataMessages) { - // We reached the max number of data messages that can be sent to - // the renderer for a given request. Pause the request and wait for - // the renderer to start processing them before resuming it. - *defer = true; - MarkAsDeferred(true); - return false; - } - - return true; -} - -void AsyncResourceHandler::MarkAsDeferred(bool deferred) { - did_defer_ = deferred; - - // Set a back-pointer from ResourceRequestInfoImpl to |this| when deferred, - // so that the ResourceDispatcherHostImpl can send us IPC messages. - // TODO(darin): Implement an IPC message filter instead? - - ResourceRequestInfoImpl* info = - ResourceRequestInfoImpl::ForRequest(request_); - if (deferred) - info->set_async_handler(this); -} - -void AsyncResourceHandler::ResumeIfDeferred() { - if (did_defer_) { - MarkAsDeferred(false); - controller()->Resume(); - } -} - } // namespace content diff --git a/content/browser/renderer_host/async_resource_handler.h b/content/browser/renderer_host/async_resource_handler.h index d508487..b865010 100644 --- a/content/browser/renderer_host/async_resource_handler.h +++ b/content/browser/renderer_host/async_resource_handler.h @@ -11,10 +11,6 @@ #include "content/browser/renderer_host/resource_handler.h" #include "googleurl/src/gurl.h" -namespace net { -class URLRequest; -} - namespace content { class ResourceDispatcherHostImpl; class ResourceMessageFilter; @@ -26,15 +22,10 @@ class AsyncResourceHandler : public ResourceHandler { public: AsyncResourceHandler(ResourceMessageFilter* filter, int routing_id, - net::URLRequest* request, + const GURL& url, ResourceDispatcherHostImpl* rdh); virtual ~AsyncResourceHandler(); - // IPC message handlers: - void OnFollowRedirect(bool has_new_first_party_for_cookies, - const GURL& new_first_party_for_cookies); - void OnDataReceivedACK(); - // ResourceHandler implementation: virtual bool OnUploadProgress(int request_id, uint64 position, @@ -65,18 +56,9 @@ class AsyncResourceHandler : public ResourceHandler { static void GlobalCleanup(); private: - // Returns true if it's ok to send the data. If there are already too many - // data messages pending, it defers the request and returns false. In this - // case the caller should not send the data. - bool WillSendData(bool* defer); - - void MarkAsDeferred(bool deferred); - void ResumeIfDeferred(); - scoped_refptr<SharedIOBuffer> read_buffer_; scoped_refptr<ResourceMessageFilter> filter_; int routing_id_; - net::URLRequest* request_; ResourceDispatcherHostImpl* rdh_; // |next_buffer_size_| is the size of the buffer to be allocated on the next @@ -86,11 +68,9 @@ class AsyncResourceHandler : public ResourceHandler { // was filled, up to a maximum size of 512k. int next_buffer_size_; - // Number of messages we've sent to the renderer that we haven't gotten an - // ACK for. This allows us to avoid having too many messages in flight. - int pending_data_count_; - - bool did_defer_; + // TODO(battre): Remove url. This is only for debugging + // http://crbug.com/107692. + GURL url_; DISALLOW_COPY_AND_ASSIGN(AsyncResourceHandler); }; diff --git a/content/browser/renderer_host/buffered_resource_handler.cc b/content/browser/renderer_host/buffered_resource_handler.cc index 11db2df..b57da4a 100644 --- a/content/browser/renderer_host/buffered_resource_handler.cc +++ b/content/browser/renderer_host/buffered_resource_handler.cc @@ -383,6 +383,13 @@ bool BufferedResourceHandler::UseAlternateResourceHandler( net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0); next_handler_->OnResponseCompleted(request_id, status, std::string()); + // Remove the non-owning pointer to the CrossSiteResourceHandler, if any, + // from the extra request info because the CrossSiteResourceHandler (part of + // the original ResourceHandler chain) will be deleted by the next statement. + ResourceRequestInfoImpl* info = + ResourceRequestInfoImpl::ForRequest(request_); + info->set_cross_site_handler(NULL); + // This is handled entirely within the new ResourceHandler, so just reset the // original ResourceHandler. next_handler_ = handler.Pass(); diff --git a/content/browser/renderer_host/cross_site_resource_handler.cc b/content/browser/renderer_host/cross_site_resource_handler.cc index 7527401..6495a63 100644 --- a/content/browser/renderer_host/cross_site_resource_handler.cc +++ b/content/browser/renderer_host/cross_site_resource_handler.cc @@ -10,10 +10,12 @@ #include "base/logging.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" #include "content/browser/renderer_host/resource_request_info_impl.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/resource_controller.h" +#include "content/public/browser/global_request_id.h" #include "content/public/common/resource_response.h" +#include "net/base/io_buffer.h" #include "net/http/http_response_headers.h" namespace content { @@ -37,23 +39,21 @@ CrossSiteResourceHandler::CrossSiteResourceHandler( scoped_ptr<ResourceHandler> next_handler, int render_process_host_id, int render_view_id, - net::URLRequest* request) + ResourceDispatcherHostImpl* rdh) : LayeredResourceHandler(next_handler.Pass()), render_process_host_id_(render_process_host_id), render_view_id_(render_view_id), - request_(request), has_started_response_(false), in_cross_site_transition_(false), request_id_(-1), completed_during_transition_(false), did_defer_(false), completed_status_(), - response_(NULL) { + response_(NULL), + rdh_(rdh) { } CrossSiteResourceHandler::~CrossSiteResourceHandler() { - // Cleanup back-pointer stored on the request info. - ResourceRequestInfoImpl::ForRequest(request_)->set_cross_site_handler(NULL); } bool CrossSiteResourceHandler::OnRequestRedirected( @@ -78,7 +78,14 @@ bool CrossSiteResourceHandler::OnResponseStarted( DCHECK(!in_cross_site_transition_); has_started_response_ = true; - ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_); + // Look up the request and associated info. + GlobalRequestID global_id(render_process_host_id_, request_id); + net::URLRequest* request = rdh_->GetURLRequest(global_id); + if (!request) { + DLOG(WARNING) << "Request wasn't found"; + return false; + } + ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); // If this is a download, just pass the response through without doing a // cross-site check. The renderer will see it is a download and abort the @@ -98,7 +105,7 @@ bool CrossSiteResourceHandler::OnResponseStarted( // Tell the renderer to run the onunload event handler, and wait for the // reply. - StartCrossSiteTransition(request_id, response, defer); + StartCrossSiteTransition(request_id, response, global_id, defer); return true; } @@ -128,8 +135,9 @@ bool CrossSiteResourceHandler::OnResponseCompleted( // so that the error message (e.g., 404) can be displayed to the user. // Also continue with the logic below to remember that we completed // during the cross-site transition. + GlobalRequestID global_id(render_process_host_id_, request_id); bool defer = false; - StartCrossSiteTransition(request_id, NULL, &defer); + StartCrossSiteTransition(request_id, NULL, global_id, &defer); DCHECK(!defer); // Since !has_started_response_. } @@ -150,6 +158,14 @@ void CrossSiteResourceHandler::ResumeResponse() { DCHECK(in_cross_site_transition_); in_cross_site_transition_ = false; + // Find the request for this response. + GlobalRequestID global_id(render_process_host_id_, request_id_); + net::URLRequest* request = rdh_->GetURLRequest(global_id); + if (!request) { + DLOG(WARNING) << "Resuming a request that wasn't found"; + return; + } + if (has_started_response_) { // Send OnResponseStarted to the new renderer. DCHECK(response_); @@ -165,7 +181,7 @@ void CrossSiteResourceHandler::ResumeResponse() { // Remove ourselves from the ExtraRequestInfo. ResourceRequestInfoImpl* info = - ResourceRequestInfoImpl::ForRequest(request_); + ResourceRequestInfoImpl::ForRequest(request); info->set_cross_site_handler(NULL); // If the response completed during the transition, notify the next @@ -183,6 +199,7 @@ void CrossSiteResourceHandler::ResumeResponse() { void CrossSiteResourceHandler::StartCrossSiteTransition( int request_id, ResourceResponse* response, + const GlobalRequestID& global_id, bool* defer) { in_cross_site_transition_ = true; request_id_ = request_id; @@ -190,8 +207,13 @@ void CrossSiteResourceHandler::StartCrossSiteTransition( // Store this handler on the ExtraRequestInfo, so that RDH can call our // ResumeResponse method when the close ACK is received. + net::URLRequest* request = rdh_->GetURLRequest(global_id); + if (!request) { + DLOG(WARNING) << "Cross site response for a request that wasn't found"; + return; + } ResourceRequestInfoImpl* info = - ResourceRequestInfoImpl::ForRequest(request_); + ResourceRequestInfoImpl::ForRequest(request); info->set_cross_site_handler(this); if (has_started_response_) { diff --git a/content/browser/renderer_host/cross_site_resource_handler.h b/content/browser/renderer_host/cross_site_resource_handler.h index 1be17de..1c20e2a 100644 --- a/content/browser/renderer_host/cross_site_resource_handler.h +++ b/content/browser/renderer_host/cross_site_resource_handler.h @@ -9,11 +9,9 @@ #include "content/browser/renderer_host/layered_resource_handler.h" #include "net/url_request/url_request_status.h" -namespace net { -class URLRequest; -} - namespace content { +class ResourceDispatcherHostImpl; +struct GlobalRequestID; // Ensures that cross-site responses are delayed until the onunload handler of // the previous page is allowed to run. This handler wraps an @@ -25,7 +23,7 @@ class CrossSiteResourceHandler : public LayeredResourceHandler { CrossSiteResourceHandler(scoped_ptr<ResourceHandler> next_handler, int render_process_host_id, int render_view_id, - net::URLRequest* request); + ResourceDispatcherHostImpl* rdh); virtual ~CrossSiteResourceHandler(); // ResourceHandler implementation: @@ -53,13 +51,13 @@ class CrossSiteResourceHandler : public LayeredResourceHandler { void StartCrossSiteTransition( int request_id, ResourceResponse* response, + const GlobalRequestID& global_id, bool* defer); void ResumeIfDeferred(); int render_process_host_id_; int render_view_id_; - net::URLRequest* request_; bool has_started_response_; bool in_cross_site_transition_; int request_id_; @@ -68,6 +66,7 @@ class CrossSiteResourceHandler : public LayeredResourceHandler { net::URLRequestStatus completed_status_; std::string completed_security_info_; ResourceResponse* response_; + ResourceDispatcherHostImpl* rdh_; DISALLOW_COPY_AND_ASSIGN(CrossSiteResourceHandler); }; diff --git a/content/browser/renderer_host/resource_dispatcher_host_impl.cc b/content/browser/renderer_host/resource_dispatcher_host_impl.cc index c1ee7d3..7ed1d12 100644 --- a/content/browser/renderer_host/resource_dispatcher_host_impl.cc +++ b/content/browser/renderer_host/resource_dispatcher_host_impl.cc @@ -99,6 +99,10 @@ static ResourceDispatcherHostImpl* g_resource_dispatcher_host; // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates const int kUpdateLoadStatesIntervalMsec = 100; +// Maximum number of pending data messages sent to the renderer at any +// given time for a given request. +const int kMaxPendingDataMessages = 20; + // Maximum byte "cost" of all the outstanding requests for a renderer. // See delcaration of |max_outstanding_requests_cost_per_process_| for details. // This bound is 25MB, which allows for around 6000 outstanding requests. @@ -927,6 +931,22 @@ void ResourceDispatcherHostImpl::BeginRequest( return; } + // Construct the event handler. + scoped_ptr<ResourceHandler> handler; + if (sync_result) { + handler.reset(new SyncResourceHandler( + filter_, request_data.url, sync_result, this)); + } else { + handler.reset(new AsyncResourceHandler( + filter_, route_id, request_data.url, this)); + } + + // The RedirectToFileResourceHandler depends on being next in the chain. + if (request_data.download_to_file) { + handler.reset( + new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); + } + int load_flags = BuildLoadFlagsForRequest(request_data, child_id, sync_result != NULL); @@ -967,22 +987,6 @@ void ResourceDispatcherHostImpl::BeginRequest( upload_size = request_data.upload_data->GetContentLengthSync(); } - // Construct the IPC resource handler. - scoped_ptr<ResourceHandler> handler; - if (sync_result) { - handler.reset(new SyncResourceHandler( - filter_, request, sync_result, this)); - } else { - handler.reset(new AsyncResourceHandler( - filter_, route_id, request, this)); - } - - // The RedirectToFileResourceHandler depends on being next in the chain. - if (request_data.download_to_file) { - handler.reset( - new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); - } - // Install a CrossSiteResourceHandler if this request is coming from a // RenderViewHost with a pending cross-site request. We only check this for // MAIN_FRAME requests. Unblock requests only come from a blocked page, do @@ -993,8 +997,8 @@ void ResourceDispatcherHostImpl::BeginRequest( HasPendingCrossSiteRequest(child_id, route_id)) { // Wrap the event handler to be sure the current page's onunload handler // has a chance to run before we render the new page. - handler.reset(new CrossSiteResourceHandler(handler.Pass(), child_id, - route_id, request)); + handler.reset( + new CrossSiteResourceHandler(handler.Pass(), child_id, route_id, this)); } // Insert a buffered event handler before the actual one. @@ -1078,13 +1082,33 @@ void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) { } void ResourceDispatcherHostImpl::OnDataReceivedACK(int request_id) { - ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); + DataReceivedACK(filter_->child_id(), request_id); +} + +void ResourceDispatcherHostImpl::DataReceivedACK(int child_id, + int request_id) { + ResourceLoader* loader = GetLoader(child_id, request_id); if (!loader) return; ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - if (info->async_handler()) - info->async_handler()->OnDataReceivedACK(); + + // Decrement the number of pending data messages. + info->DecrementPendingDataCount(); + + // If the pending data count was higher than the max, resume the request. + if (info->pending_data_count() == kMaxPendingDataMessages) { + // Decrement the pending data count one more time because we also + // incremented it before pausing the request. + info->DecrementPendingDataCount(); + + // Resume the request. + // + // TODO(darin): Make the AsyncResourceHandler be responsible for resuming + // via its controller(). This static_cast is here as a temporary measure. + // + static_cast<ResourceController*>(loader)->Resume(); + } } void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) { @@ -1148,12 +1172,8 @@ void ResourceDispatcherHostImpl::OnFollowRedirect( return; } - ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - if (info->async_handler()) { - info->async_handler()->OnFollowRedirect( - has_new_first_party_for_cookies, - new_first_party_for_cookies); - } + loader->OnFollowRedirect(has_new_first_party_for_cookies, + new_first_party_for_cookies); } ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo( @@ -1268,6 +1288,28 @@ void ResourceDispatcherHostImpl::BeginSaveFile( BeginRequestInternal(request.Pass(), handler.Pass()); } +bool ResourceDispatcherHostImpl::WillSendData(int child_id, int request_id, + bool* defer) { + ResourceLoader* loader = GetLoader(child_id, request_id); + if (!loader) { + NOTREACHED() << "WillSendData for invalid request"; + return false; + } + + ResourceRequestInfoImpl* info = loader->GetRequestInfo(); + + info->IncrementPendingDataCount(); + if (info->pending_data_count() > kMaxPendingDataMessages) { + // We reached the max number of data messages that can be sent to + // the renderer for a given request. Pause the request and wait for + // the renderer to start processing them before resuming it. + *defer = true; + return false; + } + + return true; +} + void ResourceDispatcherHostImpl::MarkAsTransferredNavigation( const GlobalRequestID& id) { GetLoader(id)->MarkAsTransferring(); @@ -1476,9 +1518,6 @@ void ResourceDispatcherHostImpl::BeginRequestInternal( IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), info->GetChildID()); - - // A ResourceHandler must not outlive its associated URLRequest. - handler.reset(); return; } diff --git a/content/browser/renderer_host/resource_dispatcher_host_impl.h b/content/browser/renderer_host/resource_dispatcher_host_impl.h index d8fece0..9d0a9ff 100644 --- a/content/browser/renderer_host/resource_dispatcher_host_impl.h +++ b/content/browser/renderer_host/resource_dispatcher_host_impl.h @@ -122,6 +122,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl int request_id, bool from_renderer); + // Returns true if it's ok to send the data. If there are already too many + // data messages pending, it pauses the request and returns false. In this + // case the caller should not send the data. + bool WillSendData(int child_id, int request_id, bool* defer); + // 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& id); @@ -188,6 +193,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl // Cancels any blocked request for the specified route id. void CancelBlockedRequestsForRoute(int child_id, int route_id); + // Decrements the pending_data_count for the request and resumes + // the request if it was paused due to too many pending data + // messages sent. + void DataReceivedACK(int child_id, int request_id); + // Maintains a collection of temp files created in support of // the download_to_file capability. Used to grant access to the // child process and to defer deletion of the file until it's diff --git a/content/browser/renderer_host/resource_loader.cc b/content/browser/renderer_host/resource_loader.cc index a1baea5..b5cba21 100644 --- a/content/browser/renderer_host/resource_loader.cc +++ b/content/browser/renderer_host/resource_loader.cc @@ -177,6 +177,18 @@ void ResourceLoader::OnUploadProgressACK() { waiting_for_upload_progress_ack_ = false; } +void ResourceLoader::OnFollowRedirect(bool has_new_first_party_for_cookies, + const GURL& new_first_party_for_cookies) { + if (!request_->status().is_success()) { + DVLOG(1) << "OnDeferredRedirect for invalid request"; + return; + } + + if (has_new_first_party_for_cookies) + request_->set_first_party_for_cookies(new_first_party_for_cookies); + request_->FollowDeferredRedirect(); +} + void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused, const GURL& new_url, bool* defer) { diff --git a/content/browser/renderer_host/resource_loader.h b/content/browser/renderer_host/resource_loader.h index 0b01f18..bb37cdd4 100644 --- a/content/browser/renderer_host/resource_loader.h +++ b/content/browser/renderer_host/resource_loader.h @@ -49,6 +49,8 @@ class ResourceLoader : public net::URLRequest::Delegate, // IPC message handlers: void OnUploadProgressACK(); + void OnFollowRedirect(bool has_new_first_party_for_cookies, + const GURL& new_first_party_for_cookies); private: // net::URLRequest::Delegate implementation: diff --git a/content/browser/renderer_host/resource_request_info_impl.cc b/content/browser/renderer_host/resource_request_info_impl.cc index c063d1d..501d3f0 100644 --- a/content/browser/renderer_host/resource_request_info_impl.cc +++ b/content/browser/renderer_host/resource_request_info_impl.cc @@ -98,7 +98,6 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl( WebKit::WebReferrerPolicy referrer_policy, ResourceContext* context) : cross_site_handler_(NULL), - async_handler_(NULL), process_type_(process_type), child_id_(child_id), route_id_(route_id), @@ -108,6 +107,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl( frame_id_(frame_id), parent_is_main_frame_(parent_is_main_frame), parent_frame_id_(parent_frame_id), + pending_data_count_(0), is_download_(is_download), allow_download_(allow_download), has_user_gesture_(has_user_gesture), diff --git a/content/browser/renderer_host/resource_request_info_impl.h b/content/browser/renderer_host/resource_request_info_impl.h index 38a926d..11bc178 100644 --- a/content/browser/renderer_host/resource_request_info_impl.h +++ b/content/browser/renderer_host/resource_request_info_impl.h @@ -25,7 +25,6 @@ class BlobData; } namespace content { -class AsyncResourceHandler; class CrossSiteResourceHandler; class ResourceContext; struct GlobalRequestID; @@ -84,7 +83,9 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, GlobalRequestID GetGlobalRequestID() const; - // CrossSiteResourceHandler for this request. May be null. + // CrossSiteResourceHandler for this request, if it is a cross-site request. + // (NULL otherwise.) This handler is part of the chain of ResourceHandlers + // pointed to by resource_handler, and is not owned by this class. CrossSiteResourceHandler* cross_site_handler() { return cross_site_handler_; } @@ -92,19 +93,17 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, cross_site_handler_ = h; } - // AsyncResourceHandler for this request. May be null. - AsyncResourceHandler* async_handler() { - return async_handler_; - } - void set_async_handler(AsyncResourceHandler* h) { - async_handler_ = h; - } - // Identifies the type of process (renderer, plugin, etc.) making the request. ProcessType process_type() const { return process_type_; } + // Number of messages we've sent to the renderer that we haven't gotten an + // ACK for. This allows us to avoid having too many messages in flight. + int pending_data_count() const { return pending_data_count_; } + void IncrementPendingDataCount() { pending_data_count_++; } + void DecrementPendingDataCount() { pending_data_count_--; } + // Downloads are allowed only as a top level request. bool allow_download() const { return allow_download_; } @@ -131,7 +130,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, private: // Non-owning, may be NULL. CrossSiteResourceHandler* cross_site_handler_; - AsyncResourceHandler* async_handler_; ProcessType process_type_; int child_id_; @@ -142,6 +140,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, int64 frame_id_; bool parent_is_main_frame_; int64 parent_frame_id_; + int pending_data_count_; bool is_download_; bool allow_download_; bool has_user_gesture_; diff --git a/content/browser/renderer_host/sync_resource_handler.cc b/content/browser/renderer_host/sync_resource_handler.cc index 90a098e..5c149b7 100644 --- a/content/browser/renderer_host/sync_resource_handler.cc +++ b/content/browser/renderer_host/sync_resource_handler.cc @@ -18,15 +18,14 @@ namespace content { SyncResourceHandler::SyncResourceHandler( ResourceMessageFilter* filter, - net::URLRequest* request, + const GURL& url, IPC::Message* result_message, ResourceDispatcherHostImpl* resource_dispatcher_host) : read_buffer_(new net::IOBuffer(kReadBufSize)), filter_(filter), - request_(request), result_message_(result_message), rdh_(resource_dispatcher_host) { - result_.final_url = request_->url(); + result_.final_url = url; } SyncResourceHandler::~SyncResourceHandler() { @@ -47,10 +46,12 @@ bool SyncResourceHandler::OnRequestRedirected( const GURL& new_url, ResourceResponse* response, bool* defer) { + net::URLRequest* request = rdh_->GetURLRequest( + GlobalRequestID(filter_->child_id(), request_id)); if (rdh_->delegate()) - rdh_->delegate()->OnRequestRedirected(request_, response); + rdh_->delegate()->OnRequestRedirected(request, response); - DevToolsNetLogObserver::PopulateResponseInfo(request_, response); + DevToolsNetLogObserver::PopulateResponseInfo(request, response); // TODO(darin): It would be much better if this could live in WebCore, but // doing so requires API changes at all levels. Similar code exists in // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-( @@ -66,10 +67,12 @@ bool SyncResourceHandler::OnResponseStarted( int request_id, ResourceResponse* response, bool* defer) { + net::URLRequest* request = rdh_->GetURLRequest( + GlobalRequestID(filter_->child_id(), request_id)); if (rdh_->delegate()) - rdh_->delegate()->OnResponseStarted(request_, response, filter_); + rdh_->delegate()->OnResponseStarted(request, response, filter_); - DevToolsNetLogObserver::PopulateResponseInfo(request_, response); + DevToolsNetLogObserver::PopulateResponseInfo(request, response); // We don't care about copying the status here. result_.headers = response->headers; @@ -113,8 +116,10 @@ bool SyncResourceHandler::OnResponseCompleted( const std::string& security_info) { result_.status = status; + net::URLRequest* request = rdh_->GetURLRequest( + GlobalRequestID(filter_->child_id(), request_id)); result_.encoded_data_length = - DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_); + DevToolsNetLogObserver::GetAndResetEncodedDataLength(request); ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_); filter_->Send(result_message_); diff --git a/content/browser/renderer_host/sync_resource_handler.h b/content/browser/renderer_host/sync_resource_handler.h index f60f2e1..8e4d4b1 100644 --- a/content/browser/renderer_host/sync_resource_handler.h +++ b/content/browser/renderer_host/sync_resource_handler.h @@ -17,7 +17,6 @@ class Message; namespace net { class IOBuffer; -class URLRequest; } namespace content { @@ -29,7 +28,7 @@ class ResourceMessageFilter; class SyncResourceHandler : public ResourceHandler { public: SyncResourceHandler(ResourceMessageFilter* filter, - net::URLRequest* request, + const GURL& url, IPC::Message* result_message, ResourceDispatcherHostImpl* resource_dispatcher_host); virtual ~SyncResourceHandler(); @@ -65,7 +64,6 @@ class SyncResourceHandler : public ResourceHandler { SyncLoadResult result_; scoped_refptr<ResourceMessageFilter> filter_; - net::URLRequest* request_; IPC::Message* result_message_; ResourceDispatcherHostImpl* rdh_; }; |