summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-21 21:32:42 +0000
committerdarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-21 21:32:42 +0000
commit3b2c4f541ddf9c3787774ec9e6f4aacd5ca85d3f (patch)
tree787bf1b1f30b12b48dc06c007ad04ef98a4a143b
parent1b553c993c7776ff7c4591e533b0ed6737a57048 (diff)
downloadchromium_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
-rw-r--r--content/browser/renderer_host/async_resource_handler.cc114
-rw-r--r--content/browser/renderer_host/async_resource_handler.h28
-rw-r--r--content/browser/renderer_host/buffered_resource_handler.cc7
-rw-r--r--content/browser/renderer_host/cross_site_resource_handler.cc44
-rw-r--r--content/browser/renderer_host/cross_site_resource_handler.h11
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host_impl.cc99
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host_impl.h10
-rw-r--r--content/browser/renderer_host/resource_loader.cc12
-rw-r--r--content/browser/renderer_host/resource_loader.h2
-rw-r--r--content/browser/renderer_host/resource_request_info_impl.cc2
-rw-r--r--content/browser/renderer_host/resource_request_info_impl.h21
-rw-r--r--content/browser/renderer_host/sync_resource_handler.cc21
-rw-r--r--content/browser/renderer_host/sync_resource_handler.h4
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_;
};