Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2027)

Unified Diff: chrome/browser/renderer_host/resource_dispatcher_host.cc

Issue 3127008: Preliminary work on resuming downloads whose connections have expired.
Patch Set: Waiting to send download automation error message until after other downloads are canceled. Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698