Index: content/browser/renderer_host/resource_dispatcher_host.cc |
diff --git a/content/browser/renderer_host/resource_dispatcher_host.cc b/content/browser/renderer_host/resource_dispatcher_host.cc |
index fb0f1c33e0108169ae32d8423f1e4cc823466d0b..69010ba08140a2fa8f16761e2be337ad9647998e 100644 |
--- a/content/browser/renderer_host/resource_dispatcher_host.cc |
+++ b/content/browser/renderer_host/resource_dispatcher_host.cc |
@@ -312,7 +312,12 @@ ResourceDispatcherHost::ResourceDispatcherHost( |
ResourceDispatcherHost::~ResourceDispatcherHost() { |
AsyncResourceHandler::GlobalCleanup(); |
+ for (PendingRequestList::const_iterator i = pending_requests_.begin(); |
+ i != pending_requests_.end(); ++i) { |
+ transferred_navigations_.erase(i->first); |
+ } |
STLDeleteValues(&pending_requests_); |
+ DCHECK(transferred_navigations_.empty()); |
} |
void ResourceDispatcherHost::Initialize() { |
@@ -340,6 +345,10 @@ void ResourceDispatcherHost::OnShutdown() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
is_shutdown_ = true; |
resource_queue_.Shutdown(); |
+ for (PendingRequestList::const_iterator i = pending_requests_.begin(); |
+ i != pending_requests_.end(); ++i) { |
+ transferred_navigations_.erase(i->first); |
+ } |
STLDeleteValues(&pending_requests_); |
// Make sure we shutdown the timer now, otherwise by the time our destructor |
// runs if the timer is still running the Task is deleted twice (once by |
@@ -457,6 +466,31 @@ void ResourceDispatcherHost::BeginRequest( |
base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf)); |
base::debug::Alias(url_buf); |
+ // TODO(mpcomplete): Step 3. (See steps 1-2 below). |
Charlie Reis
2011/12/02 22:38:11
This comment needs updating and should probably ha
Matt Perry
2011/12/03 00:14:24
Done.
|
+ // If the request that's coming in is a cross-process transferring, then we |
+ // want to reuse and resume the old request rather than start a new one. |
+ // I'm not entirely sure how much of the BeginRequest code should run. We |
+ // definitely want to create new ResourceHandlers and ExtraInfo, since those |
+ // are tied to the process. |
+ // Also, I'm not clear what should happen if any of the early returns are hit |
+ // before we actually resume the request via FollowDeferredRedirect. I think |
+ // we're then left with an orphaned request that will never be deleted. We |
+ // probably want to cancel it in those cases. |
+ // It's probably best to split apart BeginRequest into 2 methods, 1 for |
+ // regular requests and one for transferred ones - probably with some shared |
+ // code, but not all. |
+ net::URLRequest* deferred_request = NULL; |
+ |
+ GlobalRequestID old_request_id(request_data.transferred_request_child_id, |
+ request_data.transferred_request_request_id); |
+ TransferredNavigations::iterator iter = |
+ transferred_navigations_.find(old_request_id); |
+ if (iter != transferred_navigations_.end()) { |
+ deferred_request = iter->second; |
+ pending_requests_.erase(old_request_id); |
+ transferred_navigations_.erase(iter); |
+ } |
+ |
const content::ResourceContext& resource_context = |
filter_->resource_context(); |
@@ -508,13 +542,18 @@ void ResourceDispatcherHost::BeginRequest( |
} |
// Construct the request. |
- net::URLRequest* request = new net::URLRequest(request_data.url, this); |
- request->set_method(request_data.method); |
- request->set_first_party_for_cookies(request_data.first_party_for_cookies); |
- request->set_referrer(referrer.spec()); |
- net::HttpRequestHeaders headers; |
- headers.AddHeadersFromString(request_data.headers); |
- request->SetExtraRequestHeaders(headers); |
+ net::URLRequest* request; |
+ if (deferred_request) { |
+ request = deferred_request; |
+ } else { |
+ request = new net::URLRequest(request_data.url, this); |
+ request->set_method(request_data.method); |
+ request->set_first_party_for_cookies(request_data.first_party_for_cookies); |
+ request->set_referrer(referrer.spec()); |
+ net::HttpRequestHeaders headers; |
+ headers.AddHeadersFromString(request_data.headers); |
+ request->SetExtraRequestHeaders(headers); |
+ } |
int load_flags = request_data.load_flags; |
// Although EV status is irrelevant to sub-frames and sub-resources, we have |
@@ -543,15 +582,16 @@ void ResourceDispatcherHost::BeginRequest( |
net::LOAD_DO_NOT_SAVE_COOKIES); |
} |
- // Raw headers are sensitive, as they inclide Cookie/Set-Cookie, so only |
- // allow requesting them if requestor has ReadRawCookies permission. |
+ // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only |
+ // allow requesting them if requester has ReadRawCookies permission. |
if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) |
&& !policy->CanReadRawCookies(child_id)) { |
- VLOG(1) << "Denied unathorized request for raw headers"; |
+ VLOG(1) << "Denied unauthorized request for raw headers"; |
load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; |
} |
request->set_load_flags(load_flags); |
+ |
request->set_context( |
filter_->GetURLRequestContext(request_data.resource_type)); |
request->set_priority(DetermineRequestPriority(request_data.resource_type)); |
@@ -584,8 +624,11 @@ void ResourceDispatcherHost::BeginRequest( |
if (delegate_) { |
bool sub = request_data.resource_type != ResourceType::MAIN_FRAME; |
- handler = delegate_->RequestBeginning(handler, request, resource_context, |
- sub, child_id, route_id); |
+ bool is_continuation_of_transferred_request = |
+ (deferred_request != NULL); |
+ handler = delegate_->RequestBeginning( |
+ handler, request, resource_context, sub, child_id, route_id, |
+ is_continuation_of_transferred_request); |
} |
// Make extra info and read footer (contains request ID). |
@@ -624,7 +667,13 @@ void ResourceDispatcherHost::BeginRequest( |
request, resource_context.appcache_service(), child_id, |
request_data.appcache_host_id, request_data.resource_type); |
- BeginRequestInternal(request); |
+ if (deferred_request) { |
+ GlobalRequestID global_id(extra_info->child_id(), extra_info->request_id()); |
+ pending_requests_[global_id] = request; |
+ request->FollowDeferredRedirect(); |
+ } else { |
+ BeginRequestInternal(request); |
+ } |
} |
void ResourceDispatcherHost::OnReleaseDownloadedFile(int request_id) { |
@@ -1186,6 +1235,13 @@ void ResourceDispatcherHost::RemovePendingRequest( |
const PendingRequestList::iterator& iter) { |
ResourceDispatcherHostRequestInfo* info = InfoForRequest(iter->second); |
+ // This is called via CancelRequestsForRoute to remove all requests for a |
+ // closing tab. We don't want to remove requests that are being transferred |
+ // to a new tab. |
Charlie Reis
2011/12/02 22:38:11
When would a request be transferred from one tab t
Matt Perry
2011/12/03 00:14:24
I moved this block to a more isolated location, an
|
+ GlobalRequestID id(info->child_id(), info->request_id()); |
+ if (transferred_navigations_.find(id) != transferred_navigations_.end()) |
+ return; |
+ |
// Remove the memory credit that we added when pushing the request onto |
// the pending list. |
IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), |
@@ -1418,8 +1474,15 @@ bool ResourceDispatcherHost::CompleteResponseStarted(net::URLRequest* request) { |
void ResourceDispatcherHost::CancelRequest(int child_id, |
int request_id, |
bool from_renderer) { |
- PendingRequestList::iterator i = pending_requests_.find( |
- GlobalRequestID(child_id, request_id)); |
+ GlobalRequestID id(child_id, request_id); |
+ if (from_renderer) { |
+ // When the old renderer dies, it sends a message to us to cancel its |
+ // requests. |
+ if (transferred_navigations_.find(id) != transferred_navigations_.end()) |
+ return; |
+ } |
+ |
+ PendingRequestList::iterator i = pending_requests_.find(id); |
if (i == pending_requests_.end()) { |
// We probably want to remove this warning eventually, but I wanted to be |
// able to notice when this happens during initial development since it |
@@ -1481,7 +1544,7 @@ int ResourceDispatcherHost::IncrementOutstandingRequestsMemoryCost( |
new_cost += cost; |
CHECK(new_cost >= 0); |
if (new_cost == 0) |
- outstanding_requests_memory_cost_map_.erase(prev_entry); |
+ outstanding_requests_memory_cost_map_.erase(child_id); |
else |
outstanding_requests_memory_cost_map_[child_id] = new_cost; |
@@ -2179,3 +2242,9 @@ bool ResourceDispatcherHost::allow_cross_origin_auth_prompt() { |
void ResourceDispatcherHost::set_allow_cross_origin_auth_prompt(bool value) { |
allow_cross_origin_auth_prompt_ = value; |
} |
+ |
+void ResourceDispatcherHost::MarkAsTransferredNavigation( |
+ const GlobalRequestID& transferred_request_id, |
+ net::URLRequest* ransferred_request) { |
+ transferred_navigations_[transferred_request_id] = ransferred_request; |
+} |