Chromium Code Reviews| Index: content/browser/renderer_host/async_resource_handler.cc |
| =================================================================== |
| --- content/browser/renderer_host/async_resource_handler.cc (revision 142108) |
| +++ content/browser/renderer_host/async_resource_handler.cc (working copy) |
| @@ -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,6 +44,10 @@ |
| // 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. |
| @@ -81,18 +85,46 @@ |
| AsyncResourceHandler::AsyncResourceHandler( |
| ResourceMessageFilter* filter, |
| int routing_id, |
| - const GURL& url, |
| + net::URLRequest* request, |
| ResourceDispatcherHostImpl* rdh) |
| : filter_(filter), |
| routing_id_(routing_id), |
| + request_(request), |
| rdh_(rdh), |
| next_buffer_size_(kInitialReadBufSize), |
| - url_(url) { |
| + pending_data_count_(0), |
| + did_defer_(false) { |
| } |
| AsyncResourceHandler::~AsyncResourceHandler() { |
| } |
| +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, |
| uint64 position, |
| uint64 size) { |
| @@ -105,13 +137,13 @@ |
| ResourceResponse* response, |
| bool* defer) { |
| *defer = true; |
| - net::URLRequest* request = rdh_->GetURLRequest( |
| - GlobalRequestID(filter_->child_id(), request_id)); |
| + MarkAsDeferred(true); |
| + |
| 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)); |
| @@ -125,36 +157,34 @@ |
| // 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) { |
| - GURL request_url(request->url()); |
| + const 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)); |
| } |
| @@ -207,7 +237,7 @@ |
| next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize); |
| } |
| - if (!rdh_->WillSendData(filter_->child_id(), request_id, defer)) { |
| + if (!WillSendData(defer)) { |
| // We should not send this data now, we have too many pending requests. |
| return true; |
| } |
| @@ -219,7 +249,8 @@ |
| // 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. |
| - rdh_->DataReceivedACK(filter_->child_id(), request_id); |
| + OnDataReceivedACK(); |
| + |
| // We just unmapped the memory. |
| read_buffer_ = NULL; |
| return false; |
| @@ -227,10 +258,8 @@ |
| // 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)); |
| @@ -250,7 +279,7 @@ |
| // If we crash here, figure out what URL the renderer was requesting. |
| // http://crbug.com/107692 |
| char url_buf[128]; |
| - base::strlcpy(url_buf, url_.spec().c_str(), arraysize(url_buf)); |
| + base::strlcpy(url_buf, request_->url().spec().c_str(), arraysize(url_buf)); |
| base::debug::Alias(url_buf); |
| TimeTicks completion_time = TimeTicks::Now(); |
| @@ -283,4 +312,40 @@ |
| } |
| } |
| +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 set us IPC messages. |
|
jam
2012/06/19 06:03:34
nit: set -> send
|
| + // TODO(darin): Implement an IPC message filter instead? |
| + |
| + ResourceRequestInfoImpl* info = |
| + ResourceRequestInfoImpl::ForRequest(request_); |
| + if (deferred) { |
| + info->set_async_handler(this); |
| + } else { |
| + info->set_async_handler(NULL); |
| + } |
| +} |
| + |
| +void AsyncResourceHandler::ResumeIfDeferred() { |
| + if (did_defer_) { |
| + MarkAsDeferred(false); |
| + controller()->Resume(); |
| + } |
| +} |
| + |
| } // namespace content |