| Index: content/browser/renderer_host/resource_dispatcher_host_impl.cc
|
| ===================================================================
|
| --- content/browser/renderer_host/resource_dispatcher_host_impl.cc (revision 170763)
|
| +++ content/browser/renderer_host/resource_dispatcher_host_impl.cc (working copy)
|
| @@ -1,1729 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading
|
| -
|
| -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h"
|
| -
|
| -#include <set>
|
| -#include <vector>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/command_line.h"
|
| -#include "base/compiler_specific.h"
|
| -#include "base/debug/alias.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/metrics/histogram.h"
|
| -#include "base/shared_memory.h"
|
| -#include "base/stl_util.h"
|
| -#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
|
| -#include "content/browser/appcache/chrome_appcache_service.h"
|
| -#include "content/browser/cert_store_impl.h"
|
| -#include "content/browser/child_process_security_policy_impl.h"
|
| -#include "content/browser/cross_site_request_manager.h"
|
| -#include "content/browser/download/download_resource_handler.h"
|
| -#include "content/browser/download/save_file_manager.h"
|
| -#include "content/browser/download/save_file_resource_handler.h"
|
| -#include "content/browser/fileapi/chrome_blob_storage_context.h"
|
| -#include "content/browser/plugin_service_impl.h"
|
| -#include "content/browser/renderer_host/async_resource_handler.h"
|
| -#include "content/browser/renderer_host/buffered_resource_handler.h"
|
| -#include "content/browser/renderer_host/cross_site_resource_handler.h"
|
| -#include "content/browser/renderer_host/redirect_to_file_resource_handler.h"
|
| -#include "content/browser/renderer_host/render_view_host_delegate.h"
|
| -#include "content/browser/renderer_host/render_view_host_impl.h"
|
| -#include "content/browser/renderer_host/resource_message_filter.h"
|
| -#include "content/browser/renderer_host/resource_request_info_impl.h"
|
| -#include "content/browser/renderer_host/sync_resource_handler.h"
|
| -#include "content/browser/renderer_host/throttling_resource_handler.h"
|
| -#include "content/browser/renderer_host/transfer_navigation_resource_throttle.h"
|
| -#include "content/browser/resource_context_impl.h"
|
| -#include "content/browser/worker_host/worker_service_impl.h"
|
| -#include "content/common/resource_messages.h"
|
| -#include "content/common/ssl_status_serialization.h"
|
| -#include "content/common/view_messages.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "content/public/browser/content_browser_client.h"
|
| -#include "content/public/browser/download_manager.h"
|
| -#include "content/public/browser/global_request_id.h"
|
| -#include "content/public/browser/notification_service.h"
|
| -#include "content/public/browser/resource_dispatcher_host_delegate.h"
|
| -#include "content/public/browser/resource_request_details.h"
|
| -#include "content/public/browser/resource_throttle.h"
|
| -#include "content/public/browser/user_metrics.h"
|
| -#include "content/public/common/content_switches.h"
|
| -#include "content/public/common/process_type.h"
|
| -#include "content/public/common/url_constants.h"
|
| -#include "net/base/auth.h"
|
| -#include "net/base/cert_status_flags.h"
|
| -#include "net/base/load_flags.h"
|
| -#include "net/base/mime_util.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
| -#include "net/base/request_priority.h"
|
| -#include "net/base/ssl_cert_request_info.h"
|
| -#include "net/base/upload_data.h"
|
| -#include "net/cookies/cookie_monster.h"
|
| -#include "net/http/http_cache.h"
|
| -#include "net/http/http_response_headers.h"
|
| -#include "net/http/http_response_info.h"
|
| -#include "net/http/http_transaction_factory.h"
|
| -#include "net/url_request/url_request.h"
|
| -#include "net/url_request/url_request_context.h"
|
| -#include "net/url_request/url_request_job_factory.h"
|
| -#include "webkit/appcache/appcache_interceptor.h"
|
| -#include "webkit/appcache/appcache_interfaces.h"
|
| -#include "webkit/blob/blob_storage_controller.h"
|
| -#include "webkit/blob/shareable_file_reference.h"
|
| -#include "webkit/glue/resource_request_body.h"
|
| -#include "webkit/glue/webkit_glue.h"
|
| -
|
| -using base::Time;
|
| -using base::TimeDelta;
|
| -using base::TimeTicks;
|
| -using webkit_blob::ShareableFileReference;
|
| -using webkit_glue::ResourceRequestBody;
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -namespace content {
|
| -
|
| -namespace {
|
| -
|
| -static ResourceDispatcherHostImpl* g_resource_dispatcher_host;
|
| -
|
| -// The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates
|
| -const int kUpdateLoadStatesIntervalMsec = 100;
|
| -
|
| -// Maximum byte "cost" of all the outstanding requests for a renderer.
|
| -// See delcaration of |max_outstanding_requests_cost_per_process_| for details.
|
| -// This bound is 25MB, which allows for around 6000 outstanding requests.
|
| -const int kMaxOutstandingRequestsCostPerProcess = 26214400;
|
| -
|
| -// The number of milliseconds after noting a user gesture that we will
|
| -// tag newly-created URLRequest objects with the
|
| -// net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary
|
| -// guess at how long to expect direct impact from a user gesture, but
|
| -// this should be OK as the load flag is a best-effort thing only,
|
| -// rather than being intended as fully accurate.
|
| -const int kUserGestureWindowMs = 3500;
|
| -
|
| -// All possible error codes from the network module. Note that the error codes
|
| -// are all positive (since histograms expect positive sample values).
|
| -const int kAllNetErrorCodes[] = {
|
| -#define NET_ERROR(label, value) -(value),
|
| -#include "net/base/net_error_list.h"
|
| -#undef NET_ERROR
|
| -};
|
| -
|
| -// Aborts a request before an URLRequest has actually been created.
|
| -void AbortRequestBeforeItStarts(ResourceMessageFilter* filter,
|
| - IPC::Message* sync_result,
|
| - int route_id,
|
| - int request_id) {
|
| - if (sync_result) {
|
| - SyncLoadResult result;
|
| - result.error_code = net::ERR_ABORTED;
|
| - ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result, result);
|
| - filter->Send(sync_result);
|
| - } else {
|
| - // Tell the renderer that this request was disallowed.
|
| - filter->Send(new ResourceMsg_RequestComplete(
|
| - route_id,
|
| - request_id,
|
| - net::ERR_ABORTED,
|
| - false,
|
| - std::string(), // No security info needed, connection not established.
|
| - base::TimeTicks()));
|
| - }
|
| -}
|
| -
|
| -GURL MaybeStripReferrer(const GURL& possible_referrer) {
|
| - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoReferrers))
|
| - return GURL();
|
| - return possible_referrer;
|
| -}
|
| -
|
| -// Consults the RendererSecurity policy to determine whether the
|
| -// ResourceDispatcherHostImpl should service this request. A request might be
|
| -// 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(ProcessType process_type,
|
| - int child_id,
|
| - const ResourceHostMsg_Request& request_data) {
|
| - if (process_type == PROCESS_TYPE_PLUGIN)
|
| - return true;
|
| -
|
| - ChildProcessSecurityPolicyImpl* policy =
|
| - ChildProcessSecurityPolicyImpl::GetInstance();
|
| -
|
| - // Check if the renderer is permitted to request the requested URL.
|
| - if (!policy->CanRequestURL(child_id, request_data.url)) {
|
| - VLOG(1) << "Denied unauthorized request for "
|
| - << request_data.url.possibly_invalid_spec();
|
| - return false;
|
| - }
|
| -
|
| - // Check if the renderer is permitted to upload the requested files.
|
| - if (request_data.request_body) {
|
| - const std::vector<ResourceRequestBody::Element>* uploads =
|
| - request_data.request_body->elements();
|
| - std::vector<ResourceRequestBody::Element>::const_iterator iter;
|
| - for (iter = uploads->begin(); iter != uploads->end(); ++iter) {
|
| - if (iter->type() == ResourceRequestBody::Element::TYPE_FILE &&
|
| - !policy->CanReadFile(child_id, iter->path())) {
|
| - NOTREACHED() << "Denied unauthorized upload of "
|
| - << iter->path().value();
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void RemoveDownloadFileFromChildSecurityPolicy(int child_id,
|
| - const FilePath& path) {
|
| - ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile(
|
| - child_id, path);
|
| -}
|
| -
|
| -#if defined(OS_WIN)
|
| -#pragma warning(disable: 4748)
|
| -#pragma optimize("", off)
|
| -#endif
|
| -
|
| -#if defined(OS_WIN)
|
| -#pragma optimize("", on)
|
| -#pragma warning(default: 4748)
|
| -#endif
|
| -
|
| -net::RequestPriority DetermineRequestPriority(ResourceType::Type type) {
|
| - // Determine request priority based on how critical this resource typically
|
| - // is to user-perceived page load performance. Important considerations are:
|
| - // * Can this resource block the download of other resources.
|
| - // * Can this resource block the rendering of the page.
|
| - // * How useful is the page to the user if this resource is not loaded yet.
|
| -
|
| - switch (type) {
|
| - // Main frames are the highest priority because they can block nearly every
|
| - // type of other resource and there is no useful display without them.
|
| - // Sub frames are a close second, however it is a common pattern to wrap
|
| - // ads in an iframe or even in multiple nested iframes. It is worth
|
| - // investigating if there is a better priority for them.
|
| - case ResourceType::MAIN_FRAME:
|
| - case ResourceType::SUB_FRAME:
|
| - return net::HIGHEST;
|
| -
|
| - // Stylesheets and scripts can block rendering and loading of other
|
| - // resources. Fonts can block text from rendering.
|
| - case ResourceType::STYLESHEET:
|
| - case ResourceType::SCRIPT:
|
| - case ResourceType::FONT_RESOURCE:
|
| - return net::MEDIUM;
|
| -
|
| - // Sub resources, objects and media are lower priority than potentially
|
| - // blocking stylesheets, scripts and fonts, but are higher priority than
|
| - // images because if they exist they are probably more central to the page
|
| - // focus than images on the page.
|
| - case ResourceType::SUB_RESOURCE:
|
| - case ResourceType::OBJECT:
|
| - case ResourceType::MEDIA:
|
| - case ResourceType::WORKER:
|
| - case ResourceType::SHARED_WORKER:
|
| - case ResourceType::XHR:
|
| - return net::LOW;
|
| -
|
| - // Images are the "lowest" priority because they typically do not block
|
| - // downloads or rendering and most pages have some useful content without
|
| - // them.
|
| - case ResourceType::IMAGE:
|
| - // Favicons aren't required for rendering the current page, but
|
| - // are user visible.
|
| - case ResourceType::FAVICON:
|
| - return net::LOWEST;
|
| -
|
| - // Prefetches are at a lower priority than even LOWEST, since they are not
|
| - // even required for rendering of the current page.
|
| - case ResourceType::PREFETCH:
|
| - return net::IDLE;
|
| -
|
| - default:
|
| - // When new resource types are added, their priority must be considered.
|
| - NOTREACHED();
|
| - return net::LOW;
|
| - }
|
| -}
|
| -
|
| -void OnSwapOutACKHelper(int render_process_id,
|
| - int render_view_id,
|
| - bool timed_out) {
|
| - RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(render_process_id,
|
| - render_view_id);
|
| - if (rvh)
|
| - rvh->OnSwapOutACK(timed_out);
|
| -}
|
| -
|
| -net::Error CallbackAndReturn(
|
| - const DownloadResourceHandler::OnStartedCallback& started_cb,
|
| - net::Error net_error) {
|
| - if (started_cb.is_null())
|
| - return net_error;
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(started_cb, static_cast<DownloadItem*>(NULL), net_error));
|
| -
|
| - return net_error;
|
| -}
|
| -
|
| -int BuildLoadFlagsForRequest(const ResourceHostMsg_Request& request_data,
|
| - int child_id, bool is_sync_load) {
|
| - int load_flags = request_data.load_flags;
|
| -
|
| - // Although EV status is irrelevant to sub-frames and sub-resources, we have
|
| - // to perform EV certificate verification on all resources because an HTTP
|
| - // keep-alive connection created to load a sub-frame or a sub-resource could
|
| - // be reused to load a main frame.
|
| - load_flags |= net::LOAD_VERIFY_EV_CERT;
|
| - if (request_data.resource_type == ResourceType::MAIN_FRAME) {
|
| - load_flags |= net::LOAD_MAIN_FRAME;
|
| - } else if (request_data.resource_type == ResourceType::SUB_FRAME) {
|
| - load_flags |= net::LOAD_SUB_FRAME;
|
| - } else if (request_data.resource_type == ResourceType::PREFETCH) {
|
| - load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN);
|
| - } else if (request_data.resource_type == ResourceType::FAVICON) {
|
| - load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN;
|
| - }
|
| -
|
| - if (is_sync_load)
|
| - load_flags |= net::LOAD_IGNORE_LIMITS;
|
| -
|
| - ChildProcessSecurityPolicyImpl* policy =
|
| - ChildProcessSecurityPolicyImpl::GetInstance();
|
| - if (!policy->CanSendCookiesForOrigin(child_id, request_data.url)) {
|
| - load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES |
|
| - net::LOAD_DO_NOT_SEND_AUTH_DATA |
|
| - net::LOAD_DO_NOT_SAVE_COOKIES);
|
| - }
|
| -
|
| - // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only
|
| - // allow requesting them if requester has ReadRawCookies permission.
|
| - if ((load_flags & net::LOAD_REPORT_RAW_HEADERS)
|
| - && !policy->CanReadRawCookies(child_id)) {
|
| - VLOG(1) << "Denied unauthorized request for raw headers";
|
| - load_flags &= ~net::LOAD_REPORT_RAW_HEADERS;
|
| - }
|
| -
|
| - return load_flags;
|
| -}
|
| -
|
| -int GetCertID(net::URLRequest* request, int child_id) {
|
| - if (request->ssl_info().cert) {
|
| - return CertStore::GetInstance()->StoreCert(request->ssl_info().cert,
|
| - child_id);
|
| - }
|
| - return 0;
|
| -}
|
| -
|
| -template <class T>
|
| -void NotifyOnUI(int type, int render_process_id, int render_view_id,
|
| - scoped_ptr<T> detail) {
|
| - RenderViewHostImpl* host =
|
| - RenderViewHostImpl::FromID(render_process_id, render_view_id);
|
| - if (host) {
|
| - RenderViewHostDelegate* delegate = host->GetDelegate();
|
| - NotificationService::current()->Notify(
|
| - type, Source<WebContents>(delegate->GetAsWebContents()),
|
| - Details<T>(detail.get()));
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// static
|
| -ResourceDispatcherHost* ResourceDispatcherHost::Get() {
|
| - return g_resource_dispatcher_host;
|
| -}
|
| -
|
| -ResourceDispatcherHostImpl::ResourceDispatcherHostImpl()
|
| - : save_file_manager_(new SaveFileManager()),
|
| - request_id_(-1),
|
| - is_shutdown_(false),
|
| - max_outstanding_requests_cost_per_process_(
|
| - kMaxOutstandingRequestsCostPerProcess),
|
| - filter_(NULL),
|
| - delegate_(NULL),
|
| - allow_cross_origin_auth_prompt_(false) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK(!g_resource_dispatcher_host);
|
| - g_resource_dispatcher_host = this;
|
| -
|
| - GetContentClient()->browser()->ResourceDispatcherHostCreated();
|
| -
|
| - ANNOTATE_BENIGN_RACE(
|
| - &last_user_gesture_time_,
|
| - "We don't care about the precise value, see http://crbug.com/92889");
|
| -
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO, FROM_HERE,
|
| - base::Bind(&appcache::AppCacheInterceptor::EnsureRegistered));
|
| -
|
| - update_load_states_timer_.reset(
|
| - new base::RepeatingTimer<ResourceDispatcherHostImpl>());
|
| -}
|
| -
|
| -ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() {
|
| - DCHECK(g_resource_dispatcher_host);
|
| - g_resource_dispatcher_host = NULL;
|
| -}
|
| -
|
| -// static
|
| -ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() {
|
| - return g_resource_dispatcher_host;
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::SetDelegate(
|
| - ResourceDispatcherHostDelegate* delegate) {
|
| - delegate_ = delegate;
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::SetAllowCrossOriginAuthPrompt(bool value) {
|
| - allow_cross_origin_auth_prompt_ = value;
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::AddResourceContext(ResourceContext* context) {
|
| - active_resource_contexts_.insert(context);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::RemoveResourceContext(
|
| - ResourceContext* context) {
|
| - CHECK(ContainsKey(active_resource_contexts_, context));
|
| - active_resource_contexts_.erase(context);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::CancelRequestsForContext(
|
| - ResourceContext* context) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - DCHECK(context);
|
| -
|
| - CHECK(ContainsKey(active_resource_contexts_, context));
|
| -
|
| - // Note that request cancellation has side effects. Therefore, we gather all
|
| - // the requests to cancel first, and then we start cancelling. We assert at
|
| - // the end that there are no more to cancel since the context is about to go
|
| - // away.
|
| - typedef std::vector<linked_ptr<ResourceLoader> > LoaderList;
|
| - LoaderList loaders_to_cancel;
|
| -
|
| - for (LoaderMap::iterator i = pending_loaders_.begin();
|
| - i != pending_loaders_.end();) {
|
| - if (i->second->GetRequestInfo()->GetContext() == context) {
|
| - loaders_to_cancel.push_back(i->second);
|
| - pending_loaders_.erase(i++);
|
| - } else {
|
| - ++i;
|
| - }
|
| - }
|
| -
|
| - for (BlockedLoadersMap::iterator i = blocked_loaders_map_.begin();
|
| - i != blocked_loaders_map_.end();) {
|
| - BlockedLoadersList* loaders = i->second;
|
| - if (loaders->empty()) {
|
| - // This can happen if BlockRequestsForRoute() has been called for a route,
|
| - // but we haven't blocked any matching requests yet.
|
| - ++i;
|
| - continue;
|
| - }
|
| - ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo();
|
| - if (info->GetContext() == context) {
|
| - blocked_loaders_map_.erase(i++);
|
| - for (BlockedLoadersList::const_iterator it = loaders->begin();
|
| - it != loaders->end(); ++it) {
|
| - linked_ptr<ResourceLoader> loader = *it;
|
| - info = loader->GetRequestInfo();
|
| - // We make the assumption that all requests on the list have the same
|
| - // ResourceContext.
|
| - DCHECK_EQ(context, info->GetContext());
|
| - IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(),
|
| - info->GetChildID());
|
| - loaders_to_cancel.push_back(loader);
|
| - }
|
| - delete loaders;
|
| - } else {
|
| - ++i;
|
| - }
|
| - }
|
| -
|
| -#ifndef NDEBUG
|
| - for (LoaderList::iterator i = loaders_to_cancel.begin();
|
| - i != loaders_to_cancel.end(); ++i) {
|
| - // There is no strict requirement that this be the case, but currently
|
| - // downloads and transferred requests are the only requests that aren't
|
| - // cancelled when the associated processes go away. It may be OK for this
|
| - // invariant to change in the future, but if this assertion fires without
|
| - // the invariant changing, then it's indicative of a leak.
|
| - DCHECK((*i)->GetRequestInfo()->is_download() || (*i)->is_transferring());
|
| - }
|
| -#endif
|
| -
|
| - loaders_to_cancel.clear();
|
| -
|
| - // Validate that no more requests for this context were added.
|
| - for (LoaderMap::const_iterator i = pending_loaders_.begin();
|
| - i != pending_loaders_.end(); ++i) {
|
| - // http://crbug.com/90971
|
| - CHECK_NE(i->second->GetRequestInfo()->GetContext(), context);
|
| - }
|
| -
|
| - for (BlockedLoadersMap::const_iterator i = blocked_loaders_map_.begin();
|
| - i != blocked_loaders_map_.end(); ++i) {
|
| - BlockedLoadersList* loaders = i->second;
|
| - if (!loaders->empty()) {
|
| - ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo();
|
| - // http://crbug.com/90971
|
| - CHECK_NE(info->GetContext(), context);
|
| - }
|
| - }
|
| -}
|
| -
|
| -net::Error ResourceDispatcherHostImpl::BeginDownload(
|
| - scoped_ptr<net::URLRequest> request,
|
| - bool is_content_initiated,
|
| - ResourceContext* context,
|
| - int child_id,
|
| - int route_id,
|
| - bool prefer_cache,
|
| - scoped_ptr<DownloadSaveInfo> save_info,
|
| - const DownloadStartedCallback& started_callback) {
|
| - if (is_shutdown_)
|
| - return CallbackAndReturn(started_callback, net::ERR_INSUFFICIENT_RESOURCES);
|
| -
|
| - const GURL& url = request->original_url();
|
| -
|
| - // http://crbug.com/90971
|
| - char url_buf[128];
|
| - base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf));
|
| - base::debug::Alias(url_buf);
|
| - CHECK(ContainsKey(active_resource_contexts_, context));
|
| -
|
| - request->set_referrer(MaybeStripReferrer(GURL(request->referrer())).spec());
|
| - int extra_load_flags = net::LOAD_IS_DOWNLOAD;
|
| - if (prefer_cache) {
|
| - // If there is upload data attached, only retrieve from cache because there
|
| - // is no current mechanism to prompt the user for their consent for a
|
| - // re-post. For GETs, try to retrieve data from the cache and skip
|
| - // validating the entry if present.
|
| - if (request->get_upload() != NULL)
|
| - extra_load_flags |= net::LOAD_ONLY_FROM_CACHE;
|
| - else
|
| - extra_load_flags |= net::LOAD_PREFERRING_CACHE;
|
| - } else {
|
| - extra_load_flags |= net::LOAD_DISABLE_CACHE;
|
| - }
|
| - request->set_load_flags(request->load_flags() | extra_load_flags);
|
| - // Check if the renderer is permitted to request the requested URL.
|
| - if (!ChildProcessSecurityPolicyImpl::GetInstance()->
|
| - CanRequestURL(child_id, url)) {
|
| - VLOG(1) << "Denied unauthorized download request for "
|
| - << url.possibly_invalid_spec();
|
| - return CallbackAndReturn(started_callback, net::ERR_ACCESS_DENIED);
|
| - }
|
| -
|
| - request_id_--;
|
| -
|
| - const net::URLRequestContext* request_context = context->GetRequestContext();
|
| - if (!request_context->job_factory()->IsHandledURL(url)) {
|
| - VLOG(1) << "Download request for unsupported protocol: "
|
| - << url.possibly_invalid_spec();
|
| - return CallbackAndReturn(started_callback, net::ERR_ACCESS_DENIED);
|
| - }
|
| -
|
| - ResourceRequestInfoImpl* extra_info =
|
| - CreateRequestInfo(child_id, route_id, true, context);
|
| - extra_info->AssociateWithRequest(request.get()); // Request takes ownership.
|
| -
|
| - // From this point forward, the |DownloadResourceHandler| is responsible for
|
| - // |started_callback|.
|
| - scoped_ptr<ResourceHandler> handler(
|
| - CreateResourceHandlerForDownload(request.get(), is_content_initiated,
|
| - save_info.Pass(), started_callback));
|
| -
|
| - BeginRequestInternal(request.Pass(), handler.Pass());
|
| -
|
| - return net::OK;
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest(
|
| - net::URLRequest* request) {
|
| - ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
|
| - if (info) {
|
| - ResourceLoader* loader = GetLoader(info->GetGlobalRequestID());
|
| - if (loader)
|
| - loader->ClearLoginDelegate();
|
| - }
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::Shutdown() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - BrowserThread::PostTask(BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(&ResourceDispatcherHostImpl::OnShutdown,
|
| - base::Unretained(this)));
|
| -}
|
| -
|
| -scoped_ptr<ResourceHandler>
|
| -ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
|
| - net::URLRequest* request,
|
| - bool is_content_initiated,
|
| - scoped_ptr<DownloadSaveInfo> save_info,
|
| - const DownloadResourceHandler::OnStartedCallback& started_cb) {
|
| - scoped_ptr<ResourceHandler> handler(
|
| - new DownloadResourceHandler(request, started_cb, save_info.Pass()));
|
| - if (delegate_) {
|
| - const ResourceRequestInfo* request_info(
|
| - ResourceRequestInfo::ForRequest(request));
|
| -
|
| - ScopedVector<ResourceThrottle> throttles;
|
| - delegate_->DownloadStarting(
|
| - request, request_info->GetContext(), request_info->GetChildID(),
|
| - request_info->GetRouteID(), request_info->GetRequestID(),
|
| - is_content_initiated, &throttles);
|
| - if (!throttles.empty()) {
|
| - handler.reset(
|
| - new ThrottlingResourceHandler(
|
| - handler.Pass(), request_info->GetChildID(),
|
| - request_info->GetRequestID(), throttles.Pass()));
|
| - }
|
| - }
|
| - return handler.Pass();
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::ClearSSLClientAuthHandlerForRequest(
|
| - net::URLRequest* request) {
|
| - ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
|
| - if (info) {
|
| - ResourceLoader* loader = GetLoader(info->GetGlobalRequestID());
|
| - if (loader)
|
| - loader->ClearSSLClientAuthHandler();
|
| - }
|
| -}
|
| -
|
| -ResourceDispatcherHostLoginDelegate*
|
| -ResourceDispatcherHostImpl::CreateLoginDelegate(
|
| - ResourceLoader* loader,
|
| - net::AuthChallengeInfo* auth_info) {
|
| - if (!delegate_)
|
| - return NULL;
|
| -
|
| - return delegate_->CreateLoginDelegate(auth_info, loader->request());
|
| -}
|
| -
|
| -bool ResourceDispatcherHostImpl::AcceptAuthRequest(
|
| - ResourceLoader* loader,
|
| - net::AuthChallengeInfo* auth_info) {
|
| - if (delegate_ && !delegate_->AcceptAuthRequest(loader->request(), auth_info))
|
| - return false;
|
| -
|
| - // Prevent third-party content from prompting for login, unless it is
|
| - // a proxy that is trying to authenticate. This is often the foundation
|
| - // of a scam to extract credentials for another domain from the user.
|
| - if (!auth_info->is_proxy) {
|
| - HttpAuthResourceType resource_type =
|
| - HttpAuthResourceTypeOf(loader->request());
|
| - UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthResource",
|
| - resource_type,
|
| - HTTP_AUTH_RESOURCE_LAST);
|
| -
|
| - if (resource_type == HTTP_AUTH_RESOURCE_BLOCKED_CROSS)
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ResourceDispatcherHostImpl::AcceptSSLClientCertificateRequest(
|
| - ResourceLoader* loader,
|
| - net::SSLCertRequestInfo* cert_info) {
|
| - if (delegate_ && !delegate_->AcceptSSLClientCertificateRequest(
|
| - loader->request(), cert_info)) {
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader,
|
| - const GURL& url) {
|
| - if (!delegate_)
|
| - return false;
|
| -
|
| - ResourceRequestInfoImpl* info = loader->GetRequestInfo();
|
| -
|
| - if (!ResourceType::IsFrame(info->GetResourceType()))
|
| - return false;
|
| -
|
| - const net::URLRequestJobFactory* job_factory =
|
| - info->GetContext()->GetRequestContext()->job_factory();
|
| - if (job_factory->IsHandledURL(url))
|
| - return false;
|
| -
|
| - return delegate_->HandleExternalProtocol(url, info->GetChildID(),
|
| - info->GetRouteID());
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) {
|
| - // Make sure we have the load state monitor running
|
| - if (!update_load_states_timer_->IsRunning()) {
|
| - update_load_states_timer_->Start(FROM_HERE,
|
| - TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec),
|
| - this, &ResourceDispatcherHostImpl::UpdateLoadStates);
|
| - }
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader,
|
| - const GURL& new_url) {
|
| - ResourceRequestInfoImpl* info = loader->GetRequestInfo();
|
| -
|
| - int render_process_id, render_view_id;
|
| - if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
|
| - return;
|
| -
|
| - // Notify the observers on the UI thread.
|
| - scoped_ptr<ResourceRedirectDetails> detail(new ResourceRedirectDetails(
|
| - loader->request(),
|
| - GetCertID(loader->request(), info->GetChildID()),
|
| - new_url));
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(
|
| - &NotifyOnUI<ResourceRedirectDetails>,
|
| - static_cast<int>(NOTIFICATION_RESOURCE_RECEIVED_REDIRECT),
|
| - render_process_id, render_view_id, base::Passed(&detail)));
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
|
| - ResourceRequestInfoImpl* info = loader->GetRequestInfo();
|
| -
|
| - int render_process_id, render_view_id;
|
| - if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
|
| - return;
|
| -
|
| - // Notify the observers on the UI thread.
|
| - scoped_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails(
|
| - loader->request(),
|
| - GetCertID(loader->request(), info->GetChildID())));
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(
|
| - &NotifyOnUI<ResourceRequestDetails>,
|
| - static_cast<int>(NOTIFICATION_RESOURCE_RESPONSE_STARTED),
|
| - render_process_id, render_view_id, base::Passed(&detail)));
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
|
| - ResourceRequestInfo* info = loader->GetRequestInfo();
|
| -
|
| - // Record final result of all resource loads.
|
| - if (info->GetResourceType() == ResourceType::MAIN_FRAME) {
|
| - // This enumeration has "3" appended to its name to distinguish it from
|
| - // older versions.
|
| - UMA_HISTOGRAM_CUSTOM_ENUMERATION(
|
| - "Net.ErrorCodesForMainFrame3",
|
| - -loader->request()->status().error(),
|
| - base::CustomHistogram::ArrayToCustomRanges(
|
| - kAllNetErrorCodes, arraysize(kAllNetErrorCodes)));
|
| -
|
| - if (loader->request()->url().SchemeIsSecure() &&
|
| - loader->request()->url().host() == "www.google.com") {
|
| - UMA_HISTOGRAM_CUSTOM_ENUMERATION(
|
| - "Net.ErrorCodesForHTTPSGoogleMainFrame2",
|
| - -loader->request()->status().error(),
|
| - base::CustomHistogram::ArrayToCustomRanges(
|
| - kAllNetErrorCodes, arraysize(kAllNetErrorCodes)));
|
| - }
|
| - } else {
|
| - // This enumeration has "2" appended to distinguish it from older versions.
|
| - UMA_HISTOGRAM_CUSTOM_ENUMERATION(
|
| - "Net.ErrorCodesForSubresources2",
|
| - -loader->request()->status().error(),
|
| - base::CustomHistogram::ArrayToCustomRanges(
|
| - kAllNetErrorCodes, arraysize(kAllNetErrorCodes)));
|
| - }
|
| -
|
| - // Destroy the ResourceLoader.
|
| - RemovePendingRequest(info->GetChildID(), info->GetRequestID());
|
| -}
|
| -
|
| -// static
|
| -bool ResourceDispatcherHostImpl::RenderViewForRequest(
|
| - const net::URLRequest* request,
|
| - int* render_process_id,
|
| - int* render_view_id) {
|
| - const ResourceRequestInfoImpl* info =
|
| - ResourceRequestInfoImpl::ForRequest(request);
|
| - if (!info) {
|
| - *render_process_id = -1;
|
| - *render_view_id = -1;
|
| - return false;
|
| - }
|
| -
|
| - return info->GetAssociatedRenderView(render_process_id, render_view_id);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnShutdown() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| -
|
| - is_shutdown_ = true;
|
| - pending_loaders_.clear();
|
| -
|
| - // 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).
|
| - update_load_states_timer_.reset();
|
| -
|
| - // Clear blocked requests if any left.
|
| - // Note that we have to do this in 2 passes as we cannot call
|
| - // CancelBlockedRequestsForRoute while iterating over
|
| - // blocked_loaders_map_, as it modifies it.
|
| - std::set<ProcessRouteIDs> ids;
|
| - for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin();
|
| - iter != blocked_loaders_map_.end(); ++iter) {
|
| - std::pair<std::set<ProcessRouteIDs>::iterator, bool> result =
|
| - ids.insert(iter->first);
|
| - // We should not have duplicates.
|
| - DCHECK(result.second);
|
| - }
|
| - for (std::set<ProcessRouteIDs>::const_iterator iter = ids.begin();
|
| - iter != ids.end(); ++iter) {
|
| - CancelBlockedRequestsForRoute(iter->first, iter->second);
|
| - }
|
| -}
|
| -
|
| -bool ResourceDispatcherHostImpl::OnMessageReceived(
|
| - const IPC::Message& message,
|
| - ResourceMessageFilter* filter,
|
| - bool* message_was_ok) {
|
| - filter_ = filter;
|
| - bool handled = true;
|
| - IPC_BEGIN_MESSAGE_MAP_EX(ResourceDispatcherHostImpl, message, *message_was_ok)
|
| - IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource)
|
| - IPC_MESSAGE_HANDLER_DELAY_REPLY(ResourceHostMsg_SyncLoad, OnSyncLoad)
|
| - IPC_MESSAGE_HANDLER(ResourceHostMsg_ReleaseDownloadedFile,
|
| - OnReleaseDownloadedFile)
|
| - IPC_MESSAGE_HANDLER(ResourceHostMsg_DataReceived_ACK, OnDataReceivedACK)
|
| - IPC_MESSAGE_HANDLER(ResourceHostMsg_DataDownloaded_ACK, OnDataDownloadedACK)
|
| - IPC_MESSAGE_HANDLER(ResourceHostMsg_UploadProgress_ACK, OnUploadProgressACK)
|
| - IPC_MESSAGE_HANDLER(ResourceHostMsg_CancelRequest, OnCancelRequest)
|
| - IPC_MESSAGE_HANDLER(ResourceHostMsg_FollowRedirect, OnFollowRedirect)
|
| - IPC_MESSAGE_HANDLER(ViewHostMsg_SwapOut_ACK, OnSwapOutACK)
|
| - IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
|
| - OnDidLoadResourceFromMemoryCache)
|
| - IPC_MESSAGE_UNHANDLED(handled = false)
|
| - IPC_END_MESSAGE_MAP_EX()
|
| -
|
| - if (message.type() == ViewHostMsg_DidLoadResourceFromMemoryCache::ID) {
|
| - // We just needed to peek at this message. We still want it to reach its
|
| - // normal destination.
|
| - handled = false;
|
| - }
|
| -
|
| - filter_ = NULL;
|
| - return handled;
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnRequestResource(
|
| - const IPC::Message& message,
|
| - int request_id,
|
| - const ResourceHostMsg_Request& request_data) {
|
| - BeginRequest(request_id, request_data, NULL, message.routing_id());
|
| -}
|
| -
|
| -// Begins a resource request with the given params on behalf of the specified
|
| -// child process. Responses will be dispatched through the given receiver. The
|
| -// process ID is used to lookup WebContentsImpl from routing_id's in the case of
|
| -// a request from a renderer. request_context is the cookie/cache context to be
|
| -// used for this request.
|
| -//
|
| -// If sync_result is non-null, then a SyncLoad reply will be generated, else
|
| -// a normal asynchronous set of response messages will be generated.
|
| -void ResourceDispatcherHostImpl::OnSyncLoad(
|
| - int request_id,
|
| - const ResourceHostMsg_Request& request_data,
|
| - IPC::Message* sync_result) {
|
| - BeginRequest(request_id, request_data, sync_result,
|
| - sync_result->routing_id());
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::BeginRequest(
|
| - int request_id,
|
| - const ResourceHostMsg_Request& request_data,
|
| - IPC::Message* sync_result, // only valid for sync
|
| - int route_id) {
|
| - ProcessType process_type = filter_->process_type();
|
| - int child_id = filter_->child_id();
|
| -
|
| - // If we crash here, figure out what URL the renderer was requesting.
|
| - // http://crbug.com/91398
|
| - char url_buf[128];
|
| - base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf));
|
| - base::debug::Alias(url_buf);
|
| -
|
| - // If the request that's coming in is being transferred from another process,
|
| - // we want to reuse and resume the old loader rather than start a new one.
|
| - linked_ptr<ResourceLoader> deferred_loader;
|
| - {
|
| - LoaderMap::iterator it = pending_loaders_.find(
|
| - GlobalRequestID(request_data.transferred_request_child_id,
|
| - request_data.transferred_request_request_id));
|
| - if (it != pending_loaders_.end()) {
|
| - if (it->second->is_transferring()) {
|
| - deferred_loader = it->second;
|
| - pending_loaders_.erase(it);
|
| - } else {
|
| - RecordAction(UserMetricsAction("BadMessageTerminate_RDH"));
|
| - filter_->BadMessageReceived();
|
| - return;
|
| - }
|
| - }
|
| - }
|
| -
|
| - ResourceContext* resource_context = filter_->resource_context();
|
| - // http://crbug.com/90971
|
| - CHECK(ContainsKey(active_resource_contexts_, resource_context));
|
| -
|
| - if (is_shutdown_ ||
|
| - !ShouldServiceRequest(process_type, child_id, request_data)) {
|
| - AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id);
|
| - return;
|
| - }
|
| -
|
| - const Referrer referrer(MaybeStripReferrer(request_data.referrer),
|
| - request_data.referrer_policy);
|
| -
|
| - // Allow the observer to block/handle the request.
|
| - if (delegate_ && !delegate_->ShouldBeginRequest(child_id,
|
| - route_id,
|
| - request_data.method,
|
| - request_data.url,
|
| - request_data.resource_type,
|
| - resource_context,
|
| - referrer)) {
|
| - AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id);
|
| - return;
|
| - }
|
| -
|
| - int load_flags =
|
| - BuildLoadFlagsForRequest(request_data, child_id, sync_result != NULL);
|
| -
|
| - // Construct the request.
|
| - scoped_ptr<net::URLRequest> new_request;
|
| - net::URLRequest* request;
|
| - if (deferred_loader.get()) {
|
| - request = deferred_loader->request();
|
| -
|
| - // Give the ResourceLoader (or any of the ResourceHandlers held by it) a
|
| - // chance to reset some state before we complete the transfer.
|
| - deferred_loader->WillCompleteTransfer();
|
| - } else {
|
| - net::URLRequestContext* context =
|
| - filter_->GetURLRequestContext(request_data.resource_type);
|
| - new_request.reset(context->CreateRequest(request_data.url, NULL));
|
| - request = new_request.get();
|
| -
|
| - request->set_method(request_data.method);
|
| - request->set_first_party_for_cookies(request_data.first_party_for_cookies);
|
| - request->set_referrer(referrer.url.spec());
|
| - webkit_glue::ConfigureURLRequestForReferrerPolicy(request,
|
| - referrer.policy);
|
| - net::HttpRequestHeaders headers;
|
| - headers.AddHeadersFromString(request_data.headers);
|
| - request->SetExtraRequestHeaders(headers);
|
| - }
|
| -
|
| - // TODO(darin): Do we really need all of these URLRequest setters in the
|
| - // transferred navigation case?
|
| -
|
| - request->set_load_flags(load_flags);
|
| -
|
| - request->set_priority(DetermineRequestPriority(request_data.resource_type));
|
| -
|
| - // Resolve elements from request_body and prepare upload data.
|
| - if (request_data.request_body) {
|
| - request->set_upload(
|
| - request_data.request_body->ResolveElementsAndCreateUploadData(
|
| - filter_->blob_storage_context()->controller()));
|
| - }
|
| -
|
| - bool allow_download = request_data.allow_download &&
|
| - ResourceType::IsFrame(request_data.resource_type);
|
| -
|
| - // Make extra info and read footer (contains request ID).
|
| - ResourceRequestInfoImpl* extra_info =
|
| - new ResourceRequestInfoImpl(
|
| - process_type,
|
| - child_id,
|
| - route_id,
|
| - request_data.origin_pid,
|
| - request_id,
|
| - request_data.is_main_frame,
|
| - request_data.frame_id,
|
| - request_data.parent_is_main_frame,
|
| - request_data.parent_frame_id,
|
| - request_data.resource_type,
|
| - request_data.transition_type,
|
| - false, // is download
|
| - allow_download,
|
| - request_data.has_user_gesture,
|
| - request_data.referrer_policy,
|
| - resource_context);
|
| - extra_info->AssociateWithRequest(request); // Request takes ownership.
|
| -
|
| - if (request->url().SchemeIs(chrome::kBlobScheme)) {
|
| - // Hang on to a reference to ensure the blob is not released prior
|
| - // to the job being started.
|
| - extra_info->set_requested_blob_data(
|
| - filter_->blob_storage_context()->controller()->
|
| - GetBlobDataFromUrl(request->url()));
|
| - }
|
| -
|
| - // Have the appcache associate its extra info with the request.
|
| - appcache::AppCacheInterceptor::SetExtraRequestInfo(
|
| - request, filter_->appcache_service(), child_id,
|
| - request_data.appcache_host_id, request_data.resource_type);
|
| -
|
| - // Construct the IPC resource handler.
|
| - scoped_ptr<ResourceHandler> handler;
|
| - if (sync_result) {
|
| - handler.reset(new SyncResourceHandler(
|
| - filter_, request, sync_result, this));
|
| - } else {
|
| - handler.reset(new AsyncResourceHandler(
|
| - filter_, route_id, request, this));
|
| - }
|
| -
|
| - // The RedirectToFileResourceHandler depends on being next in the chain.
|
| - if (request_data.download_to_file) {
|
| - handler.reset(
|
| - new RedirectToFileResourceHandler(handler.Pass(), child_id, this));
|
| - }
|
| -
|
| - // Install a CrossSiteResourceHandler if this request is coming from a
|
| - // RenderViewHost with a pending cross-site request. We only check this for
|
| - // MAIN_FRAME requests. Unblock requests only come from a blocked page, do
|
| - // not count as cross-site, otherwise it gets blocked indefinitely.
|
| - if (request_data.resource_type == ResourceType::MAIN_FRAME &&
|
| - process_type == PROCESS_TYPE_RENDERER &&
|
| - CrossSiteRequestManager::GetInstance()->
|
| - HasPendingCrossSiteRequest(child_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.reset(new CrossSiteResourceHandler(handler.Pass(), child_id,
|
| - route_id, request));
|
| - }
|
| -
|
| - // Insert a buffered event handler before the actual one.
|
| - handler.reset(
|
| - new BufferedResourceHandler(handler.Pass(), this, request));
|
| -
|
| - ScopedVector<ResourceThrottle> throttles;
|
| - if (delegate_) {
|
| - bool is_continuation_of_transferred_request =
|
| - (deferred_loader.get() != NULL);
|
| -
|
| - delegate_->RequestBeginning(request,
|
| - resource_context,
|
| - filter_->appcache_service(),
|
| - request_data.resource_type,
|
| - child_id,
|
| - route_id,
|
| - is_continuation_of_transferred_request,
|
| - &throttles);
|
| - }
|
| -
|
| - if (request_data.resource_type == ResourceType::MAIN_FRAME) {
|
| - throttles.insert(
|
| - throttles.begin(),
|
| - new TransferNavigationResourceThrottle(request));
|
| - }
|
| -
|
| - if (!throttles.empty()) {
|
| - handler.reset(
|
| - new ThrottlingResourceHandler(handler.Pass(), child_id, request_id,
|
| - throttles.Pass()));
|
| - }
|
| -
|
| - if (deferred_loader.get()) {
|
| - pending_loaders_[extra_info->GetGlobalRequestID()] = deferred_loader;
|
| - deferred_loader->CompleteTransfer(handler.Pass());
|
| - } else {
|
| - BeginRequestInternal(new_request.Pass(), handler.Pass());
|
| - }
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) {
|
| - UnregisterDownloadedTempFile(filter_->child_id(), request_id);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnDataReceivedACK(int request_id) {
|
| - ResourceLoader* loader = GetLoader(filter_->child_id(), request_id);
|
| - if (!loader)
|
| - return;
|
| -
|
| - ResourceRequestInfoImpl* info = loader->GetRequestInfo();
|
| - if (info->async_handler())
|
| - info->async_handler()->OnDataReceivedACK();
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) {
|
| - // TODO(michaeln): maybe throttle DataDownloaded messages
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::RegisterDownloadedTempFile(
|
| - int child_id, int request_id, ShareableFileReference* reference) {
|
| - registered_temp_files_[child_id][request_id] = reference;
|
| - ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
|
| - child_id, reference->path());
|
| -
|
| - // When the temp file is deleted, revoke permissions that the renderer has
|
| - // to that file. This covers an edge case where the file is deleted and then
|
| - // the same name is re-used for some other purpose, we don't want the old
|
| - // renderer to still have access to it.
|
| - //
|
| - // We do this when the file is deleted because the renderer can take a blob
|
| - // reference to the temp file that outlives the url loaded that it was
|
| - // loaded with to keep the file (and permissions) alive.
|
| - reference->AddFinalReleaseCallback(
|
| - base::Bind(&RemoveDownloadFileFromChildSecurityPolicy,
|
| - child_id));
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::UnregisterDownloadedTempFile(
|
| - int child_id, int request_id) {
|
| - DeletableFilesMap& map = registered_temp_files_[child_id];
|
| - DeletableFilesMap::iterator found = map.find(request_id);
|
| - if (found == map.end())
|
| - return;
|
| -
|
| - map.erase(found);
|
| -
|
| - // Note that we don't remove the security bits here. This will be done
|
| - // when all file refs are deleted (see RegisterDownloadedTempFile).
|
| -}
|
| -
|
| -bool ResourceDispatcherHostImpl::Send(IPC::Message* message) {
|
| - delete message;
|
| - return false;
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnUploadProgressACK(int request_id) {
|
| - ResourceLoader* loader = GetLoader(filter_->child_id(), request_id);
|
| - if (loader)
|
| - loader->OnUploadProgressACK();
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnCancelRequest(int request_id) {
|
| - CancelRequest(filter_->child_id(), request_id, true);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnFollowRedirect(
|
| - int request_id,
|
| - bool has_new_first_party_for_cookies,
|
| - const GURL& new_first_party_for_cookies) {
|
| - ResourceLoader* loader = GetLoader(filter_->child_id(), request_id);
|
| - if (!loader) {
|
| - DVLOG(1) << "OnFollowRedirect for invalid request";
|
| - return;
|
| - }
|
| -
|
| - ResourceRequestInfoImpl* info = loader->GetRequestInfo();
|
| - if (info->async_handler()) {
|
| - info->async_handler()->OnFollowRedirect(
|
| - has_new_first_party_for_cookies,
|
| - new_first_party_for_cookies);
|
| - }
|
| -}
|
| -
|
| -ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
|
| - int child_id,
|
| - int route_id,
|
| - bool download,
|
| - ResourceContext* context) {
|
| - return new ResourceRequestInfoImpl(
|
| - PROCESS_TYPE_RENDERER,
|
| - child_id,
|
| - route_id,
|
| - 0,
|
| - request_id_,
|
| - false, // is_main_frame
|
| - -1, // frame_id
|
| - false, // parent_is_main_frame
|
| - -1, // parent_frame_id
|
| - ResourceType::SUB_RESOURCE,
|
| - PAGE_TRANSITION_LINK,
|
| - download, // is_download
|
| - download, // allow_download
|
| - false, // has_user_gesture
|
| - WebKit::WebReferrerPolicyDefault,
|
| - context);
|
| -}
|
| -
|
| -
|
| -void ResourceDispatcherHostImpl::OnSwapOutACK(
|
| - const ViewMsg_SwapOut_Params& params) {
|
| - HandleSwapOutACK(params, false);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnSimulateSwapOutACK(
|
| - const ViewMsg_SwapOut_Params& params) {
|
| - // Call the real implementation with true, which means that we timed out.
|
| - HandleSwapOutACK(params, true);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::HandleSwapOutACK(
|
| - const ViewMsg_SwapOut_Params& params, bool timed_out) {
|
| - // Closes for cross-site transitions are handled such that the cross-site
|
| - // transition continues.
|
| - ResourceLoader* loader = GetLoader(params.new_render_process_host_id,
|
| - params.new_request_id);
|
| - if (loader) {
|
| - // The response we were meant to resume could have already been canceled.
|
| - ResourceRequestInfoImpl* info = loader->GetRequestInfo();
|
| - if (info->cross_site_handler())
|
| - info->cross_site_handler()->ResumeResponse();
|
| - }
|
| -
|
| - // Update the RenderViewHost's internal state after the ACK.
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI,
|
| - FROM_HERE,
|
| - base::Bind(&OnSwapOutACKHelper,
|
| - params.closing_process_id,
|
| - params.closing_route_id,
|
| - timed_out));
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnDidLoadResourceFromMemoryCache(
|
| - const GURL& url,
|
| - const std::string& security_info,
|
| - const std::string& http_method,
|
| - const std::string& mime_type,
|
| - ResourceType::Type resource_type) {
|
| - if (!url.is_valid() || !(url.SchemeIs("http") || url.SchemeIs("https")))
|
| - return;
|
| -
|
| - filter_->GetURLRequestContext(resource_type)->http_transaction_factory()->
|
| - GetCache()->OnExternalCacheHit(url, http_method);
|
| -}
|
| -
|
| -// This function is only used for saving feature.
|
| -void ResourceDispatcherHostImpl::BeginSaveFile(
|
| - const GURL& url,
|
| - const Referrer& referrer,
|
| - int child_id,
|
| - int route_id,
|
| - ResourceContext* context) {
|
| - if (is_shutdown_)
|
| - return;
|
| -
|
| - // http://crbug.com/90971
|
| - char url_buf[128];
|
| - base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf));
|
| - base::debug::Alias(url_buf);
|
| - CHECK(ContainsKey(active_resource_contexts_, context));
|
| -
|
| - scoped_ptr<ResourceHandler> handler(
|
| - new SaveFileResourceHandler(child_id,
|
| - route_id,
|
| - url,
|
| - save_file_manager_.get()));
|
| - request_id_--;
|
| -
|
| - const net::URLRequestContext* request_context = context->GetRequestContext();
|
| - bool known_proto =
|
| - request_context->job_factory()->IsHandledURL(url);
|
| - if (!known_proto) {
|
| - // Since any URLs which have non-standard scheme have been filtered
|
| - // by save manager(see GURL::SchemeIsStandard). This situation
|
| - // should not happen.
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - scoped_ptr<net::URLRequest> request(
|
| - request_context->CreateRequest(url, NULL));
|
| - request->set_method("GET");
|
| - request->set_referrer(MaybeStripReferrer(referrer.url).spec());
|
| - webkit_glue::ConfigureURLRequestForReferrerPolicy(request.get(),
|
| - referrer.policy);
|
| - // So far, for saving page, we need fetch content from cache, in the
|
| - // future, maybe we can use a configuration to configure this behavior.
|
| - request->set_load_flags(net::LOAD_PREFERRING_CACHE);
|
| -
|
| - // Since we're just saving some resources we need, disallow downloading.
|
| - ResourceRequestInfoImpl* extra_info =
|
| - CreateRequestInfo(child_id, route_id, false, context);
|
| - extra_info->AssociateWithRequest(request.get()); // Request takes ownership.
|
| -
|
| - BeginRequestInternal(request.Pass(), handler.Pass());
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::MarkAsTransferredNavigation(
|
| - const GlobalRequestID& id) {
|
| - GetLoader(id)->MarkAsTransferring();
|
| -}
|
| -
|
| -int ResourceDispatcherHostImpl::GetOutstandingRequestsMemoryCost(
|
| - int child_id) const {
|
| - OutstandingRequestsMemoryCostMap::const_iterator entry =
|
| - outstanding_requests_memory_cost_map_.find(child_id);
|
| - return (entry == outstanding_requests_memory_cost_map_.end()) ?
|
| - 0 : entry->second;
|
| -}
|
| -
|
| -// 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 ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) {
|
| - CancelRequestsForRoute(child_id, -1 /* cancel all */);
|
| - registered_temp_files_.erase(child_id);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::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> matching_requests;
|
| - for (LoaderMap::const_iterator i = pending_loaders_.begin();
|
| - i != pending_loaders_.end(); ++i) {
|
| - if (i->first.child_id != child_id)
|
| - continue;
|
| -
|
| - ResourceRequestInfoImpl* info = i->second->GetRequestInfo();
|
| -
|
| - GlobalRequestID id(child_id, i->first.request_id);
|
| - DCHECK(id == i->first);
|
| -
|
| - // Don't cancel navigations that are transferring to another process,
|
| - // since they belong to another process now.
|
| - if (!info->is_download() && !IsTransferredNavigation(id) &&
|
| - (route_id == -1 || route_id == info->GetRouteID())) {
|
| - matching_requests.push_back(id);
|
| - }
|
| - }
|
| -
|
| - // Remove matches.
|
| - for (size_t i = 0; i < matching_requests.size(); ++i) {
|
| - LoaderMap::iterator iter = pending_loaders_.find(matching_requests[i]);
|
| - // Although every matching request was in pending_requests_ when we built
|
| - // matching_requests, it is normal for a matching request to be not found
|
| - // in pending_requests_ after we have removed some matching requests from
|
| - // pending_requests_. For example, deleting a net::URLRequest that has
|
| - // exclusive (write) access to an HTTP cache entry may unblock another
|
| - // net::URLRequest that needs exclusive access to the same cache entry, and
|
| - // that net::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_loaders_.end())
|
| - RemovePendingLoader(iter);
|
| - }
|
| -
|
| - // Now deal with blocked requests if any.
|
| - if (route_id != -1) {
|
| - if (blocked_loaders_map_.find(ProcessRouteIDs(child_id, route_id)) !=
|
| - blocked_loaders_map_.end()) {
|
| - CancelBlockedRequestsForRoute(child_id, route_id);
|
| - }
|
| - } else {
|
| - // We have to do all render views for the process |child_id|.
|
| - // Note that we have to do this in 2 passes as we cannot call
|
| - // CancelBlockedRequestsForRoute while iterating over
|
| - // blocked_loaders_map_, as it modifies it.
|
| - std::set<int> route_ids;
|
| - for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin();
|
| - iter != blocked_loaders_map_.end(); ++iter) {
|
| - if (iter->first.first == child_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);
|
| - }
|
| - }
|
| -}
|
| -
|
| -// Cancels the request and removes it from the list.
|
| -void ResourceDispatcherHostImpl::RemovePendingRequest(int child_id,
|
| - int request_id) {
|
| - LoaderMap::iterator i = pending_loaders_.find(
|
| - GlobalRequestID(child_id, request_id));
|
| - if (i == pending_loaders_.end()) {
|
| - NOTREACHED() << "Trying to remove a request that's not here";
|
| - return;
|
| - }
|
| - RemovePendingLoader(i);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::RemovePendingLoader(
|
| - const LoaderMap::iterator& iter) {
|
| - ResourceRequestInfoImpl* info = iter->second->GetRequestInfo();
|
| -
|
| - // Remove the memory credit that we added when pushing the request onto
|
| - // the pending list.
|
| - IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(),
|
| - info->GetChildID());
|
| -
|
| - pending_loaders_.erase(iter);
|
| -
|
| - // If we have no more pending requests, then stop the load state monitor
|
| - if (pending_loaders_.empty() && update_load_states_timer_.get())
|
| - update_load_states_timer_->Stop();
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::CancelRequest(int child_id,
|
| - int request_id,
|
| - bool from_renderer) {
|
| - if (from_renderer) {
|
| - // When the old renderer dies, it sends a message to us to cancel its
|
| - // requests.
|
| - if (IsTransferredNavigation(GlobalRequestID(child_id, request_id)))
|
| - return;
|
| - }
|
| -
|
| - ResourceLoader* loader = GetLoader(child_id, request_id);
|
| - if (!loader) {
|
| - // 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.
|
| - DVLOG(1) << "Canceling a request that wasn't found";
|
| - return;
|
| - }
|
| -
|
| - loader->CancelRequest(from_renderer);
|
| -}
|
| -
|
| -int ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemoryCost(
|
| - int cost,
|
| - int child_id) {
|
| - // Retrieve the previous value (defaulting to 0 if not found).
|
| - OutstandingRequestsMemoryCostMap::iterator prev_entry =
|
| - outstanding_requests_memory_cost_map_.find(child_id);
|
| - int new_cost = 0;
|
| - if (prev_entry != outstanding_requests_memory_cost_map_.end())
|
| - new_cost = prev_entry->second;
|
| -
|
| - // Insert/update the total; delete entries when their value reaches 0.
|
| - new_cost += cost;
|
| - CHECK(new_cost >= 0);
|
| - if (new_cost == 0)
|
| - outstanding_requests_memory_cost_map_.erase(child_id);
|
| - else
|
| - outstanding_requests_memory_cost_map_[child_id] = new_cost;
|
| -
|
| - return new_cost;
|
| -}
|
| -
|
| -// static
|
| -int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
|
| - net::URLRequest* request) {
|
| - // The following fields should be a minor size contribution (experimentally
|
| - // on the order of 100). However since they are variable length, it could
|
| - // in theory be a sizeable contribution.
|
| - int strings_cost = request->extra_request_headers().ToString().size() +
|
| - request->original_url().spec().size() +
|
| - request->referrer().size() +
|
| - request->method().size();
|
| -
|
| - // Note that this expression will typically be dominated by:
|
| - // |kAvgBytesPerOutstandingRequest|.
|
| - return kAvgBytesPerOutstandingRequest + strings_cost;
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::BeginRequestInternal(
|
| - scoped_ptr<net::URLRequest> request,
|
| - scoped_ptr<ResourceHandler> handler) {
|
| - DCHECK(!request->is_pending());
|
| - ResourceRequestInfoImpl* info =
|
| - ResourceRequestInfoImpl::ForRequest(request.get());
|
| -
|
| - if ((TimeTicks::Now() - last_user_gesture_time_) <
|
| - TimeDelta::FromMilliseconds(kUserGestureWindowMs)) {
|
| - request->set_load_flags(
|
| - request->load_flags() | net::LOAD_MAYBE_USER_GESTURE);
|
| - }
|
| -
|
| - // Add the memory estimate that starting this request will consume.
|
| - info->set_memory_cost(CalculateApproximateMemoryCost(request.get()));
|
| - int memory_cost = IncrementOutstandingRequestsMemoryCost(info->memory_cost(),
|
| - info->GetChildID());
|
| -
|
| - // If enqueing/starting this request will exceed our per-process memory
|
| - // bound, abort it right away.
|
| - if (memory_cost > max_outstanding_requests_cost_per_process_) {
|
| - // We call "CancelWithError()" as a way of setting the net::URLRequest's
|
| - // status -- it has no effect beyond this, since the request hasn't started.
|
| - request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
|
| -
|
| - if (!handler->OnResponseCompleted(info->GetRequestID(), request->status(),
|
| - std::string())) {
|
| - // TODO(darin): The handler is not ready for us to kill the request. Oops!
|
| - NOTREACHED();
|
| - }
|
| -
|
| - IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(),
|
| - info->GetChildID());
|
| -
|
| - // A ResourceHandler must not outlive its associated URLRequest.
|
| - handler.reset();
|
| - return;
|
| - }
|
| -
|
| - linked_ptr<ResourceLoader> loader(
|
| - new ResourceLoader(request.Pass(), handler.Pass(), this));
|
| -
|
| - ProcessRouteIDs pair_id(info->GetChildID(), info->GetRouteID());
|
| - BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(pair_id);
|
| - if (iter != blocked_loaders_map_.end()) {
|
| - // The request should be blocked.
|
| - iter->second->push_back(loader);
|
| - return;
|
| - }
|
| -
|
| - StartLoading(info, loader);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::StartLoading(
|
| - ResourceRequestInfoImpl* info,
|
| - const linked_ptr<ResourceLoader>& loader) {
|
| - pending_loaders_[info->GetGlobalRequestID()] = loader;
|
| -
|
| - loader->StartRequest();
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::OnUserGesture(WebContentsImpl* contents) {
|
| - last_user_gesture_time_ = TimeTicks::Now();
|
| -}
|
| -
|
| -net::URLRequest* ResourceDispatcherHostImpl::GetURLRequest(
|
| - const GlobalRequestID& id) {
|
| - ResourceLoader* loader = GetLoader(id);
|
| - if (!loader)
|
| - return NULL;
|
| -
|
| - return loader->request();
|
| -}
|
| -
|
| -namespace {
|
| -
|
| -// This function attempts to return the "more interesting" load state of |a|
|
| -// and |b|. We don't have temporal information about these load states
|
| -// (meaning we don't know when we transitioned into these states), so we just
|
| -// rank them according to how "interesting" the states are.
|
| -//
|
| -// We take advantage of the fact that the load states are an enumeration listed
|
| -// in the order in which they occur during the lifetime of a request, so we can
|
| -// regard states with larger numeric values as being further along toward
|
| -// completion. We regard those states as more interesting to report since they
|
| -// represent progress.
|
| -//
|
| -// For example, by this measure "tranferring data" is a more interesting state
|
| -// than "resolving host" because when we are transferring data we are actually
|
| -// doing something that corresponds to changes that the user might observe,
|
| -// whereas waiting for a host name to resolve implies being stuck.
|
| -//
|
| -const net::LoadStateWithParam& MoreInterestingLoadState(
|
| - const net::LoadStateWithParam& a, const net::LoadStateWithParam& b) {
|
| - return (a.state < b.state) ? b : a;
|
| -}
|
| -
|
| -// Carries information about a load state change.
|
| -struct LoadInfo {
|
| - GURL url;
|
| - net::LoadStateWithParam load_state;
|
| - uint64 upload_position;
|
| - uint64 upload_size;
|
| -};
|
| -
|
| -// Map from ProcessID+ViewID pair to LoadState
|
| -typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap;
|
| -
|
| -// Used to marshal calls to LoadStateChanged from the IO to UI threads. We do
|
| -// them all as a single callback to avoid spamming the UI thread.
|
| -void LoadInfoUpdateCallback(const LoadInfoMap& info_map) {
|
| - LoadInfoMap::const_iterator i;
|
| - for (i = info_map.begin(); i != info_map.end(); ++i) {
|
| - RenderViewHostImpl* view =
|
| - RenderViewHostImpl::FromID(i->first.first, i->first.second);
|
| - if (view) // The view could be gone at this point.
|
| - view->LoadStateChanged(i->second.url, i->second.load_state,
|
| - i->second.upload_position,
|
| - i->second.upload_size);
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -void ResourceDispatcherHostImpl::UpdateLoadStates() {
|
| - // Populate this map with load state changes, and then send them on to the UI
|
| - // thread where they can be passed along to the respective RVHs.
|
| - LoadInfoMap info_map;
|
| -
|
| - LoaderMap::const_iterator i;
|
| -
|
| - // Determine the largest upload size of all requests
|
| - // in each View (good chance it's zero).
|
| - std::map<std::pair<int, int>, uint64> largest_upload_size;
|
| - for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) {
|
| - net::URLRequest* request = i->second->request();
|
| - ResourceRequestInfoImpl* info = i->second->GetRequestInfo();
|
| - uint64 upload_size = request->GetUploadProgress().size();
|
| - if (request->GetLoadState().state != net::LOAD_STATE_SENDING_REQUEST)
|
| - upload_size = 0;
|
| - std::pair<int, int> key(info->GetChildID(), info->GetRouteID());
|
| - if (upload_size && largest_upload_size[key] < upload_size)
|
| - largest_upload_size[key] = upload_size;
|
| - }
|
| -
|
| - for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) {
|
| - net::URLRequest* request = i->second->request();
|
| - ResourceRequestInfoImpl* info = i->second->GetRequestInfo();
|
| - net::LoadStateWithParam load_state = request->GetLoadState();
|
| - net::UploadProgress progress = request->GetUploadProgress();
|
| -
|
| - // We also poll for upload progress on this timer and send upload
|
| - // progress ipc messages to the plugin process.
|
| - i->second->ReportUploadProgress();
|
| -
|
| - std::pair<int, int> key(info->GetChildID(), info->GetRouteID());
|
| -
|
| - // If a request is uploading data, ignore all other requests so that the
|
| - // upload progress takes priority for being shown in the status bar.
|
| - if (largest_upload_size.find(key) != largest_upload_size.end() &&
|
| - progress.size() < largest_upload_size[key])
|
| - continue;
|
| -
|
| - net::LoadStateWithParam to_insert = load_state;
|
| - LoadInfoMap::iterator existing = info_map.find(key);
|
| - if (existing != info_map.end()) {
|
| - to_insert =
|
| - MoreInterestingLoadState(existing->second.load_state, load_state);
|
| - if (to_insert.state == existing->second.load_state.state)
|
| - continue;
|
| - }
|
| - LoadInfo& load_info = info_map[key];
|
| - load_info.url = request->url();
|
| - load_info.load_state = to_insert;
|
| - load_info.upload_size = progress.size();
|
| - load_info.upload_position = progress.position();
|
| - }
|
| -
|
| - if (info_map.empty())
|
| - return;
|
| -
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&LoadInfoUpdateCallback, info_map));
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id,
|
| - int route_id) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - ProcessRouteIDs key(child_id, route_id);
|
| - DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) <<
|
| - "BlockRequestsForRoute called multiple time for the same RVH";
|
| - blocked_loaders_map_[key] = new BlockedLoadersList();
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(int child_id,
|
| - int route_id) {
|
| - ProcessBlockedRequestsForRoute(child_id, route_id, false);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(int child_id,
|
| - int route_id) {
|
| - ProcessBlockedRequestsForRoute(child_id, route_id, true);
|
| -}
|
| -
|
| -void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute(
|
| - int child_id,
|
| - int route_id,
|
| - bool cancel_requests) {
|
| - BlockedLoadersMap::iterator iter = blocked_loaders_map_.find(
|
| - std::pair<int, int>(child_id, route_id));
|
| - if (iter == blocked_loaders_map_.end()) {
|
| - // It's possible to reach here if the renderer crashed while an interstitial
|
| - // page was showing.
|
| - return;
|
| - }
|
| -
|
| - BlockedLoadersList* loaders = iter->second;
|
| -
|
| - // Removing the vector from the map unblocks any subsequent requests.
|
| - blocked_loaders_map_.erase(iter);
|
| -
|
| - for (BlockedLoadersList::iterator loaders_iter = loaders->begin();
|
| - loaders_iter != loaders->end(); ++loaders_iter) {
|
| - linked_ptr<ResourceLoader> loader = *loaders_iter;
|
| - ResourceRequestInfoImpl* info = loader->GetRequestInfo();
|
| - if (cancel_requests) {
|
| - IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(),
|
| - info->GetChildID());
|
| - } else {
|
| - StartLoading(info, loader);
|
| - }
|
| - }
|
| -
|
| - delete loaders;
|
| -}
|
| -
|
| -ResourceDispatcherHostImpl::HttpAuthResourceType
|
| -ResourceDispatcherHostImpl::HttpAuthResourceTypeOf(net::URLRequest* request) {
|
| - // Use the same critera as for cookies to determine the sub-resource type
|
| - // that is requesting to be authenticated.
|
| - if (!request->first_party_for_cookies().is_valid())
|
| - return HTTP_AUTH_RESOURCE_TOP;
|
| -
|
| - if (net::RegistryControlledDomainService::SameDomainOrHost(
|
| - request->first_party_for_cookies(), request->url()))
|
| - return HTTP_AUTH_RESOURCE_SAME_DOMAIN;
|
| -
|
| - if (allow_cross_origin_auth_prompt())
|
| - return HTTP_AUTH_RESOURCE_ALLOWED_CROSS;
|
| -
|
| - return HTTP_AUTH_RESOURCE_BLOCKED_CROSS;
|
| -}
|
| -
|
| -bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() {
|
| - return allow_cross_origin_auth_prompt_;
|
| -}
|
| -
|
| -bool ResourceDispatcherHostImpl::IsTransferredNavigation(
|
| - const GlobalRequestID& id) const {
|
| - ResourceLoader* loader = GetLoader(id);
|
| - return loader ? loader->is_transferring() : false;
|
| -}
|
| -
|
| -ResourceLoader* ResourceDispatcherHostImpl::GetLoader(
|
| - const GlobalRequestID& id) const {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| -
|
| - LoaderMap::const_iterator i = pending_loaders_.find(id);
|
| - if (i == pending_loaders_.end())
|
| - return NULL;
|
| -
|
| - return i->second.get();
|
| -}
|
| -
|
| -ResourceLoader* ResourceDispatcherHostImpl::GetLoader(int child_id,
|
| - int request_id) const {
|
| - return GetLoader(GlobalRequestID(child_id, request_id));
|
| -}
|
| -
|
| -} // namespace content
|
|
|