Chromium Code Reviews| 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; |
| +} |