| 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
|
|
|