Index: chrome/browser/renderer_host/resource_dispatcher_host.cc |
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc |
index 899f0777bdd7abc9a0f9d4b5ad2eed3725f9c97f..54e5e48111f55ce3eb9115cecd10a59fce491599 100644 |
--- a/chrome/browser/renderer_host/resource_dispatcher_host.cc |
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc |
@@ -10,6 +10,8 @@ |
#include "base/logging.h" |
#include "base/command_line.h" |
+#include "base/file_util.h" |
+#include "base/format_macros.h" |
#include "base/histogram.h" |
#include "base/message_loop.h" |
#include "base/scoped_ptr.h" |
@@ -23,9 +25,11 @@ |
#include "chrome/browser/download/download_file_manager.h" |
#include "chrome/browser/download/download_manager.h" |
#include "chrome/browser/download/download_request_limiter.h" |
+#include "chrome/browser/download/download_util.h" |
#include "chrome/browser/download/save_file_manager.h" |
#include "chrome/browser/extensions/user_script_listener.h" |
#include "chrome/browser/external_protocol_handler.h" |
+#include "chrome/browser/history/download_create_info.h" |
#include "chrome/browser/in_process_webkit/webkit_thread.h" |
#include "chrome/browser/login_prompt.h" |
#include "chrome/browser/net/chrome_url_request_context.h" |
@@ -127,7 +131,7 @@ const int kMaxOutstandingRequestsCostPerProcess = 26214400; |
// disallowed if the renderer is not authorized to retrieve the request URL or |
// if the renderer is attempting to upload an unauthorized file. |
bool ShouldServiceRequest(ChildProcessInfo::ProcessType process_type, |
- int child_id, |
+ int process_unique_id, |
const ViewHostMsg_Resource_Request& request_data) { |
if (process_type == ChildProcessInfo::PLUGIN_PROCESS) |
return true; |
@@ -140,7 +144,7 @@ bool ShouldServiceRequest(ChildProcessInfo::ProcessType process_type, |
ChildProcessSecurityPolicy::GetInstance(); |
// Check if the renderer is permitted to request the requested URL. |
- if (!policy->CanRequestURL(child_id, request_data.url)) { |
+ if (!policy->CanRequestURL(process_unique_id, request_data.url)) { |
LOG(INFO) << "Denied unauthorized request for " << |
request_data.url.possibly_invalid_spec(); |
return false; |
@@ -153,7 +157,7 @@ bool ShouldServiceRequest(ChildProcessInfo::ProcessType process_type, |
std::vector<net::UploadData::Element>::const_iterator iter; |
for (iter = uploads->begin(); iter != uploads->end(); ++iter) { |
if (iter->type() == net::UploadData::TYPE_FILE && |
- !policy->CanUploadFile(child_id, iter->file_path())) { |
+ !policy->CanUploadFile(process_unique_id, iter->file_path())) { |
NOTREACHED() << "Denied unauthorized upload of " |
<< iter->file_path().value(); |
return false; |
@@ -234,6 +238,7 @@ ResourceDispatcherHost::ResourceDispatcherHost() |
ResourceDispatcherHost::~ResourceDispatcherHost() { |
AsyncResourceHandler::GlobalCleanup(); |
STLDeleteValues(&pending_requests_); |
+ STLDeleteValues(&interrupted_requests_); |
user_script_listener_->ShutdownMainThread(); |
} |
@@ -243,7 +248,8 @@ void ResourceDispatcherHost::Initialize() { |
webkit_thread_->Initialize(); |
safe_browsing_->Initialize(); |
ChromeThread::PostTask( |
- ChromeThread::IO, FROM_HERE, |
+ ChromeThread::IO, |
+ FROM_HERE, |
NewRunnableFunction(&appcache::AppCacheInterceptor::EnsureRegistered)); |
} |
@@ -263,6 +269,7 @@ void ResourceDispatcherHost::OnShutdown() { |
is_shutdown_ = true; |
resource_queue_.Shutdown(); |
STLDeleteValues(&pending_requests_); |
+ STLDeleteValues(&interrupted_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 |
// the MessageLoop and the second time by RepeatingTimer). |
@@ -287,7 +294,7 @@ void ResourceDispatcherHost::OnShutdown() { |
} |
bool ResourceDispatcherHost::HandleExternalProtocol(int request_id, |
- int child_id, |
+ int process_unique_id, |
int route_id, |
const GURL& url, |
ResourceType::Type type, |
@@ -296,9 +303,13 @@ bool ResourceDispatcherHost::HandleExternalProtocol(int request_id, |
return false; |
ChromeThread::PostTask( |
- ChromeThread::UI, FROM_HERE, |
+ ChromeThread::UI, |
+ FROM_HERE, |
NewRunnableFunction( |
- &ExternalProtocolHandler::LaunchUrl, url, child_id, route_id)); |
+ &ExternalProtocolHandler::LaunchUrl, |
+ url, |
+ process_unique_id, |
+ route_id)); |
handler->OnResponseCompleted(request_id, URLRequestStatus( |
URLRequestStatus::FAILED, |
@@ -362,7 +373,7 @@ void ResourceDispatcherHost::BeginRequest( |
IPC::Message* sync_result, // only valid for sync |
int route_id) { |
ChildProcessInfo::ProcessType process_type = receiver_->type(); |
- int child_id = receiver_->id(); |
+ int child_process_unique_id = receiver_->id(); |
ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( |
receiver_->GetRequestContext(request_id, request_data)); |
if (!context) { |
@@ -380,8 +391,9 @@ void ResourceDispatcherHost::BeginRequest( |
ResolveBlobReferencesInUploadData(request_data.upload_data.get()); |
} |
- if (is_shutdown_ || |
- !ShouldServiceRequest(process_type, child_id, request_data)) { |
+ if (is_shutdown_ || !ShouldServiceRequest(process_type, |
+ child_process_unique_id, |
+ request_data)) { |
URLRequestStatus status(URLRequestStatus::FAILED, net::ERR_ABORTED); |
if (sync_result) { |
SyncLoadResult result; |
@@ -410,13 +422,13 @@ void ResourceDispatcherHost::BeginRequest( |
scoped_refptr<ResourceHandler> handler; |
if (sync_result) { |
handler = new SyncResourceHandler(receiver_, |
- child_id, |
+ child_process_unique_id, |
request_data.url, |
sync_result, |
this); |
} else { |
handler = new AsyncResourceHandler(receiver_, |
- child_id, |
+ child_process_unique_id, |
route_id, |
receiver_->handle(), |
request_data.url, |
@@ -424,9 +436,11 @@ void ResourceDispatcherHost::BeginRequest( |
} |
if (request_data.download_to_file) |
- handler = new RedirectToFileResourceHandler(handler, child_id, this); |
+ handler = new RedirectToFileResourceHandler(handler, |
+ child_process_unique_id, |
+ this); |
- if (HandleExternalProtocol(request_id, child_id, route_id, |
+ if (HandleExternalProtocol(request_id, child_process_unique_id, route_id, |
request_data.url, request_data.resource_type, |
handler)) { |
return; |
@@ -469,11 +483,11 @@ void ResourceDispatcherHost::BeginRequest( |
if (request_data.resource_type == ResourceType::MAIN_FRAME && |
process_type == ChildProcessInfo::RENDER_PROCESS && |
Singleton<CrossSiteRequestManager>::get()-> |
- HasPendingCrossSiteRequest(child_id, route_id)) { |
+ HasPendingCrossSiteRequest(child_process_unique_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 = new CrossSiteResourceHandler(handler, |
- child_id, |
+ child_process_unique_id, |
route_id, |
this); |
} |
@@ -484,15 +498,20 @@ void ResourceDispatcherHost::BeginRequest( |
// Insert safe browsing at the front of the chain, so it gets to decide |
// on policies first. |
if (safe_browsing_->enabled()) { |
- handler = CreateSafeBrowsingResourceHandler(handler, child_id, route_id, |
+ handler = CreateSafeBrowsingResourceHandler(handler, |
+ child_process_unique_id, |
+ route_id, |
request_data.resource_type); |
} |
#if defined(OS_CHROMEOS) |
// We check offline first, then check safe browsing so that we still can block |
// unsafe site after we remove offline page. |
- handler = |
- new OfflineResourceHandler(handler, child_id, route_id, this, request); |
+ handler = new OfflineResourceHandler(handler, |
+ child_process_unique_id, |
+ route_id, |
+ this, |
+ request); |
#endif |
// Make extra info and read footer (contains request ID). |
@@ -500,7 +519,7 @@ void ResourceDispatcherHost::BeginRequest( |
new ResourceDispatcherHostRequestInfo( |
handler, |
process_type, |
- child_id, |
+ child_process_unique_id, |
route_id, |
request_id, |
request_data.frame_origin, |
@@ -519,8 +538,11 @@ void ResourceDispatcherHost::BeginRequest( |
// Have the appcache associate its extra info with the request. |
appcache::AppCacheInterceptor::SetExtraRequestInfo( |
- request, context ? context->appcache_service() : NULL, child_id, |
- request_data.appcache_host_id, request_data.resource_type); |
+ request, |
+ context ? context->appcache_service() : NULL, |
+ child_process_unique_id, |
+ request_data.appcache_host_id, |
+ request_data.resource_type); |
BeginRequestInternal(request); |
} |
@@ -529,10 +551,10 @@ void ResourceDispatcherHost::OnDataReceivedACK(int request_id) { |
DataReceivedACK(receiver_->id(), request_id); |
} |
-void ResourceDispatcherHost::DataReceivedACK(int child_id, |
+void ResourceDispatcherHost::DataReceivedACK(int process_unique_id, |
int request_id) { |
PendingRequestList::iterator i = pending_requests_.find( |
- GlobalRequestID(child_id, request_id)); |
+ GlobalRequestID(process_unique_id, request_id)); |
if (i == pending_requests_.end()) |
return; |
@@ -548,7 +570,7 @@ void ResourceDispatcherHost::DataReceivedACK(int child_id, |
info->DecrementPendingDataCount(); |
// Resume the request. |
- PauseRequest(child_id, request_id, false); |
+ PauseRequest(process_unique_id, request_id, false); |
} |
} |
@@ -558,9 +580,9 @@ bool ResourceDispatcherHost::Send(IPC::Message* message) { |
} |
void ResourceDispatcherHost::OnUploadProgressACK(int request_id) { |
- int child_id = receiver_->id(); |
+ int child_process_unique_id = receiver_->id(); |
PendingRequestList::iterator i = pending_requests_.find( |
- GlobalRequestID(child_id, request_id)); |
+ GlobalRequestID(child_process_unique_id, request_id)); |
if (i == pending_requests_.end()) |
return; |
@@ -582,10 +604,10 @@ void ResourceDispatcherHost::OnFollowRedirect( |
} |
ResourceHandler* ResourceDispatcherHost::CreateSafeBrowsingResourceHandler( |
- ResourceHandler* handler, int child_id, int route_id, |
+ ResourceHandler* handler, int process_unique_id, int route_id, |
ResourceType::Type resource_type) { |
return new SafeBrowsingResourceHandler(handler, |
- child_id, |
+ process_unique_id, |
route_id, |
resource_type, |
safe_browsing_, |
@@ -595,10 +617,13 @@ ResourceHandler* ResourceDispatcherHost::CreateSafeBrowsingResourceHandler( |
ResourceDispatcherHostRequestInfo* |
ResourceDispatcherHost::CreateRequestInfoForBrowserRequest( |
- ResourceHandler* handler, int child_id, int route_id, bool download) { |
+ ResourceHandler* handler, |
+ int process_unique_id, |
+ int route_id, |
+ bool download) { |
return new ResourceDispatcherHostRequestInfo(handler, |
ChildProcessInfo::RENDER_PROCESS, |
- child_id, |
+ process_unique_id, |
route_id, |
request_id_, |
"null", // frame_origin |
@@ -641,15 +666,16 @@ void ResourceDispatcherHost::BeginDownload( |
const GURL& referrer, |
const DownloadSaveInfo& save_info, |
bool prompt_for_save_location, |
- int child_id, |
+ int process_unique_id, |
int route_id, |
- URLRequestContext* request_context) { |
+ URLRequestContext* request_context, |
+ uint64 start_offset) { |
if (is_shutdown_) |
return; |
// Check if the renderer is permitted to request the requested URL. |
if (!ChildProcessSecurityPolicy::GetInstance()-> |
- CanRequestURL(child_id, url)) { |
+ CanRequestURL(process_unique_id, url)) { |
LOG(INFO) << "Denied unauthorized download request for " << |
url.possibly_invalid_spec(); |
return; |
@@ -664,7 +690,7 @@ void ResourceDispatcherHost::BeginDownload( |
scoped_refptr<ResourceHandler> handler = |
new DownloadResourceHandler(this, |
- child_id, |
+ process_unique_id, |
route_id, |
request_id_, |
url, |
@@ -674,7 +700,9 @@ void ResourceDispatcherHost::BeginDownload( |
save_info); |
if (safe_browsing_->enabled()) { |
- handler = CreateSafeBrowsingResourceHandler(handler, child_id, route_id, |
+ handler = CreateSafeBrowsingResourceHandler(handler, |
+ process_unique_id, |
+ route_id, |
ResourceType::MAIN_FRAME); |
} |
@@ -692,9 +720,25 @@ void ResourceDispatcherHost::BeginDownload( |
net::LOAD_IS_DOWNLOAD); |
ResourceDispatcherHostRequestInfo* extra_info = |
- CreateRequestInfoForBrowserRequest(handler, child_id, route_id, true); |
+ CreateRequestInfoForBrowserRequest(handler, |
+ process_unique_id, |
+ route_id, |
+ true); |
+ |
+ // If we're not at the beginning of the file, retrieve only the remaining |
+ // portion. |
+ if (start_offset > 0) { |
+ request->SetExtraRequestHeaderByName( |
+ "Range", |
+ StringPrintf("bytes=%" PRId64 "-", start_offset), |
+ false); |
+ extra_info->set_was_interrupted(true); |
+ extra_info->set_interrupted_bytes(start_offset); |
+ } |
+ |
SetRequestInfo(request, extra_info); // Request takes ownership. |
- chrome_browser_net::SetOriginProcessUniqueIDForRequest(child_id, request); |
+ chrome_browser_net::SetOriginProcessUniqueIDForRequest(process_unique_id, |
+ request); |
BeginRequestInternal(request); |
} |
@@ -702,7 +746,7 @@ void ResourceDispatcherHost::BeginDownload( |
// This function is only used for saving feature. |
void ResourceDispatcherHost::BeginSaveFile(const GURL& url, |
const GURL& referrer, |
- int child_id, |
+ int process_unique_id, |
int route_id, |
URLRequestContext* request_context) { |
if (is_shutdown_) |
@@ -713,7 +757,7 @@ void ResourceDispatcherHost::BeginSaveFile(const GURL& url, |
PluginService::GetInstance()->LoadChromePlugins(this); |
scoped_refptr<ResourceHandler> handler = |
- new SaveFileResourceHandler(child_id, |
+ new SaveFileResourceHandler(process_unique_id, |
route_id, |
url, |
save_file_manager_.get()); |
@@ -739,20 +783,24 @@ void ResourceDispatcherHost::BeginSaveFile(const GURL& url, |
// Since we're just saving some resources we need, disallow downloading. |
ResourceDispatcherHostRequestInfo* extra_info = |
- CreateRequestInfoForBrowserRequest(handler, child_id, route_id, false); |
+ CreateRequestInfoForBrowserRequest(handler, |
+ process_unique_id, |
+ route_id, |
+ false); |
SetRequestInfo(request, extra_info); // Request takes ownership. |
- chrome_browser_net::SetOriginProcessUniqueIDForRequest(child_id, request); |
+ chrome_browser_net::SetOriginProcessUniqueIDForRequest(process_unique_id, |
+ request); |
BeginRequestInternal(request); |
} |
void ResourceDispatcherHost::FollowDeferredRedirect( |
- int child_id, |
+ int process_unique_id, |
int request_id, |
bool has_new_first_party_for_cookies, |
const GURL& new_first_party_for_cookies) { |
PendingRequestList::iterator i = pending_requests_.find( |
- GlobalRequestID(child_id, request_id)); |
+ GlobalRequestID(process_unique_id, request_id)); |
if (i == pending_requests_.end() || !i->second->status().is_success()) { |
DLOG(WARNING) << "FollowDeferredRedirect for invalid request"; |
return; |
@@ -781,10 +829,10 @@ void ResourceDispatcherHost::StartDeferredRequest(int process_unique_id, |
InsertIntoResourceQueue(request, *InfoForRequest(request)); |
} |
-bool ResourceDispatcherHost::WillSendData(int child_id, |
+bool ResourceDispatcherHost::WillSendData(int process_unique_id, |
int request_id) { |
PendingRequestList::iterator i = pending_requests_.find( |
- GlobalRequestID(child_id, request_id)); |
+ GlobalRequestID(process_unique_id, request_id)); |
if (i == pending_requests_.end()) { |
NOTREACHED() << "WillSendData for invalid request"; |
return false; |
@@ -797,17 +845,17 @@ bool ResourceDispatcherHost::WillSendData(int child_id, |
// 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. |
- PauseRequest(child_id, request_id, true); |
+ PauseRequest(process_unique_id, request_id, true); |
return false; |
} |
return true; |
} |
-void ResourceDispatcherHost::PauseRequest(int child_id, |
+void ResourceDispatcherHost::PauseRequest(int process_unique_id, |
int request_id, |
bool pause) { |
- GlobalRequestID global_id(child_id, request_id); |
+ GlobalRequestID global_id(process_unique_id, request_id); |
PendingRequestList::iterator i = pending_requests_.find(global_id); |
if (i == pending_requests_.end()) { |
DLOG(WARNING) << "Pausing a request that wasn't found"; |
@@ -827,16 +875,48 @@ void ResourceDispatcherHost::PauseRequest(int child_id, |
// If we're resuming, kick the request to start reading again. Run the read |
// asynchronously to avoid recursion problems. |
if (info->pause_count() == 0) { |
- MessageLoop::current()->PostTask(FROM_HERE, |
+ MessageLoop::current()->PostTask( |
+ FROM_HERE, |
method_runner_.NewRunnableMethod( |
&ResourceDispatcherHost::ResumeRequest, global_id)); |
} |
} |
+void ResourceDispatcherHost::RestartRequest(int process_unique_id, |
+ int request_id, |
+ DownloadCreateInfo* create_info) { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
+ GlobalRequestID global_id(process_unique_id, request_id); |
+ RESOURCE_LOG("Restart : " << url.spec()); |
+ |
+ // Copy the IDs from the existing interrupted request. |
+ PendingRequestList::iterator i = interrupted_requests_.find(global_id); |
+ if (i != interrupted_requests_.end()) { |
+ URLRequest* request = i->second; |
+ if (request) { |
+ ResourceDispatcherHostRequestInfo* req_info = InfoForRequest(request); |
+ create_info->render_view_id = req_info->route_id(); |
+ create_info->child_id = req_info->child_id(); |
+ } |
+ |
+ MoveInterruptedRequestToPending(process_unique_id, request_id); |
+ } |
+ |
+ // Restart the request to continue reading. Run the read asynchronously to |
+ // avoid recursion problems. |
+ ChromeThread::PostTask( |
+ ChromeThread::FILE, |
+ FROM_HERE, |
+ NewRunnableFunction(&ResourceDispatcherHost::RestartDownload, |
+ this, |
+ global_id, |
+ create_info)); |
+} |
+ |
int ResourceDispatcherHost::GetOutstandingRequestsMemoryCost( |
- int child_id) const { |
+ int process_unique_id) const { |
OutstandingRequestsMemoryCostMap::const_iterator entry = |
- outstanding_requests_memory_cost_map_.find(child_id); |
+ outstanding_requests_memory_cost_map_.find(process_unique_id); |
return (entry == outstanding_requests_memory_cost_map_.end()) ? |
0 : entry->second; |
} |
@@ -844,31 +924,45 @@ int ResourceDispatcherHost::GetOutstandingRequestsMemoryCost( |
// The object died, so cancel and detach all requests associated with it except |
// for downloads, which belong to the browser process even if initiated via a |
// renderer. |
-void ResourceDispatcherHost::CancelRequestsForProcess(int child_id) { |
- socket_stream_dispatcher_host_->CancelRequestsForProcess(child_id); |
- CancelRequestsForRoute(child_id, -1 /* cancel all */); |
+void ResourceDispatcherHost::CancelRequestsForProcess(int process_unique_id) { |
+ socket_stream_dispatcher_host_->CancelRequestsForProcess(process_unique_id); |
+ CancelRequestsForRoute(process_unique_id, -1 /* cancel all */); |
} |
-void ResourceDispatcherHost::CancelRequestsForRoute(int child_id, |
- int route_id) { |
- // Since pending_requests_ is a map, we first build up a list of all of the |
- // matching requests to be cancelled, and then we cancel them. Since there |
- // may be more than one request to cancel, we cannot simply hold onto the map |
- // iterators found in the first loop. |
- |
- // Find the global ID of all matching elements. |
+std::vector<GlobalRequestID> ResourceDispatcherHost::GetMatchingRequests( |
+ int process_unique_id, |
+ int route_id, |
+ const PendingRequestList& requests) { |
std::vector<GlobalRequestID> matching_requests; |
- for (PendingRequestList::const_iterator i = pending_requests_.begin(); |
- i != pending_requests_.end(); ++i) { |
- if (i->first.child_id == child_id) { |
+ for (PendingRequestList::const_iterator i = requests.begin(); |
+ i != requests.end(); ++i) { |
+ if (i->first.child_id == process_unique_id) { |
ResourceDispatcherHostRequestInfo* info = InfoForRequest(i->second); |
if (!info->is_download() && |
(route_id == -1 || route_id == info->route_id())) { |
matching_requests.push_back( |
- GlobalRequestID(child_id, i->first.request_id)); |
+ GlobalRequestID(process_unique_id, i->first.request_id)); |
} |
} |
} |
+ return matching_requests; |
+} |
+ |
+void ResourceDispatcherHost::CancelRequestsForRoute(int process_unique_id, |
+ int route_id) { |
+ // Since pending_requests_ is a map, we first build up a list of all of the |
+ // matching requests to be cancelled, and then we cancel them. Since there |
+ // may be more than one request to cancel, we cannot simply hold onto the map |
+ // iterators found in the first loop. |
+ |
+ // Find the global ID of all matching elements. |
+ std::vector<GlobalRequestID> matching_requests = |
+ GetMatchingRequests(process_unique_id, route_id, pending_requests_); |
+ std::vector<GlobalRequestID> matching_requests2 = |
+ GetMatchingRequests(process_unique_id, route_id, interrupted_requests_); |
+ matching_requests.insert(matching_requests.begin(), |
+ matching_requests2.begin(), |
+ matching_requests2.end()); |
// Remove matches. |
for (size_t i = 0; i < matching_requests.size(); ++i) { |
@@ -883,46 +977,103 @@ void ResourceDispatcherHost::CancelRequestsForRoute(int child_id, |
// that URLRequest may complete and remove itself from pending_requests_. |
// So we need to check that iter is not equal to pending_requests_.end(). |
if (iter != pending_requests_.end()) |
- RemovePendingRequest(iter); |
+ RemoveRequestFromMap(iter); |
+ // Same for interrupted requests. |
+ iter = interrupted_requests_.find(matching_requests[i]); |
+ if (iter != interrupted_requests_.end()) |
+ RemoveRequestFromMap(iter); |
} |
// Now deal with blocked requests if any. |
if (route_id != -1) { |
- if (blocked_requests_map_.find(std::pair<int, int>(child_id, route_id)) != |
+ if (blocked_requests_map_.find(std::pair<int, int>(process_unique_id, |
+ route_id)) != |
blocked_requests_map_.end()) { |
- CancelBlockedRequestsForRoute(child_id, route_id); |
+ CancelBlockedRequestsForRoute(process_unique_id, route_id); |
} |
} else { |
- // We have to do all render views for the process |child_id|. |
+ // We have to do all render views for the process |process_unique_id|. |
// Note that we have to do this in 2 passes as we cannot call |
// CancelBlockedRequestsForRoute while iterating over |
// blocked_requests_map_, as it modifies it. |
std::set<int> route_ids; |
for (BlockedRequestMap::const_iterator iter = blocked_requests_map_.begin(); |
iter != blocked_requests_map_.end(); ++iter) { |
- if (iter->first.first == child_id) |
+ if (iter->first.first == process_unique_id) |
route_ids.insert(iter->first.second); |
} |
for (std::set<int>::const_iterator iter = route_ids.begin(); |
iter != route_ids.end(); ++iter) { |
- CancelBlockedRequestsForRoute(child_id, *iter); |
+ CancelBlockedRequestsForRoute(process_unique_id, *iter); |
} |
} |
} |
// Cancels the request and removes it from the list. |
-void ResourceDispatcherHost::RemovePendingRequest(int child_id, |
+void ResourceDispatcherHost::RemovePendingRequest(int process_unique_id, |
int request_id) { |
- PendingRequestList::iterator i = pending_requests_.find( |
- GlobalRequestID(child_id, request_id)); |
+ GlobalRequestID id(process_unique_id, request_id); |
+ PendingRequestList::iterator i = pending_requests_.find(id); |
if (i == pending_requests_.end()) { |
+ i = interrupted_requests_.find(id); |
+ if (i != interrupted_requests_.end()) |
+ return; |
NOTREACHED() << "Trying to remove a request that's not here"; |
return; |
} |
- RemovePendingRequest(i); |
+ RemoveRequestFromMap(i); |
} |
-void ResourceDispatcherHost::RemovePendingRequest( |
+// Cancels the request and removes it from the list. |
+void ResourceDispatcherHost::RemoveInterruptedRequest(int process_unique_id, |
+ int request_id) { |
+ GlobalRequestID id(process_unique_id, request_id); |
+ PendingRequestList::iterator i = interrupted_requests_.find(id); |
+ if (i == interrupted_requests_.end()) { |
+ NOTREACHED() << "Trying to remove a request that's not here"; |
+ return; |
+ } |
+ RemoveRequestFromMap(i); |
+} |
+ |
+void ResourceDispatcherHost::MovePendingRequestToInterrupted( |
+ int process_unique_id, int request_id) { |
+ GlobalRequestID id(process_unique_id, request_id); |
+ PendingRequestList::iterator iter = pending_requests_.find(id); |
+ if (iter == pending_requests_.end()) |
+ return; |
+ |
+ URLRequest* url_req = iter->second; |
+ |
+ ResourceDispatcherHostRequestInfo* info = InfoForRequest(url_req); |
+ |
+ info->set_was_interrupted(true); |
+ |
+ interrupted_requests_[id] = pending_requests_[id]; |
+ pending_requests_.erase(iter); |
+ |
+ // If we have no more pending requests, then stop the load state monitor |
+ if (pending_requests_.empty()) |
+ update_load_states_timer_.Stop(); |
+} |
+ |
+void ResourceDispatcherHost::MoveInterruptedRequestToPending( |
+ int process_unique_id, int request_id) { |
+ GlobalRequestID id(process_unique_id, request_id); |
+ PendingRequestList::iterator iter = interrupted_requests_.find(id); |
+ if (iter == interrupted_requests_.end()) |
+ return; |
+ |
+ // Don't need to call info->set_was_interrupted(false), as we will have |
+ // a new URLRequest when we resume downloading. If we clear it here, |
+ // then the information won't be available to |
+ // DownloadResourceHandler::OnResponseStarted(). |
+ |
+ pending_requests_[id] = interrupted_requests_[id]; |
+ interrupted_requests_.erase(iter); |
+} |
+ |
+void ResourceDispatcherHost::RemoveRequestFromMap( |
const PendingRequestList::iterator& iter) { |
ResourceDispatcherHostRequestInfo* info = InfoForRequest(iter->second); |
@@ -936,14 +1087,20 @@ void ResourceDispatcherHost::RemovePendingRequest( |
info->login_handler()->OnRequestCancelled(); |
if (info->ssl_client_auth_handler()) |
info->ssl_client_auth_handler()->OnRequestCancelled(); |
- resource_queue_.RemoveRequest(iter->first); |
+ |
+ GlobalRequestID id = iter->first; |
+ resource_queue_.RemoveRequest(id); |
delete iter->second; |
- pending_requests_.erase(iter); |
+ if (pending_requests_.find(id) != pending_requests_.end()) { |
+ pending_requests_.erase(iter); |
- // If we have no more pending requests, then stop the load state monitor |
- if (pending_requests_.empty()) |
- update_load_states_timer_.Stop(); |
+ // If we have no more pending requests, then stop the load state monitor |
+ if (pending_requests_.empty()) |
+ update_load_states_timer_.Stop(); |
+ } |
+ if (interrupted_requests_.find(id) != interrupted_requests_.end()) |
+ interrupted_requests_.erase(iter); |
} |
// URLRequest::Delegate ------------------------------------------------------- |
@@ -1104,17 +1261,20 @@ bool ResourceDispatcherHost::CompleteResponseStarted(URLRequest* request) { |
response.get()); |
} |
-void ResourceDispatcherHost::CancelRequest(int child_id, |
+void ResourceDispatcherHost::CancelRequest(int process_unique_id, |
int request_id, |
bool from_renderer) { |
- PendingRequestList::iterator i = pending_requests_.find( |
- GlobalRequestID(child_id, request_id)); |
+ GlobalRequestID id(process_unique_id, request_id); |
+ 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 |
- // should be rare and may indicate a bug. |
- DLOG(WARNING) << "Canceling a request that wasn't found"; |
- return; |
+ i = interrupted_requests_.find(id); |
+ if (i == interrupted_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 |
+ // should be rare and may indicate a bug. |
+ DLOG(WARNING) << "Canceling a request that wasn't found"; |
+ return; |
+ } |
} |
CancelRequestInternal(i->second, from_renderer); |
} |
@@ -1147,10 +1307,10 @@ void ResourceDispatcherHost::CancelRequestInternal(URLRequest* request, |
int ResourceDispatcherHost::IncrementOutstandingRequestsMemoryCost( |
int cost, |
- int child_id) { |
+ int process_unique_id) { |
// Retrieve the previous value (defaulting to 0 if not found). |
OutstandingRequestsMemoryCostMap::iterator prev_entry = |
- outstanding_requests_memory_cost_map_.find(child_id); |
+ outstanding_requests_memory_cost_map_.find(process_unique_id); |
int new_cost = 0; |
if (prev_entry != outstanding_requests_memory_cost_map_.end()) |
new_cost = prev_entry->second; |
@@ -1161,7 +1321,7 @@ int ResourceDispatcherHost::IncrementOutstandingRequestsMemoryCost( |
if (new_cost == 0) |
outstanding_requests_memory_cost_map_.erase(prev_entry); |
else |
- outstanding_requests_memory_cost_map_[child_id] = new_cost; |
+ outstanding_requests_memory_cost_map_[process_unique_id] = new_cost; |
return new_cost; |
} |
@@ -1292,21 +1452,42 @@ void ResourceDispatcherHost::ResumeRequest(const GlobalRequestID& request_id) { |
if (!info->is_paused()) |
return; |
- RESOURCE_LOG("Resuming: " << i->second->url().spec()); |
+ RESOURCE_LOG("Resuming: " << request->url().spec()); |
info->set_is_paused(false); |
if (info->called_on_response_started()) { |
if (info->has_started_reading()) { |
- OnReadCompleted(i->second, info->paused_read_bytes()); |
+ OnReadCompleted(request, info->paused_read_bytes()); |
} else { |
StartReading(request); |
} |
} else { |
- OnResponseStarted(i->second); |
+ OnResponseStarted(request); |
} |
} |
+// static |
+void ResourceDispatcherHost::RestartDownload( |
+ ResourceDispatcherHost* rdh, |
+ const GlobalRequestID& request_id, |
+ DownloadCreateInfo* info) { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
+ RESOURCE_LOG("Restarting: " << info->url.spec()); |
+ |
+ // Restart the request. |
+ download_util::RestartDownloadUrl(rdh, |
+ info->url, |
+ info->referrer_url, |
+ info->path, |
+ info->received_bytes, |
+ request_id.child_id, |
+ info->render_view_id); |
+ |
+ // Clean up. |
+ delete info; |
+} |
+ |
void ResourceDispatcherHost::StartReading(URLRequest* request) { |
// Start reading. |
int bytes_read = 0; |
@@ -1433,6 +1614,11 @@ void ResourceDispatcherHost::OnResponseCompleted(URLRequest* request) { |
if (info->resource_handler()->OnResponseCompleted(info->request_id(), |
request->status(), |
security_info)) { |
+ if ((request->status().status() == URLRequestStatus::FAILED) && |
+ (request->status().os_error() < 0)) { |
+ MovePendingRequestToInterrupted(info->child_id(), info->request_id()); |
+ } |
+ |
NotifyResponseCompleted(request, info->child_id()); |
// The request is complete so we can remove it. |
@@ -1445,7 +1631,7 @@ void ResourceDispatcherHost::OnResponseCompleted(URLRequest* request) { |
// static |
ResourceDispatcherHostRequestInfo* ResourceDispatcherHost::InfoForRequest( |
URLRequest* request) { |
- // Avoid writing this function twice by casting the cosnt version. |
+ // Avoid writing this function twice by casting the const version. |
const URLRequest* const_request = request; |
return const_cast<ResourceDispatcherHostRequestInfo*>( |
InfoForRequest(const_request)); |
@@ -1509,16 +1695,19 @@ URLRequest* ResourceDispatcherHost::GetURLRequest( |
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
PendingRequestList::const_iterator i = pending_requests_.find(request_id); |
- if (i == pending_requests_.end()) |
- return NULL; |
+ if (i == pending_requests_.end()) { |
+ i = interrupted_requests_.find(request_id); |
+ if (i == interrupted_requests_.end()) |
+ return NULL; |
+ } |
return i->second; |
} |
-static int GetCertID(URLRequest* request, int child_id) { |
+static int GetCertID(URLRequest* request, int process_unique_id) { |
if (request->ssl_info().cert) { |
return CertStore::GetSharedInstance()->StoreCert(request->ssl_info().cert, |
- child_id); |
+ process_unique_id); |
} |
// If there is no SSL info attached to this request, we must either be a non |
// secure request, or the request has been canceled or failed (before the SSL |
@@ -1533,7 +1722,7 @@ static int GetCertID(URLRequest* request, int child_id) { |
} |
void ResourceDispatcherHost::NotifyResponseStarted(URLRequest* request, |
- int child_id) { |
+ int process_unique_id) { |
// Notify the observers on the IO thread. |
FOR_EACH_OBSERVER(Observer, observer_list_, OnRequestStarted(this, request)); |
@@ -1545,18 +1734,18 @@ void ResourceDispatcherHost::NotifyResponseStarted(URLRequest* request, |
CallRenderViewHostResourceDelegate( |
render_process_id, render_view_id, |
&RenderViewHostDelegate::Resource::DidStartReceivingResourceResponse, |
- ResourceRequestDetails(request, GetCertID(request, child_id))); |
+ ResourceRequestDetails(request, GetCertID(request, process_unique_id))); |
} |
void ResourceDispatcherHost::NotifyResponseCompleted(URLRequest* request, |
- int child_id) { |
+ int process_unique_id) { |
// Notify the observers on the IO thread. |
FOR_EACH_OBSERVER(Observer, observer_list_, |
OnResponseCompleted(this, request)); |
} |
void ResourceDispatcherHost::NotifyReceivedRedirect(URLRequest* request, |
- int child_id, |
+ int process_unique_id, |
const GURL& new_url) { |
// Notify the observers on the IO thread. |
FOR_EACH_OBSERVER(Observer, observer_list_, |
@@ -1570,7 +1759,9 @@ void ResourceDispatcherHost::NotifyReceivedRedirect(URLRequest* request, |
CallRenderViewHostResourceDelegate( |
render_process_id, render_view_id, |
&RenderViewHostDelegate::Resource::DidRedirectResource, |
- ResourceRedirectDetails(request, GetCertID(request, child_id), new_url)); |
+ ResourceRedirectDetails(request, |
+ GetCertID(request, process_unique_id), |
+ new_url)); |
} |
namespace { |
@@ -1730,29 +1921,32 @@ bool ResourceDispatcherHost::MaybeUpdateUploadProgress( |
return false; |
} |
-void ResourceDispatcherHost::BlockRequestsForRoute(int child_id, int route_id) { |
- std::pair<int, int> key(child_id, route_id); |
+void ResourceDispatcherHost::BlockRequestsForRoute(int process_unique_id, |
+ int route_id) { |
+ std::pair<int, int> key(process_unique_id, route_id); |
DCHECK(blocked_requests_map_.find(key) == blocked_requests_map_.end()) << |
"BlockRequestsForRoute called multiple time for the same RVH"; |
blocked_requests_map_[key] = new BlockedRequestsList(); |
} |
-void ResourceDispatcherHost::ResumeBlockedRequestsForRoute(int child_id, |
- int route_id) { |
- ProcessBlockedRequestsForRoute(child_id, route_id, false); |
+void ResourceDispatcherHost::ResumeBlockedRequestsForRoute( |
+ int process_unique_id, |
+ int route_id) { |
+ ProcessBlockedRequestsForRoute(process_unique_id, route_id, false); |
} |
-void ResourceDispatcherHost::CancelBlockedRequestsForRoute(int child_id, |
- int route_id) { |
- ProcessBlockedRequestsForRoute(child_id, route_id, true); |
+void ResourceDispatcherHost::CancelBlockedRequestsForRoute( |
+ int process_unique_id, |
+ int route_id) { |
+ ProcessBlockedRequestsForRoute(process_unique_id, route_id, true); |
} |
void ResourceDispatcherHost::ProcessBlockedRequestsForRoute( |
- int child_id, |
+ int process_unique_id, |
int route_id, |
bool cancel_requests) { |
BlockedRequestMap::iterator iter = blocked_requests_map_.find( |
- std::pair<int, int>(child_id, route_id)); |
+ std::pair<int, int>(process_unique_id, route_id)); |
if (iter == blocked_requests_map_.end()) { |
// It's possible to reach here if the renderer crashed while an interstitial |
// page was showing. |
@@ -1785,9 +1979,17 @@ bool ResourceDispatcherHost::IsValidRequest(URLRequest* request) { |
if (!request) |
return false; |
ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
- return pending_requests_.find( |
- GlobalRequestID(info->child_id(), info->request_id())) != |
- pending_requests_.end(); |
+ GlobalRequestID id(info->child_id(), info->request_id()); |
+ return (pending_requests_.find(id) != pending_requests_.end()) || |
+ (interrupted_requests_.find(id) != interrupted_requests_.end()); |
+} |
+ |
+bool ResourceDispatcherHost::IsInterruptedRequest(URLRequest* request) { |
+ if (!request) |
+ return false; |
+ ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
+ GlobalRequestID id(info->child_id(), info->request_id()); |
+ return interrupted_requests_.find(id) != interrupted_requests_.end(); |
} |
// static |