summaryrefslogtreecommitdiffstats
path: root/content/browser/loader
diff options
context:
space:
mode:
authorcreis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-25 22:05:14 +0000
committercreis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-25 22:05:14 +0000
commit1f291cd57a56e70369dc2e47e3d4be6102254102 (patch)
tree39f02a836e501f01967e46917303af0fbe785ae0 /content/browser/loader
parent0cb485cc68f91d337534372ebfd5d3a6b24ce7c3 (diff)
downloadchromium_src-1f291cd57a56e70369dc2e47e3d4be6102254102.zip
chromium_src-1f291cd57a56e70369dc2e47e3d4be6102254102.tar.gz
chromium_src-1f291cd57a56e70369dc2e47e3d4be6102254102.tar.bz2
Make ResourceHandlers stateless with respect to child/routing/request IDs.
This lets us transfer an existing handler chain to a new process. BUG=238331 TEST=Follow a link that redirects to the Chrome Web Store. R=ajwong@chromium.org, darin@chromium.org, mpcomplete@chromium.org Review URL: https://codereview.chromium.org/23180005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225263 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/loader')
-rw-r--r--content/browser/loader/async_resource_handler.cc76
-rw-r--r--content/browser/loader/async_resource_handler.h6
-rw-r--r--content/browser/loader/buffered_resource_handler.cc4
-rw-r--r--content/browser/loader/certificate_resource_handler.cc9
-rw-r--r--content/browser/loader/certificate_resource_handler.h8
-rw-r--r--content/browser/loader/cross_site_resource_handler.cc33
-rw-r--r--content/browser/loader/cross_site_resource_handler.h5
-rw-r--r--content/browser/loader/doomed_resource_handler.cc78
-rw-r--r--content/browser/loader/doomed_resource_handler.h60
-rw-r--r--content/browser/loader/redirect_to_file_resource_handler.cc19
-rw-r--r--content/browser/loader/redirect_to_file_resource_handler.h6
-rw-r--r--content/browser/loader/resource_dispatcher_host_impl.cc151
-rw-r--r--content/browser/loader/resource_dispatcher_host_impl.h9
-rw-r--r--content/browser/loader/resource_dispatcher_host_unittest.cc99
-rw-r--r--content/browser/loader/resource_loader.cc20
-rw-r--r--content/browser/loader/resource_loader.h3
-rw-r--r--content/browser/loader/resource_message_delegate.h4
-rw-r--r--content/browser/loader/resource_message_filter.cc7
-rw-r--r--content/browser/loader/resource_message_filter.h6
-rw-r--r--content/browser/loader/resource_request_info_impl.cc20
-rw-r--r--content/browser/loader/resource_request_info_impl.h23
-rw-r--r--content/browser/loader/resource_scheduler_unittest.cc1
-rw-r--r--content/browser/loader/sync_resource_handler.cc31
-rw-r--r--content/browser/loader/sync_resource_handler.h6
-rw-r--r--content/browser/loader/throttling_resource_handler.cc19
-rw-r--r--content/browser/loader/throttling_resource_handler.h9
26 files changed, 404 insertions, 308 deletions
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
index c7d7f49..f007a41 100644
--- a/content/browser/loader/async_resource_handler.cc
+++ b/content/browser/loader/async_resource_handler.cc
@@ -77,13 +77,9 @@ class DependentIOBuffer : public net::WrappedIOBuffer {
};
AsyncResourceHandler::AsyncResourceHandler(
- ResourceMessageFilter* filter,
- ResourceContext* resource_context,
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh)
: ResourceMessageDelegate(request),
- filter_(filter),
- resource_context_(resource_context),
request_(request),
rdh_(rdh),
pending_data_count_(0),
@@ -139,25 +135,34 @@ void AsyncResourceHandler::OnDataReceivedACK(int request_id) {
bool AsyncResourceHandler::OnUploadProgress(int request_id,
uint64 position,
uint64 size) {
- return filter_->Send(new ResourceMsg_UploadProgress(request_id, position,
- size));
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ if (!info->filter())
+ return false;
+ return info->filter()->Send(
+ new ResourceMsg_UploadProgress(request_id, position, size));
}
bool AsyncResourceHandler::OnRequestRedirected(int request_id,
const GURL& new_url,
ResourceResponse* response,
bool* defer) {
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ if (!info->filter())
+ return false;
+
*defer = did_defer_ = true;
if (rdh_->delegate()) {
rdh_->delegate()->OnRequestRedirected(
- new_url, request_, resource_context_, response);
+ new_url, request_, info->GetContext(), response);
}
DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
response->head.request_start = request_->creation_time();
response->head.response_start = TimeTicks::Now();
- return filter_->Send(new ResourceMsg_ReceivedRedirect(
+ return info->filter()->Send(new ResourceMsg_ReceivedRedirect(
request_id, new_url, response->head));
}
@@ -170,20 +175,24 @@ bool AsyncResourceHandler::OnResponseStarted(int request_id,
// request commits, avoiding the possibility of e.g. zooming the old content
// or of having to layout the new content twice.
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ if (!info->filter())
+ return false;
+
if (rdh_->delegate()) {
rdh_->delegate()->OnResponseStarted(
- request_, resource_context_, response, filter_.get());
+ request_, info->GetContext(), response, info->filter());
}
DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
HostZoomMap* host_zoom_map =
- GetHostZoomMapForResourceContext(resource_context_);
+ GetHostZoomMapForResourceContext(info->GetContext());
- const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
if (info->GetResourceType() == ResourceType::MAIN_FRAME && host_zoom_map) {
const GURL& request_url = request_->url();
- filter_->Send(new ViewMsg_SetZoomLevelForLoadingURL(
+ info->filter()->Send(new ViewMsg_SetZoomLevelForLoadingURL(
info->GetRouteID(),
request_url, host_zoom_map->GetZoomLevelForHostAndScheme(
request_url.scheme(),
@@ -192,14 +201,16 @@ bool AsyncResourceHandler::OnResponseStarted(int request_id,
response->head.request_start = request_->creation_time();
response->head.response_start = TimeTicks::Now();
- filter_->Send(new ResourceMsg_ReceivedResponse(request_id, response->head));
+ info->filter()->Send(new ResourceMsg_ReceivedResponse(request_id,
+ response->head));
sent_received_response_msg_ = true;
if (request_->response_info().metadata.get()) {
std::vector<char> copy(request_->response_info().metadata->data(),
request_->response_info().metadata->data() +
request_->response_info().metadata->size());
- filter_->Send(new ResourceMsg_ReceivedCachedMetadata(request_id, copy));
+ info->filter()->Send(new ResourceMsg_ReceivedCachedMetadata(request_id,
+ copy));
}
return true;
@@ -236,6 +247,11 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
if (!bytes_read)
return true;
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ if (!info->filter())
+ return false;
+
buffer_->ShrinkLastAllocation(bytes_read);
UMA_HISTOGRAM_CUSTOM_COUNTS(
@@ -248,10 +264,10 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
if (!sent_first_data_msg_) {
base::SharedMemoryHandle handle;
int size;
- if (!buffer_->ShareToProcess(filter_->PeerHandle(), &handle, &size))
+ if (!buffer_->ShareToProcess(info->filter()->PeerHandle(), &handle, &size))
return false;
- filter_->Send(new ResourceMsg_SetDataBuffer(
- request_id, handle, size, filter_->peer_pid()));
+ info->filter()->Send(new ResourceMsg_SetDataBuffer(
+ request_id, handle, size, info->filter()->peer_pid()));
sent_first_data_msg_ = true;
}
@@ -259,7 +275,7 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
int encoded_data_length =
DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
- filter_->Send(new ResourceMsg_DataReceived(
+ info->filter()->Send(new ResourceMsg_DataReceived(
request_id, data_offset, bytes_read, encoded_data_length));
++pending_data_count_;
UMA_HISTOGRAM_CUSTOM_COUNTS(
@@ -281,14 +297,23 @@ void AsyncResourceHandler::OnDataDownloaded(
int encoded_data_length =
DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
- filter_->Send(new ResourceMsg_DataDownloaded(
- request_id, bytes_downloaded, encoded_data_length));
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ if (info->filter()) {
+ info->filter()->Send(new ResourceMsg_DataDownloaded(
+ request_id, bytes_downloaded, encoded_data_length));
+ }
}
bool AsyncResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
const std::string& security_info) {
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ if (!info->filter())
+ return false;
+
// If we crash here, figure out what URL the renderer was requesting.
// http://crbug.com/107692
char url_buf[128];
@@ -325,11 +350,12 @@ bool AsyncResourceHandler::OnResponseCompleted(
error_code = net::ERR_FAILED;
}
- filter_->Send(new ResourceMsg_RequestComplete(request_id,
- error_code,
- was_ignored_by_handler,
- security_info,
- completion_time));
+ info->filter()->Send(
+ new ResourceMsg_RequestComplete(request_id,
+ error_code,
+ was_ignored_by_handler,
+ security_info,
+ completion_time));
return true;
}
diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h
index b43e0ef..0992841 100644
--- a/content/browser/loader/async_resource_handler.h
+++ b/content/browser/loader/async_resource_handler.h
@@ -28,9 +28,7 @@ class SharedIOBuffer;
class AsyncResourceHandler : public ResourceHandler,
public ResourceMessageDelegate {
public:
- AsyncResourceHandler(ResourceMessageFilter* filter,
- ResourceContext* resource_context,
- net::URLRequest* request,
+ AsyncResourceHandler(net::URLRequest* request,
ResourceDispatcherHostImpl* rdh);
virtual ~AsyncResourceHandler();
@@ -75,8 +73,6 @@ class AsyncResourceHandler : public ResourceHandler,
void ResumeIfDeferred();
scoped_refptr<ResourceBuffer> buffer_;
- scoped_refptr<ResourceMessageFilter> filter_;
- ResourceContext* resource_context_;
net::URLRequest* request_;
ResourceDispatcherHostImpl* rdh_;
diff --git a/content/browser/loader/buffered_resource_handler.cc b/content/browser/loader/buffered_resource_handler.cc
index a3afb3f..beb3228 100644
--- a/content/browser/loader/buffered_resource_handler.cc
+++ b/content/browser/loader/buffered_resource_handler.cc
@@ -307,9 +307,7 @@ bool BufferedResourceHandler::SelectNextHandler(bool* defer) {
if (net::IsSupportedCertificateMimeType(mime_type)) {
// Install certificate file.
scoped_ptr<ResourceHandler> handler(
- new CertificateResourceHandler(request_,
- info->GetChildID(),
- info->GetRouteID()));
+ new CertificateResourceHandler(request_));
return UseAlternateNextHandler(handler.Pass());
}
diff --git a/content/browser/loader/certificate_resource_handler.cc b/content/browser/loader/certificate_resource_handler.cc
index 9d99542..d850b19 100644
--- a/content/browser/loader/certificate_resource_handler.cc
+++ b/content/browser/loader/certificate_resource_handler.cc
@@ -18,15 +18,11 @@
namespace content {
CertificateResourceHandler::CertificateResourceHandler(
- net::URLRequest* request,
- int render_process_host_id,
- int render_view_id)
+ net::URLRequest* request)
: request_(request),
content_length_(0),
read_buffer_(NULL),
resource_buffer_(NULL),
- render_process_host_id_(render_process_host_id),
- render_view_id_(render_view_id),
cert_type_(net::CERTIFICATE_MIME_TYPE_UNKNOWN) {
}
@@ -112,9 +108,10 @@ bool CertificateResourceHandler::OnResponseCompleted(
// Note that it's up to the browser to verify that the certificate
// data is well-formed.
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
GetContentClient()->browser()->AddCertificate(
request_, cert_type_, content_bytes, content_length_,
- render_process_host_id_, render_view_id_);
+ info->GetChildID(), info->GetRouteID());
return true;
}
diff --git a/content/browser/loader/certificate_resource_handler.h b/content/browser/loader/certificate_resource_handler.h
index b1bd8f4..12a7f67 100644
--- a/content/browser/loader/certificate_resource_handler.h
+++ b/content/browser/loader/certificate_resource_handler.h
@@ -31,9 +31,7 @@ namespace content {
//
class CertificateResourceHandler : public ResourceHandler {
public:
- CertificateResourceHandler(net::URLRequest* request,
- int render_process_host_id,
- int render_view_id);
+ explicit CertificateResourceHandler(net::URLRequest* request);
virtual ~CertificateResourceHandler();
virtual bool OnUploadProgress(int request_id,
@@ -87,10 +85,6 @@ class CertificateResourceHandler : public ResourceHandler {
ContentVector buffer_;
scoped_refptr<net::IOBuffer> read_buffer_;
scoped_refptr<net::IOBuffer> resource_buffer_; // Downloaded certificate.
- // The id of the |RenderProcessHost| which started the download.
- int render_process_host_id_;
- // The id of the |RenderView| which started the download.
- int render_view_id_;
net::CertificateMimeType cert_type_;
DISALLOW_COPY_AND_ASSIGN(CertificateResourceHandler);
};
diff --git a/content/browser/loader/cross_site_resource_handler.cc b/content/browser/loader/cross_site_resource_handler.cc
index 6b735f6..90fe84a 100644
--- a/content/browser/loader/cross_site_resource_handler.cc
+++ b/content/browser/loader/cross_site_resource_handler.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "content/browser/cross_site_request_manager.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -36,16 +37,11 @@ void OnCrossSiteResponseHelper(int render_process_id,
CrossSiteResourceHandler::CrossSiteResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
- int render_process_host_id,
- int render_view_id,
net::URLRequest* request)
: 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_(),
@@ -81,6 +77,11 @@ bool CrossSiteResourceHandler::OnResponseStarted(
ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_);
+ // A swap may no longer be needed if we transferred back into the original
+ // process due to a redirect.
+ bool swap_needed = CrossSiteRequestManager::GetInstance()->
+ HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID());
+
// 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
// request.
@@ -92,8 +93,9 @@ bool CrossSiteResourceHandler::OnResponseStarted(
// In both cases, the pending RenderViewHost will stick around until the next
// cross-site navigation, since we are unable to tell when to destroy it.
// See RenderViewHostManager::RendererAbortedProvisionalLoad.
- if (info->is_download() || (response->head.headers.get() &&
- response->head.headers->response_code() == 204)) {
+ if (!swap_needed || info->is_download() ||
+ (response->head.headers.get() &&
+ response->head.headers->response_code() == 204)) {
return next_handler_->OnResponseStarted(request_id, response, defer);
}
@@ -146,15 +148,18 @@ bool CrossSiteResourceHandler::OnResponseCompleted(
// We can now send the response to the new renderer, which will cause
// WebContentsImpl to swap in the new renderer and destroy the old one.
void CrossSiteResourceHandler::ResumeResponse() {
- DCHECK(request_id_ != -1);
+ DCHECK(request_);
DCHECK(in_cross_site_transition_);
in_cross_site_transition_ = false;
+ ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
if (has_started_response_) {
// Send OnResponseStarted to the new renderer.
DCHECK(response_);
bool defer = false;
- if (!next_handler_->OnResponseStarted(request_id_, response_, &defer)) {
+ if (!next_handler_->OnResponseStarted(info->GetRequestID(), response_,
+ &defer)) {
controller()->Cancel();
} else if (!defer) {
// Unpause the request to resume reading. Any further reads will be
@@ -164,14 +169,13 @@ void CrossSiteResourceHandler::ResumeResponse() {
}
// Remove ourselves from the ExtraRequestInfo.
- ResourceRequestInfoImpl* info =
- ResourceRequestInfoImpl::ForRequest(request_);
info->set_cross_site_handler(NULL);
// If the response completed during the transition, notify the next
// event handler.
if (completed_during_transition_) {
- if (next_handler_->OnResponseCompleted(request_id_, completed_status_,
+ if (next_handler_->OnResponseCompleted(info->GetRequestID(),
+ completed_status_,
completed_security_info_)) {
ResumeIfDeferred();
}
@@ -184,7 +188,6 @@ void CrossSiteResourceHandler::StartCrossSiteTransition(
int request_id,
ResourceResponse* response) {
in_cross_site_transition_ = true;
- request_id_ = request_id;
response_ = response;
// Store this handler on the ExtraRequestInfo, so that RDH can call our
@@ -201,8 +204,8 @@ void CrossSiteResourceHandler::StartCrossSiteTransition(
FROM_HERE,
base::Bind(
&OnCrossSiteResponseHelper,
- render_process_host_id_,
- render_view_id_,
+ info->GetChildID(),
+ info->GetRouteID(),
request_id));
// TODO(creis): If the above call should fail, then we need to notify the IO
diff --git a/content/browser/loader/cross_site_resource_handler.h b/content/browser/loader/cross_site_resource_handler.h
index 378a206..39c3a14 100644
--- a/content/browser/loader/cross_site_resource_handler.h
+++ b/content/browser/loader/cross_site_resource_handler.h
@@ -22,8 +22,6 @@ namespace content {
class CrossSiteResourceHandler : public LayeredResourceHandler {
public:
CrossSiteResourceHandler(scoped_ptr<ResourceHandler> next_handler,
- int render_process_host_id,
- int render_view_id,
net::URLRequest* request);
virtual ~CrossSiteResourceHandler();
@@ -55,12 +53,9 @@ class CrossSiteResourceHandler : public LayeredResourceHandler {
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_;
bool completed_during_transition_;
bool did_defer_;
net::URLRequestStatus completed_status_;
diff --git a/content/browser/loader/doomed_resource_handler.cc b/content/browser/loader/doomed_resource_handler.cc
deleted file mode 100644
index d9f2f58..0000000
--- a/content/browser/loader/doomed_resource_handler.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/doomed_resource_handler.h"
-
-#include "base/logging.h"
-#include "net/url_request/url_request_status.h"
-
-namespace content {
-
-DoomedResourceHandler::DoomedResourceHandler(
- scoped_ptr<ResourceHandler> old_handler)
- : old_handler_(old_handler.Pass()) {
-}
-
-DoomedResourceHandler::~DoomedResourceHandler() {
-}
-
-bool DoomedResourceHandler::OnUploadProgress(int request_id,
- uint64 position,
- uint64 size) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnRequestRedirected(int request_id,
- const GURL& new_url,
- ResourceResponse* response,
- bool* defer) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnResponseStarted(int request_id,
- ResourceResponse* response,
- bool* defer) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnWillStart(int request_id,
- const GURL& url,
- bool* defer) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnWillRead(int request_id,
- net::IOBuffer** buf,
- int* buf_size,
- int min_size) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnReadCompleted(int request_id,
- int bytes_read,
- bool* defer) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnResponseCompleted(
- int request_id,
- const net::URLRequestStatus& status,
- const std::string& security_info) {
- DCHECK(status.status() == net::URLRequestStatus::CANCELED ||
- status.status() == net::URLRequestStatus::FAILED);
- return true;
-}
-
-void DoomedResourceHandler::OnDataDownloaded(int request_id,
- int bytes_downloaded) {
- NOTREACHED();
-}
-
-} // namespace content
diff --git a/content/browser/loader/doomed_resource_handler.h b/content/browser/loader/doomed_resource_handler.h
deleted file mode 100644
index 9533ef1c..0000000
--- a/content/browser/loader/doomed_resource_handler.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_DOOMED_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_DOOMED_RESOURCE_HANDLER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/loader/resource_handler.h"
-
-namespace content {
-
-// ResourceHandler that DCHECKs on all events but canceling and failing of
-// requests while activated for a URLRequest.
-class DoomedResourceHandler : public ResourceHandler {
- public:
- // As the DoomedResourceHandler is constructed and substituted from code
- // of another ResourceHandler, we need to make sure that this other handler
- // does not lose its last reference and gets destroyed by being substituted.
- // Therefore, we retain a reference to |old_handler| that prevents the
- // destruction.
- explicit DoomedResourceHandler(scoped_ptr<ResourceHandler> old_handler);
- virtual ~DoomedResourceHandler();
-
- // ResourceHandler implementation:
- virtual bool OnUploadProgress(int request_id,
- uint64 position,
- uint64 size) OVERRIDE;
- virtual bool OnRequestRedirected(int request_id,
- const GURL& new_url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnResponseStarted(int request_id,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillStart(int request_id,
- const GURL& url,
- bool* defer) OVERRIDE;
- virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
- int* buf_size,
- int min_size) OVERRIDE;
- virtual bool OnReadCompleted(int request_id,
- int bytes_read,
- bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
- const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
- virtual void OnDataDownloaded(int request_id,
- int bytes_downloaded) OVERRIDE;
-
- private:
- scoped_ptr<ResourceHandler> old_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(DoomedResourceHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_DOOMED_RESOURCE_HANDLER_H_
diff --git a/content/browser/loader/redirect_to_file_resource_handler.cc b/content/browser/loader/redirect_to_file_resource_handler.cc
index 9d996dc..74dc08a 100644
--- a/content/browser/loader/redirect_to_file_resource_handler.cc
+++ b/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -12,6 +12,7 @@
#include "base/threading/thread_restrictions.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_response.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
@@ -54,13 +55,12 @@ static const int kMaxReadBufSize = 524288;
RedirectToFileResourceHandler::RedirectToFileResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
- int process_id,
+ net::URLRequest* request,
ResourceDispatcherHostImpl* host)
: LayeredResourceHandler(next_handler.Pass()),
weak_factory_(this),
host_(host),
- process_id_(process_id),
- request_id_(-1),
+ request_(request),
buf_(new net::GrowableIOBuffer()),
buf_write_pending_(false),
write_cursor_(0),
@@ -88,7 +88,6 @@ bool RedirectToFileResourceHandler::OnResponseStarted(
bool RedirectToFileResourceHandler::OnWillStart(int request_id,
const GURL& url,
bool* defer) {
- request_id_ = request_id;
if (!deletable_file_.get()) {
// Defer starting the request until we have created the temporary file.
// TODO(darin): This is sub-optimal. We should not delay starting the
@@ -172,17 +171,19 @@ void RedirectToFileResourceHandler::DidCreateTemporaryFile(
new net::FileStream(file_handle.ReleaseValue(),
base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC,
NULL));
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
host_->RegisterDownloadedTempFile(
- process_id_, request_id_, deletable_file_.get());
+ info->GetChildID(), info->GetRequestID(), deletable_file_.get());
ResumeIfDeferred();
}
void RedirectToFileResourceHandler::DidWriteToFile(int result) {
write_callback_pending_ = false;
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
bool failed = false;
if (result > 0) {
- next_handler_->OnDataDownloaded(request_id_, result);
+ next_handler_->OnDataDownloaded(info->GetRequestID(), result);
write_cursor_ += result;
failed = !WriteMore();
} else {
@@ -192,7 +193,8 @@ void RedirectToFileResourceHandler::DidWriteToFile(int result) {
if (failed) {
ResumeIfDeferred();
} else if (completed_during_write_) {
- if (next_handler_->OnResponseCompleted(request_id_, completed_status_,
+ if (next_handler_->OnResponseCompleted(info->GetRequestID(),
+ completed_status_,
completed_security_info_)) {
ResumeIfDeferred();
}
@@ -246,7 +248,8 @@ bool RedirectToFileResourceHandler::WriteMore() {
}
if (rv <= 0)
return false;
- next_handler_->OnDataDownloaded(request_id_, rv);
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ next_handler_->OnDataDownloaded(info->GetRequestID(), rv);
write_cursor_ += rv;
}
}
diff --git a/content/browser/loader/redirect_to_file_resource_handler.h b/content/browser/loader/redirect_to_file_resource_handler.h
index 459b982..1af25df 100644
--- a/content/browser/loader/redirect_to_file_resource_handler.h
+++ b/content/browser/loader/redirect_to_file_resource_handler.h
@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "base/platform_file.h"
#include "content/browser/loader/layered_resource_handler.h"
+#include "net/url_request/url_request.h"
#include "net/url_request/url_request_status.h"
namespace net {
@@ -31,7 +32,7 @@ class RedirectToFileResourceHandler : public LayeredResourceHandler {
public:
RedirectToFileResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
- int process_id,
+ net::URLRequest* request,
ResourceDispatcherHostImpl* resource_dispatcher_host);
virtual ~RedirectToFileResourceHandler();
@@ -65,8 +66,7 @@ class RedirectToFileResourceHandler : public LayeredResourceHandler {
base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_;
ResourceDispatcherHostImpl* host_;
- int process_id_;
- int request_id_;
+ net::URLRequest* request_;
// We allocate a single, fixed-size IO buffer (buf_) used to read from the
// network (buf_write_pending_ is true while the system is copying data into
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 9c29a28..0402e98 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -571,8 +571,7 @@ ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
if (!throttles.empty()) {
handler.reset(
new ThrottlingResourceHandler(
- handler.Pass(), request_info->GetChildID(),
- request_info->GetRequestID(), throttles.Pass()));
+ handler.Pass(), request, throttles.Pass()));
}
}
return handler.Pass();
@@ -878,6 +877,77 @@ void ResourceDispatcherHostImpl::OnSyncLoad(
sync_result->routing_id());
}
+void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
+ int child_id,
+ int route_id,
+ int request_id,
+ const ResourceHostMsg_Request& request_data,
+ const linked_ptr<ResourceLoader>& loader) {
+ ResourceRequestInfoImpl* info = loader->GetRequestInfo();
+ GlobalRoutingID old_routing_id(
+ request_data.transferred_request_child_id, info->GetRouteID());
+ GlobalRequestID old_request_id(request_data.transferred_request_child_id,
+ request_data.transferred_request_request_id);
+ GlobalRoutingID new_routing_id(child_id, route_id);
+ GlobalRequestID new_request_id(child_id, request_id);
+
+ // Clear out data that depends on |info| before updating it.
+ IncrementOutstandingRequestsMemory(-1, *info);
+ OustandingRequestsStats empty_stats = { 0, 0 };
+ OustandingRequestsStats old_stats = GetOutstandingRequestsStats(*info);
+ UpdateOutstandingRequestsStats(*info, empty_stats);
+ pending_loaders_.erase(old_request_id);
+
+ // ResourceHandlers should always get state related to the request from the
+ // ResourceRequestInfo rather than caching it locally. This lets us update
+ // the info object when a transfer occurs.
+ info->UpdateForTransfer(child_id, route_id, request_data.origin_pid,
+ request_id, request_data.frame_id,
+ request_data.parent_frame_id, filter_->GetWeakPtr());
+
+ // Update maps that used the old IDs, if necessary. Some transfers in tests
+ // do not actually use a different ID, so not all maps need to be updated.
+ pending_loaders_[new_request_id] = loader;
+ UpdateOutstandingRequestsStats(*info, old_stats);
+ IncrementOutstandingRequestsMemory(1, *info);
+ if (old_routing_id != new_routing_id) {
+ if (offline_policy_map_.find(old_routing_id) != offline_policy_map_.end()) {
+ offline_policy_map_[new_routing_id] = offline_policy_map_[old_routing_id];
+ offline_policy_map_.erase(old_routing_id);
+ }
+ if (blocked_loaders_map_.find(old_routing_id) !=
+ blocked_loaders_map_.end()) {
+ blocked_loaders_map_[new_routing_id] =
+ blocked_loaders_map_[old_routing_id];
+ blocked_loaders_map_.erase(old_routing_id);
+ }
+ }
+ if (old_request_id != new_request_id) {
+ DelegateMap::iterator it = delegate_map_.find(old_request_id);
+ if (it != delegate_map_.end()) {
+ // Tell each delegate that the request ID has changed.
+ ObserverList<ResourceMessageDelegate>::Iterator del_it(*it->second);
+ ResourceMessageDelegate* delegate;
+ while ((delegate = del_it.GetNext()) != NULL) {
+ delegate->set_request_id(new_request_id);
+ }
+ // Now store the observer list under the new request ID.
+ delegate_map_[new_request_id] = delegate_map_[old_request_id];
+ delegate_map_.erase(old_request_id);
+ }
+ }
+
+ // Notify the delegate to allow it to update state as well.
+ if (delegate_) {
+ delegate_->WillTransferRequestToNewProcess(old_routing_id.child_id,
+ old_routing_id.route_id,
+ old_request_id.request_id,
+ child_id,
+ route_id,
+ request_id);
+ }
+}
+
void ResourceDispatcherHostImpl::BeginRequest(
int request_id,
const ResourceHostMsg_Request& request_data,
@@ -908,16 +978,19 @@ void ResourceDispatcherHostImpl::BeginRequest(
GlobalRequestID(request_data.transferred_request_child_id,
request_data.transferred_request_request_id));
if (it != pending_loaders_.end()) {
+ // If the request is transferring to a new process, we can update our
+ // state and let it resume with its existing ResourceHandlers.
if (it->second->is_transferring()) {
deferred_loader = it->second;
- IncrementOutstandingRequestsMemory(-1,
- *deferred_loader->GetRequestInfo());
- pending_loaders_.erase(it);
+ UpdateRequestForTransfer(child_id, route_id, request_id,
+ request_data, deferred_loader);
+
+ deferred_loader->CompleteTransfer();
} else {
RecordAction(UserMetricsAction("BadMessageTerminate_RDH"));
filter_->BadMessageReceived();
- return;
}
+ return;
}
}
@@ -960,27 +1033,16 @@ void ResourceDispatcherHostImpl::BeginRequest(
// Construct the request.
scoped_ptr<net::URLRequest> new_request;
net::URLRequest* request;
- if (deferred_loader.get()) {
- request = deferred_loader->request();
-
- // Give the ResourceLoader (or any of the ResourceHandlers held by it) a
- // chance to reset some state before we complete the transfer.
- deferred_loader->WillCompleteTransfer();
- } else {
- new_request.reset(request_context->CreateRequest(request_data.url, NULL));
- request = new_request.get();
-
- request->set_method(request_data.method);
- request->set_first_party_for_cookies(request_data.first_party_for_cookies);
- SetReferrerForRequest(request, referrer);
+ new_request.reset(request_context->CreateRequest(request_data.url, NULL));
+ request = new_request.get();
- net::HttpRequestHeaders headers;
- headers.AddHeadersFromString(request_data.headers);
- request->SetExtraRequestHeaders(headers);
- }
+ request->set_method(request_data.method);
+ request->set_first_party_for_cookies(request_data.first_party_for_cookies);
+ SetReferrerForRequest(request, referrer);
- // TODO(darin): Do we really need all of these URLRequest setters in the
- // transferred navigation case?
+ net::HttpRequestHeaders headers;
+ headers.AddHeadersFromString(request_data.headers);
+ request->SetExtraRequestHeaders(headers);
request->set_load_flags(load_flags);
request->SetPriority(request_data.priority);
@@ -1021,6 +1083,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
request_data.has_user_gesture,
request_data.referrer_policy,
resource_context,
+ filter_->GetWeakPtr(),
!is_sync_load);
extra_info->AssociateWithRequest(request); // Request takes ownership.
@@ -1041,17 +1104,15 @@ void ResourceDispatcherHostImpl::BeginRequest(
// Construct the IPC resource handler.
scoped_ptr<ResourceHandler> handler;
if (sync_result) {
- handler.reset(new SyncResourceHandler(
- filter_, resource_context, request, sync_result, this));
+ handler.reset(new SyncResourceHandler(request, sync_result, this));
} else {
- handler.reset(new AsyncResourceHandler(
- filter_, resource_context, request, this));
+ handler.reset(new AsyncResourceHandler(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));
+ new RedirectToFileResourceHandler(handler.Pass(), request, this));
}
// Install a CrossSiteResourceHandler if this request is coming from a
@@ -1064,8 +1125,7 @@ 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(), request));
}
// Insert a buffered event handler before the actual one.
@@ -1074,16 +1134,12 @@ void ResourceDispatcherHostImpl::BeginRequest(
ScopedVector<ResourceThrottle> throttles;
if (delegate_) {
- bool is_continuation_of_transferred_request =
- (deferred_loader.get() != NULL);
-
delegate_->RequestBeginning(request,
resource_context,
filter_->appcache_service(),
request_data.resource_type,
child_id,
route_id,
- is_continuation_of_transferred_request,
&throttles);
}
@@ -1102,16 +1158,9 @@ void ResourceDispatcherHostImpl::BeginRequest(
scheduler_->ScheduleRequest(child_id, route_id, request).release());
handler.reset(
- new ThrottlingResourceHandler(handler.Pass(), child_id, request_id,
- throttles.Pass()));
+ new ThrottlingResourceHandler(handler.Pass(), request, throttles.Pass()));
- if (deferred_loader.get()) {
- pending_loaders_[extra_info->GetGlobalRequestID()] = deferred_loader;
- IncrementOutstandingRequestsMemory(1, *extra_info);
- deferred_loader->CompleteTransfer(handler.Pass());
- } else {
- BeginRequestInternal(new_request.Pass(), handler.Pass());
- }
+ BeginRequestInternal(new_request.Pass(), handler.Pass());
}
void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) {
@@ -1192,6 +1241,7 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
false, // has_user_gesture
WebKit::WebReferrerPolicyDefault,
context,
+ base::WeakPtr<ResourceMessageFilter>(), // filter
true); // is_async
}
@@ -1297,6 +1347,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
// iterators found in the first loop.
// Find the global ID of all matching elements.
+ bool any_requests_transferring = false;
std::vector<GlobalRequestID> matching_requests;
for (LoaderMap::const_iterator i = pending_loaders_.begin();
i != pending_loaders_.end(); ++i) {
@@ -1310,6 +1361,8 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
// Don't cancel navigations that are transferring to another process,
// since they belong to another process now.
+ if (IsTransferredNavigation(id))
+ any_requests_transferring = true;
if (!info->is_download() && !info->is_stream() &&
!IsTransferredNavigation(id) &&
(route_id == -1 || route_id == info->GetRouteID())) {
@@ -1333,6 +1386,14 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
RemovePendingLoader(iter);
}
+ // Don't clear the blocked loaders or offline policy maps if any of the
+ // requests in route_id are being transferred to a new process, since those
+ // maps will be updated with the new route_id after the transfer. Otherwise
+ // we will lose track of this info when the old route goes away, before the
+ // new one is created.
+ if (any_requests_transferring)
+ return;
+
// Now deal with blocked requests if any.
if (route_id != -1) {
if (blocked_loaders_map_.find(GlobalRoutingID(child_id, route_id)) !=
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h
index e6f2241..f10b3f7 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -356,6 +356,15 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void OnSyncLoad(int request_id,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result);
+
+ // Update the ResourceRequestInfo and internal maps when a request is
+ // transferred from one process to another.
+ void UpdateRequestForTransfer(int child_id,
+ int route_id,
+ int request_id,
+ const ResourceHostMsg_Request& request_data,
+ const linked_ptr<ResourceLoader>& loader);
+
void BeginRequest(int request_id,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result, // only valid for sync
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 89b17c4..449b515 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -15,6 +15,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/worker_host/worker_service_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/resource_messages.h"
@@ -22,6 +23,7 @@
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/process_type.h"
#include "content/public/common/resource_response.h"
@@ -489,7 +491,6 @@ class TestResourceDispatcherHostDelegate
ResourceType::Type resource_type,
int child_id,
int route_id,
- bool is_continuation_of_transferred_request,
ScopedVector<ResourceThrottle>* throttles) OVERRIDE {
if (user_data_) {
const void* key = user_data_.get();
@@ -1758,6 +1759,93 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
CheckSuccessfulRequest(msgs[0], kResponseBody);
}
+TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
+ EXPECT_EQ(0, host_.pending_requests());
+
+ int render_view_id = 0;
+ int request_id = 1;
+ int first_child_id = -1;
+
+ // Configure initial request.
+ SetResponse("HTTP/1.1 302 Found\n"
+ "Location: http://other.com/blech\n\n");
+
+ SetResourceType(ResourceType::MAIN_FRAME);
+ HandleScheme("http");
+
+ // Temporarily replace ContentBrowserClient with one that will trigger the
+ // transfer navigation code paths.
+ TransfersAllNavigationsContentBrowserClient new_client;
+ ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+
+ // Create a first filter that can be deleted before the second one starts.
+ {
+ scoped_refptr<ForwardingFilter> first_filter = new ForwardingFilter(
+ this, browser_context_->GetResourceContext());
+ first_child_id = first_filter->child_id();
+
+ ResourceHostMsg_Request first_request =
+ CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ GURL("http://example.com/blah"));
+
+ // For cleanup.
+ child_ids_.insert(first_child_id);
+ ResourceHostMsg_RequestResource first_request_msg(
+ render_view_id, request_id, first_request);
+ bool msg_was_ok;
+ host_.OnMessageReceived(
+ first_request_msg, first_filter.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+ }
+ // The first filter is now deleted, as if the child process died.
+
+ // Restore.
+ SetBrowserClientForTesting(old_client);
+
+ // Make sure we don't hold onto the ResourceMessageFilter after it is deleted.
+ GlobalRequestID first_global_request_id(first_child_id, request_id);
+ const ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(first_global_request_id));
+ EXPECT_FALSE(info->filter());
+
+ // This second filter is used to emulate a second process.
+ scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(
+ this, browser_context_->GetResourceContext());
+
+ int new_render_view_id = 1;
+ int new_request_id = 2;
+
+ const std::string kResponseBody = "hello world";
+ SetResponse("HTTP/1.1 200 OK\n"
+ "Content-Type: text/plain\n\n",
+ kResponseBody);
+
+ ResourceHostMsg_Request request =
+ CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ GURL("http://other.com/blech"));
+ request.transferred_request_child_id = first_child_id;
+ request.transferred_request_request_id = request_id;
+
+ // For cleanup.
+ child_ids_.insert(second_filter->child_id());
+ ResourceHostMsg_RequestResource transfer_request_msg(
+ new_render_view_id, new_request_id, request);
+ bool msg_was_ok;
+ host_.OnMessageReceived(
+ transfer_request_msg, second_filter.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ // Check generated messages.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ ASSERT_EQ(1U, msgs.size());
+ CheckSuccessfulRequest(msgs[0], kResponseBody);
+}
+
TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
EXPECT_EQ(0, host_.pending_requests());
@@ -1824,6 +1912,15 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+ // Verify that we update the ResourceRequestInfo.
+ GlobalRequestID global_request_id(second_filter->child_id(), new_request_id);
+ const ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(global_request_id));
+ EXPECT_EQ(second_filter->child_id(), info->GetChildID());
+ EXPECT_EQ(new_render_view_id, info->GetRouteID());
+ EXPECT_EQ(new_request_id, info->GetRequestID());
+ EXPECT_EQ(second_filter, info->filter());
+
// Now, simulate the renderer choosing to follow the redirect.
ResourceHostMsg_FollowRedirect redirect_msg(
new_request_id, false, GURL());
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc
index 5b0a9f4..c99fe5b 100644
--- a/content/browser/loader/resource_loader.cc
+++ b/content/browser/loader/resource_loader.cc
@@ -9,7 +9,6 @@
#include "base/metrics/histogram.h"
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/loader/doomed_resource_handler.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
@@ -163,29 +162,12 @@ void ResourceLoader::MarkAsTransferring(const GURL& target_url) {
// When transferring a request to another process, the renderer doesn't get
// a chance to update the cookie policy URL. Do it here instead.
request()->set_first_party_for_cookies(target_url);
-
- // When an URLRequest is transferred to a new RenderViewHost, its
- // ResourceHandler should not receive any notifications because it may depend
- // on the state of the old RVH. We set a ResourceHandler that only allows
- // canceling requests, because on shutdown of the RDH all pending requests
- // are canceled. The RVH of requests that are being transferred may be gone
- // by that time. In CompleteTransfer, the ResoureHandlers are substituted
- // again.
- handler_.reset(new DoomedResourceHandler(handler_.Pass()));
-}
-
-void ResourceLoader::WillCompleteTransfer() {
- handler_.reset();
}
-void ResourceLoader::CompleteTransfer(scoped_ptr<ResourceHandler> new_handler) {
+void ResourceLoader::CompleteTransfer() {
DCHECK_EQ(DEFERRED_REDIRECT, deferred_stage_);
- DCHECK(!handler_.get());
- handler_ = new_handler.Pass();
- handler_->SetController(this);
is_transferring_ = false;
-
Resume();
}
diff --git a/content/browser/loader/resource_loader.h b/content/browser/loader/resource_loader.h
index 76f72e2..6a611a7 100644
--- a/content/browser/loader/resource_loader.h
+++ b/content/browser/loader/resource_loader.h
@@ -43,8 +43,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
bool is_transferring() const { return is_transferring_; }
void MarkAsTransferring(const GURL& target_url);
- void WillCompleteTransfer();
- void CompleteTransfer(scoped_ptr<ResourceHandler> new_handler);
+ void CompleteTransfer();
net::URLRequest* request() { return request_.get(); }
ResourceRequestInfoImpl* GetRequestInfo();
diff --git a/content/browser/loader/resource_message_delegate.h b/content/browser/loader/resource_message_delegate.h
index d5716e3..f447808 100644
--- a/content/browser/loader/resource_message_delegate.h
+++ b/content/browser/loader/resource_message_delegate.h
@@ -32,6 +32,10 @@ class CONTENT_EXPORT ResourceMessageDelegate {
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) = 0;
+ void set_request_id(const GlobalRequestID& new_request_id) {
+ id_ = new_request_id;
+ }
+
private:
GlobalRequestID id_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceMessageDelegate);
diff --git a/content/browser/loader/resource_message_filter.cc b/content/browser/loader/resource_message_filter.cc
index 26ba80f..c55f2d1 100644
--- a/content/browser/loader/resource_message_filter.cc
+++ b/content/browser/loader/resource_message_filter.cc
@@ -24,7 +24,8 @@ ResourceMessageFilter::ResourceMessageFilter(
appcache_service_(appcache_service),
blob_storage_context_(blob_storage_context),
file_system_context_(file_system_context),
- get_contexts_callback_(get_contexts_callback) {
+ get_contexts_callback_(get_contexts_callback),
+ weak_ptr_factory_(this) {
}
ResourceMessageFilter::~ResourceMessageFilter() {
@@ -51,4 +52,8 @@ void ResourceMessageFilter::GetContexts(
return get_contexts_callback_.Run(request, resource_context, request_context);
}
+base::WeakPtr<ResourceMessageFilter> ResourceMessageFilter::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
} // namespace content
diff --git a/content/browser/loader/resource_message_filter.h b/content/browser/loader/resource_message_filter.h
index 925e452..a2fb2e3 100644
--- a/content/browser/loader/resource_message_filter.h
+++ b/content/browser/loader/resource_message_filter.h
@@ -7,6 +7,7 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "webkit/common/resource_type.h"
@@ -76,6 +77,8 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
int child_id() const { return child_id_; }
int process_type() const { return process_type_; }
+ base::WeakPtr<ResourceMessageFilter> GetWeakPtr();
+
protected:
// Protected destructor so that we can be overriden in tests.
virtual ~ResourceMessageFilter();
@@ -92,6 +95,9 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
GetContextsCallback get_contexts_callback_;
+ // This must come last to make sure weak pointers are invalidated first.
+ base::WeakPtrFactory<ResourceMessageFilter> weak_ptr_factory_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceMessageFilter);
};
diff --git a/content/browser/loader/resource_request_info_impl.cc b/content/browser/loader/resource_request_info_impl.cc
index c41fe39..04d4f2a 100644
--- a/content/browser/loader/resource_request_info_impl.cc
+++ b/content/browser/loader/resource_request_info_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/global_routing_id.h"
+#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/worker_host/worker_service_impl.h"
#include "content/common/net/url_request_user_data.h"
#include "content/public/browser/global_request_id.h"
@@ -47,6 +48,7 @@ void ResourceRequestInfo::AllocateForTesting(
false, // has_user_gesture
WebKit::WebReferrerPolicyDefault, // referrer_policy
context, // context
+ base::WeakPtr<ResourceMessageFilter>(), // filter
false); // is_async
info->AssociateWithRequest(request);
}
@@ -98,6 +100,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
bool has_user_gesture,
WebKit::WebReferrerPolicy referrer_policy,
ResourceContext* context,
+ base::WeakPtr<ResourceMessageFilter> filter,
bool is_async)
: cross_site_handler_(NULL),
process_type_(process_type),
@@ -119,6 +122,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
memory_cost_(0),
referrer_policy_(referrer_policy),
context_(context),
+ filter_(filter),
is_async_(is_async) {
}
@@ -228,4 +232,20 @@ GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
return GlobalRoutingID(child_id_, route_id_);
}
+void ResourceRequestInfoImpl::UpdateForTransfer(
+ int child_id,
+ int route_id,
+ int origin_pid,
+ int request_id,
+ int64 frame_id,
+ int64 parent_frame_id,
+ base::WeakPtr<ResourceMessageFilter> filter) {
+ child_id_ = child_id;
+ route_id_ = route_id;
+ origin_pid_ = origin_pid;
+ request_id_ = request_id;
+ frame_id_ = frame_id;
+ filter_ = filter;
+}
+
} // namespace content
diff --git a/content/browser/loader/resource_request_info_impl.h b/content/browser/loader/resource_request_info_impl.h
index e615116..6947315a 100644
--- a/content/browser/loader/resource_request_info_impl.h
+++ b/content/browser/loader/resource_request_info_impl.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/referrer.h"
@@ -19,6 +20,7 @@
namespace content {
class CrossSiteResourceHandler;
class ResourceContext;
+class ResourceMessageFilter;
struct GlobalRequestID;
struct GlobalRoutingID;
@@ -53,6 +55,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool has_user_gesture,
WebKit::WebReferrerPolicy referrer_policy,
ResourceContext* context,
+ base::WeakPtr<ResourceMessageFilter> filter,
bool is_async);
virtual ~ResourceRequestInfoImpl();
@@ -81,6 +84,23 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
CONTENT_EXPORT GlobalRequestID GetGlobalRequestID() const;
GlobalRoutingID GetGlobalRoutingID() const;
+ // May be NULL (e.g., if process dies during a transfer).
+ ResourceMessageFilter* filter() const {
+ return filter_.get();
+ }
+
+ // Updates the data associated with this request after it is is transferred
+ // to a new renderer process. Not all data will change during a transfer.
+ // We do not expect the ResourceContext to change during navigation, so that
+ // does not need to be updated.
+ void UpdateForTransfer(int child_id,
+ int route_id,
+ int origin_pid,
+ int request_id,
+ int64 frame_id,
+ int64 parent_frame_id,
+ base::WeakPtr<ResourceMessageFilter> filter);
+
// CrossSiteResourceHandler for this request. May be null.
CrossSiteResourceHandler* cross_site_handler() {
return cross_site_handler_;
@@ -135,6 +155,9 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int memory_cost_;
WebKit::WebReferrerPolicy referrer_policy_;
ResourceContext* context_;
+ // The filter might be deleted without deleting this object if the process
+ // exits during a transfer.
+ base::WeakPtr<ResourceMessageFilter> filter_;
bool is_async_;
DISALLOW_COPY_AND_ASSIGN(ResourceRequestInfoImpl);
diff --git a/content/browser/loader/resource_scheduler_unittest.cc b/content/browser/loader/resource_scheduler_unittest.cc
index 2c4c110..6a0bd28 100644
--- a/content/browser/loader/resource_scheduler_unittest.cc
+++ b/content/browser/loader/resource_scheduler_unittest.cc
@@ -159,6 +159,7 @@ class ResourceSchedulerTest : public testing::Test {
false, // has_user_gesture
WebKit::WebReferrerPolicyDefault, // referrer_policy
NULL, // context
+ base::WeakPtr<ResourceMessageFilter>(), // filter
true); // is_async
info->AssociateWithRequest(url_request.get());
return url_request.Pass();
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc
index b1a7162..1608fc4 100644
--- a/content/browser/loader/sync_resource_handler.cc
+++ b/content/browser/loader/sync_resource_handler.cc
@@ -8,23 +8,21 @@
#include "content/browser/devtools/devtools_netlog_observer.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader/resource_request_info_impl.h"
#include "content/common/resource_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 "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
namespace content {
SyncResourceHandler::SyncResourceHandler(
- ResourceMessageFilter* filter,
- ResourceContext* resource_context,
net::URLRequest* request,
IPC::Message* result_message,
ResourceDispatcherHostImpl* resource_dispatcher_host)
: read_buffer_(new net::IOBuffer(kReadBufSize)),
- filter_(filter),
- resource_context_(resource_context),
request_(request),
result_message_(result_message),
rdh_(resource_dispatcher_host) {
@@ -34,7 +32,12 @@ SyncResourceHandler::SyncResourceHandler(
SyncResourceHandler::~SyncResourceHandler() {
if (result_message_) {
result_message_->set_reply_error();
- filter_->Send(result_message_);
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ // If the filter doesn't exist at this point, the process has died and isn't
+ // waiting for the result message anymore.
+ if (info->filter())
+ info->filter()->Send(result_message_);
}
}
@@ -50,8 +53,10 @@ bool SyncResourceHandler::OnRequestRedirected(
ResourceResponse* response,
bool* defer) {
if (rdh_->delegate()) {
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
rdh_->delegate()->OnRequestRedirected(
- new_url, request_, resource_context_, response);
+ new_url, request_, info->GetContext(), response);
}
DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
@@ -70,9 +75,14 @@ bool SyncResourceHandler::OnResponseStarted(
int request_id,
ResourceResponse* response,
bool* defer) {
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ if (!info->filter())
+ return false;
+
if (rdh_->delegate()) {
rdh_->delegate()->OnResponseStarted(
- request_, resource_context_, response, filter_.get());
+ request_, info->GetContext(), response, info->filter());
}
DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
@@ -115,13 +125,18 @@ bool SyncResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
const std::string& security_info) {
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ if (!info->filter())
+ return false;
+
result_.error_code = status.error();
result_.encoded_data_length =
DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_);
- filter_->Send(result_message_);
+ info->filter()->Send(result_message_);
result_message_ = NULL;
return true;
}
diff --git a/content/browser/loader/sync_resource_handler.h b/content/browser/loader/sync_resource_handler.h
index 838a05a..358d92a 100644
--- a/content/browser/loader/sync_resource_handler.h
+++ b/content/browser/loader/sync_resource_handler.h
@@ -28,9 +28,7 @@ class ResourceMessageFilter;
// events from the resource dispatcher host.
class SyncResourceHandler : public ResourceHandler {
public:
- SyncResourceHandler(ResourceMessageFilter* filter,
- ResourceContext* resource_context,
- net::URLRequest* request,
+ SyncResourceHandler(net::URLRequest* request,
IPC::Message* result_message,
ResourceDispatcherHostImpl* resource_dispatcher_host);
virtual ~SyncResourceHandler();
@@ -66,8 +64,6 @@ class SyncResourceHandler : public ResourceHandler {
scoped_refptr<net::IOBuffer> read_buffer_;
SyncLoadResult result_;
- scoped_refptr<ResourceMessageFilter> filter_;
- ResourceContext* resource_context_;
net::URLRequest* request_;
IPC::Message* result_message_;
ResourceDispatcherHostImpl* rdh_;
diff --git a/content/browser/loader/throttling_resource_handler.cc b/content/browser/loader/throttling_resource_handler.cc
index 5725e03..8bb5446 100644
--- a/content/browser/loader/throttling_resource_handler.cc
+++ b/content/browser/loader/throttling_resource_handler.cc
@@ -4,6 +4,7 @@
#include "content/browser/loader/throttling_resource_handler.h"
+#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/resource_response.h"
@@ -11,12 +12,11 @@ namespace content {
ThrottlingResourceHandler::ThrottlingResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
- int child_id,
- int request_id,
+ net::URLRequest* request,
ScopedVector<ResourceThrottle> throttles)
: LayeredResourceHandler(next_handler.Pass()),
deferred_stage_(DEFERRED_NONE),
- request_id_(request_id),
+ request_(request),
throttles_(throttles.Pass()),
index_(0),
cancelled_by_resource_throttle_(false) {
@@ -31,7 +31,6 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id,
const GURL& new_url,
ResourceResponse* response,
bool* defer) {
- DCHECK_EQ(request_id_, request_id);
DCHECK(!cancelled_by_resource_throttle_);
*defer = false;
@@ -57,7 +56,6 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id,
bool ThrottlingResourceHandler::OnWillStart(int request_id,
const GURL& url,
bool* defer) {
- DCHECK_EQ(request_id_, request_id);
DCHECK(!cancelled_by_resource_throttle_);
*defer = false;
@@ -81,7 +79,6 @@ bool ThrottlingResourceHandler::OnWillStart(int request_id,
bool ThrottlingResourceHandler::OnResponseStarted(int request_id,
ResourceResponse* response,
bool* defer) {
- DCHECK_EQ(request_id_, request_id);
DCHECK(!cancelled_by_resource_throttle_);
while (index_ < throttles_.size()) {
@@ -144,7 +141,8 @@ void ThrottlingResourceHandler::ResumeStart() {
deferred_url_ = GURL();
bool defer = false;
- if (!OnWillStart(request_id_, url, &defer)) {
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ if (!OnWillStart(info->GetRequestID(), url, &defer)) {
controller()->Cancel();
} else if (!defer) {
controller()->Resume();
@@ -160,7 +158,9 @@ void ThrottlingResourceHandler::ResumeRedirect() {
deferred_response_.swap(response);
bool defer = false;
- if (!OnRequestRedirected(request_id_, new_url, response.get(), &defer)) {
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ if (!OnRequestRedirected(info->GetRequestID(), new_url, response.get(),
+ &defer)) {
controller()->Cancel();
} else if (!defer) {
controller()->Resume();
@@ -174,7 +174,8 @@ void ThrottlingResourceHandler::ResumeResponse() {
deferred_response_.swap(response);
bool defer = false;
- if (!OnResponseStarted(request_id_, response.get(), &defer)) {
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ if (!OnResponseStarted(info->GetRequestID(), response.get(), &defer)) {
controller()->Cancel();
} else if (!defer) {
controller()->Resume();
diff --git a/content/browser/loader/throttling_resource_handler.h b/content/browser/loader/throttling_resource_handler.h
index 2661cdd..168dc56 100644
--- a/content/browser/loader/throttling_resource_handler.h
+++ b/content/browser/loader/throttling_resource_handler.h
@@ -11,6 +11,10 @@
#include "content/public/browser/resource_controller.h"
#include "url/gurl.h"
+namespace net {
+class URLRequest;
+}
+
namespace content {
class ResourceThrottle;
@@ -22,8 +26,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
public:
// Takes ownership of the ResourceThrottle instances.
ThrottlingResourceHandler(scoped_ptr<ResourceHandler> next_handler,
- int child_id,
- int request_id,
+ net::URLRequest* request,
ScopedVector<ResourceThrottle> throttles);
virtual ~ThrottlingResourceHandler();
@@ -56,7 +59,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
};
DeferredStage deferred_stage_;
- int request_id_;
+ net::URLRequest* request_;
ScopedVector<ResourceThrottle> throttles_;
size_t index_;