1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading 6 7#include "content/browser/loader/resource_dispatcher_host_impl.h" 8 9#include <algorithm> 10#include <set> 11#include <vector> 12 13#include "base/bind.h" 14#include "base/bind_helpers.h" 15#include "base/command_line.h" 16#include "base/compiler_specific.h" 17#include "base/debug/alias.h" 18#include "base/logging.h" 19#include "base/memory/scoped_ptr.h" 20#include "base/memory/shared_memory.h" 21#include "base/message_loop/message_loop.h" 22#include "base/metrics/histogram.h" 23#include "base/metrics/sparse_histogram.h" 24#include "base/stl_util.h" 25#include "base/third_party/dynamic_annotations/dynamic_annotations.h" 26#include "content/browser/appcache/appcache_interceptor.h" 27#include "content/browser/appcache/chrome_appcache_service.h" 28#include "content/browser/cert_store_impl.h" 29#include "content/browser/child_process_security_policy_impl.h" 30#include "content/browser/download/download_resource_handler.h" 31#include "content/browser/download/save_file_manager.h" 32#include "content/browser/download/save_file_resource_handler.h" 33#include "content/browser/fileapi/chrome_blob_storage_context.h" 34#include "content/browser/frame_host/navigation_request_info.h" 35#include "content/browser/loader/async_resource_handler.h" 36#include "content/browser/loader/buffered_resource_handler.h" 37#include "content/browser/loader/cross_site_resource_handler.h" 38#include "content/browser/loader/detachable_resource_handler.h" 39#include "content/browser/loader/power_save_block_resource_throttle.h" 40#include "content/browser/loader/redirect_to_file_resource_handler.h" 41#include "content/browser/loader/resource_message_filter.h" 42#include "content/browser/loader/resource_request_info_impl.h" 43#include "content/browser/loader/stream_resource_handler.h" 44#include "content/browser/loader/sync_resource_handler.h" 45#include "content/browser/loader/throttling_resource_handler.h" 46#include "content/browser/loader/upload_data_stream_builder.h" 47#include "content/browser/renderer_host/render_view_host_delegate.h" 48#include "content/browser/renderer_host/render_view_host_impl.h" 49#include "content/browser/resource_context_impl.h" 50#include "content/browser/service_worker/service_worker_request_handler.h" 51#include "content/browser/streams/stream.h" 52#include "content/browser/streams/stream_context.h" 53#include "content/browser/streams/stream_registry.h" 54#include "content/browser/web_contents/web_contents_impl.h" 55#include "content/common/appcache_interfaces.h" 56#include "content/common/resource_messages.h" 57#include "content/common/ssl_status_serialization.h" 58#include "content/common/view_messages.h" 59#include "content/public/browser/browser_thread.h" 60#include "content/public/browser/content_browser_client.h" 61#include "content/public/browser/download_manager.h" 62#include "content/public/browser/download_url_parameters.h" 63#include "content/public/browser/global_request_id.h" 64#include "content/public/browser/resource_dispatcher_host_delegate.h" 65#include "content/public/browser/resource_request_details.h" 66#include "content/public/browser/resource_throttle.h" 67#include "content/public/browser/stream_handle.h" 68#include "content/public/browser/user_metrics.h" 69#include "content/public/common/content_switches.h" 70#include "content/public/common/process_type.h" 71#include "ipc/ipc_message_macros.h" 72#include "ipc/ipc_message_start.h" 73#include "net/base/auth.h" 74#include "net/base/load_flags.h" 75#include "net/base/mime_util.h" 76#include "net/base/net_errors.h" 77#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 78#include "net/base/request_priority.h" 79#include "net/base/upload_data_stream.h" 80#include "net/cert/cert_status_flags.h" 81#include "net/cookies/cookie_monster.h" 82#include "net/http/http_response_headers.h" 83#include "net/http/http_response_info.h" 84#include "net/ssl/ssl_cert_request_info.h" 85#include "net/url_request/url_request.h" 86#include "net/url_request/url_request_context.h" 87#include "net/url_request/url_request_job_factory.h" 88#include "storage/browser/blob/blob_data_handle.h" 89#include "storage/browser/blob/blob_storage_context.h" 90#include "storage/browser/blob/blob_url_request_job_factory.h" 91#include "storage/browser/fileapi/file_permission_policy.h" 92#include "storage/browser/fileapi/file_system_context.h" 93#include "storage/common/blob/blob_data.h" 94#include "storage/common/blob/shareable_file_reference.h" 95#include "url/url_constants.h" 96 97#if defined(ENABLE_PLUGINS) 98#include "content/browser/plugin_service_impl.h" 99#endif 100 101using base::Time; 102using base::TimeDelta; 103using base::TimeTicks; 104using storage::ShareableFileReference; 105 106// ---------------------------------------------------------------------------- 107 108namespace content { 109 110namespace { 111 112static ResourceDispatcherHostImpl* g_resource_dispatcher_host; 113 114// The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates 115const int kUpdateLoadStatesIntervalMsec = 100; 116 117// Maximum byte "cost" of all the outstanding requests for a renderer. 118// See delcaration of |max_outstanding_requests_cost_per_process_| for details. 119// This bound is 25MB, which allows for around 6000 outstanding requests. 120const int kMaxOutstandingRequestsCostPerProcess = 26214400; 121 122// The number of milliseconds after noting a user gesture that we will 123// tag newly-created URLRequest objects with the 124// net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary 125// guess at how long to expect direct impact from a user gesture, but 126// this should be OK as the load flag is a best-effort thing only, 127// rather than being intended as fully accurate. 128const int kUserGestureWindowMs = 3500; 129 130// Ratio of |max_num_in_flight_requests_| that any one renderer is allowed to 131// use. Arbitrarily chosen. 132const double kMaxRequestsPerProcessRatio = 0.45; 133 134// TODO(jkarlin): The value is high to reduce the chance of the detachable 135// request timing out, forcing a blocked second request to open a new connection 136// and start over. Reduce this value once we have a better idea of what it 137// should be and once we stop blocking multiple simultaneous requests for the 138// same resource (see bugs 46104 and 31014). 139const int kDefaultDetachableCancelDelayMs = 30000; 140 141enum SHA1HistogramTypes { 142 // SHA-1 is not present in the certificate chain. 143 SHA1_NOT_PRESENT = 0, 144 // SHA-1 is present in the certificate chain, and the leaf expires on or 145 // after January 1, 2017. 146 SHA1_EXPIRES_AFTER_JANUARY_2017 = 1, 147 // SHA-1 is present in the certificate chain, and the leaf expires on or 148 // after June 1, 2016. 149 SHA1_EXPIRES_AFTER_JUNE_2016 = 2, 150 // SHA-1 is present in the certificate chain, and the leaf expires on or 151 // after January 1, 2016. 152 SHA1_EXPIRES_AFTER_JANUARY_2016 = 3, 153 // SHA-1 is present in the certificate chain, but the leaf expires before 154 // January 1, 2016 155 SHA1_PRESENT = 4, 156 // Always keep this at the end. 157 SHA1_HISTOGRAM_TYPES_MAX, 158}; 159 160void RecordCertificateHistograms(const net::SSLInfo& ssl_info, 161 ResourceType resource_type) { 162 // The internal representation of the dates for UI treatment of SHA-1. 163 // See http://crbug.com/401365 for details 164 static const int64_t kJanuary2017 = INT64_C(13127702400000000); 165 static const int64_t kJune2016 = INT64_C(13109213000000000); 166 static const int64_t kJanuary2016 = INT64_C(13096080000000000); 167 168 SHA1HistogramTypes sha1_histogram = SHA1_NOT_PRESENT; 169 if (ssl_info.cert_status & net::CERT_STATUS_SHA1_SIGNATURE_PRESENT) { 170 DCHECK(ssl_info.cert.get()); 171 if (ssl_info.cert->valid_expiry() >= 172 base::Time::FromInternalValue(kJanuary2017)) { 173 sha1_histogram = SHA1_EXPIRES_AFTER_JANUARY_2017; 174 } else if (ssl_info.cert->valid_expiry() >= 175 base::Time::FromInternalValue(kJune2016)) { 176 sha1_histogram = SHA1_EXPIRES_AFTER_JUNE_2016; 177 } else if (ssl_info.cert->valid_expiry() >= 178 base::Time::FromInternalValue(kJanuary2016)) { 179 sha1_histogram = SHA1_EXPIRES_AFTER_JANUARY_2016; 180 } else { 181 sha1_histogram = SHA1_PRESENT; 182 } 183 } 184 if (resource_type == RESOURCE_TYPE_MAIN_FRAME) { 185 UMA_HISTOGRAM_ENUMERATION("Net.Certificate.SHA1.MainFrame", 186 sha1_histogram, 187 SHA1_HISTOGRAM_TYPES_MAX); 188 } else { 189 UMA_HISTOGRAM_ENUMERATION("Net.Certificate.SHA1.Subresource", 190 sha1_histogram, 191 SHA1_HISTOGRAM_TYPES_MAX); 192 } 193} 194 195bool IsDetachableResourceType(ResourceType type) { 196 switch (type) { 197 case RESOURCE_TYPE_PREFETCH: 198 case RESOURCE_TYPE_PING: 199 return true; 200 default: 201 return false; 202 } 203} 204 205// Aborts a request before an URLRequest has actually been created. 206void AbortRequestBeforeItStarts(ResourceMessageFilter* filter, 207 IPC::Message* sync_result, 208 int request_id) { 209 if (sync_result) { 210 SyncLoadResult result; 211 result.error_code = net::ERR_ABORTED; 212 ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result, result); 213 filter->Send(sync_result); 214 } else { 215 // Tell the renderer that this request was disallowed. 216 ResourceMsg_RequestCompleteData request_complete_data; 217 request_complete_data.error_code = net::ERR_ABORTED; 218 request_complete_data.was_ignored_by_handler = false; 219 request_complete_data.exists_in_cache = false; 220 // No security info needed, connection not established. 221 request_complete_data.completion_time = base::TimeTicks(); 222 request_complete_data.encoded_data_length = 0; 223 filter->Send(new ResourceMsg_RequestComplete( 224 request_id, request_complete_data)); 225 } 226} 227 228void SetReferrerForRequest(net::URLRequest* request, const Referrer& referrer) { 229 if (!referrer.url.is_valid() || 230 base::CommandLine::ForCurrentProcess()->HasSwitch( 231 switches::kNoReferrers)) { 232 request->SetReferrer(std::string()); 233 } else { 234 request->SetReferrer(referrer.url.spec()); 235 } 236 237 net::URLRequest::ReferrerPolicy net_referrer_policy = 238 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE; 239 switch (referrer.policy) { 240 case blink::WebReferrerPolicyDefault: 241 net_referrer_policy = 242 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE; 243 break; 244 case blink::WebReferrerPolicyAlways: 245 case blink::WebReferrerPolicyNever: 246 case blink::WebReferrerPolicyOrigin: 247 net_referrer_policy = net::URLRequest::NEVER_CLEAR_REFERRER; 248 break; 249 } 250 request->set_referrer_policy(net_referrer_policy); 251} 252 253// Consults the RendererSecurity policy to determine whether the 254// ResourceDispatcherHostImpl should service this request. A request might be 255// disallowed if the renderer is not authorized to retrieve the request URL or 256// if the renderer is attempting to upload an unauthorized file. 257bool ShouldServiceRequest(int process_type, 258 int child_id, 259 const ResourceHostMsg_Request& request_data, 260 storage::FileSystemContext* file_system_context) { 261 if (process_type == PROCESS_TYPE_PLUGIN) 262 return true; 263 264 ChildProcessSecurityPolicyImpl* policy = 265 ChildProcessSecurityPolicyImpl::GetInstance(); 266 267 // Check if the renderer is permitted to request the requested URL. 268 if (!policy->CanRequestURL(child_id, request_data.url)) { 269 VLOG(1) << "Denied unauthorized request for " 270 << request_data.url.possibly_invalid_spec(); 271 return false; 272 } 273 274 // Check if the renderer is permitted to upload the requested files. 275 if (request_data.request_body.get()) { 276 const std::vector<ResourceRequestBody::Element>* uploads = 277 request_data.request_body->elements(); 278 std::vector<ResourceRequestBody::Element>::const_iterator iter; 279 for (iter = uploads->begin(); iter != uploads->end(); ++iter) { 280 if (iter->type() == ResourceRequestBody::Element::TYPE_FILE && 281 !policy->CanReadFile(child_id, iter->path())) { 282 NOTREACHED() << "Denied unauthorized upload of " 283 << iter->path().value(); 284 return false; 285 } 286 if (iter->type() == ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM) { 287 storage::FileSystemURL url = 288 file_system_context->CrackURL(iter->filesystem_url()); 289 if (!policy->CanReadFileSystemFile(child_id, url)) { 290 NOTREACHED() << "Denied unauthorized upload of " 291 << iter->filesystem_url().spec(); 292 return false; 293 } 294 } 295 } 296 } 297 298 return true; 299} 300 301void RemoveDownloadFileFromChildSecurityPolicy(int child_id, 302 const base::FilePath& path) { 303 ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile( 304 child_id, path); 305} 306 307DownloadInterruptReason CallbackAndReturn( 308 const DownloadUrlParameters::OnStartedCallback& started_cb, 309 DownloadInterruptReason interrupt_reason) { 310 if (started_cb.is_null()) 311 return interrupt_reason; 312 BrowserThread::PostTask( 313 BrowserThread::UI, 314 FROM_HERE, 315 base::Bind( 316 started_cb, static_cast<DownloadItem*>(NULL), interrupt_reason)); 317 318 return interrupt_reason; 319} 320 321int GetCertID(net::URLRequest* request, int child_id) { 322 if (request->ssl_info().cert.get()) { 323 return CertStore::GetInstance()->StoreCert(request->ssl_info().cert.get(), 324 child_id); 325 } 326 return 0; 327} 328 329void NotifyRedirectOnUI(int render_process_id, 330 int render_frame_host, 331 scoped_ptr<ResourceRedirectDetails> details) { 332 RenderFrameHostImpl* host = 333 RenderFrameHostImpl::FromID(render_process_id, render_frame_host); 334 WebContentsImpl* web_contents = 335 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host)); 336 if (!web_contents) 337 return; 338 web_contents->DidGetRedirectForResourceRequest( 339 host->render_view_host(), *details.get()); 340} 341 342void NotifyResponseOnUI(int render_process_id, 343 int render_frame_host, 344 scoped_ptr<ResourceRequestDetails> details) { 345 RenderFrameHostImpl* host = 346 RenderFrameHostImpl::FromID(render_process_id, render_frame_host); 347 WebContentsImpl* web_contents = 348 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host)); 349 if (!web_contents) 350 return; 351 web_contents->DidGetResourceResponseStart(*details.get()); 352} 353 354bool IsValidatedSCT( 355 const net::SignedCertificateTimestampAndStatus& sct_status) { 356 return sct_status.status == net::ct::SCT_STATUS_OK; 357} 358 359storage::BlobStorageContext* GetBlobStorageContext( 360 ResourceMessageFilter* filter) { 361 if (!filter->blob_storage_context()) 362 return NULL; 363 return filter->blob_storage_context()->context(); 364} 365 366void AttachRequestBodyBlobDataHandles( 367 ResourceRequestBody* body, 368 storage::BlobStorageContext* blob_context) { 369 DCHECK(blob_context); 370 for (size_t i = 0; i < body->elements()->size(); ++i) { 371 const ResourceRequestBody::Element& element = (*body->elements())[i]; 372 if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) 373 continue; 374 scoped_ptr<storage::BlobDataHandle> handle = 375 blob_context->GetBlobDataFromUUID(element.blob_uuid()); 376 DCHECK(handle); 377 if (!handle) 378 continue; 379 // Ensure the blob and any attached shareable files survive until 380 // upload completion. The |body| takes ownership of |handle|. 381 const void* key = handle.get(); 382 body->SetUserData(key, handle.release()); 383 } 384} 385 386} // namespace 387 388// static 389ResourceDispatcherHost* ResourceDispatcherHost::Get() { 390 return g_resource_dispatcher_host; 391} 392 393ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() 394 : save_file_manager_(new SaveFileManager()), 395 request_id_(-1), 396 is_shutdown_(false), 397 num_in_flight_requests_(0), 398 max_num_in_flight_requests_(base::SharedMemory::GetHandleLimit()), 399 max_num_in_flight_requests_per_process_( 400 static_cast<int>( 401 max_num_in_flight_requests_ * kMaxRequestsPerProcessRatio)), 402 max_outstanding_requests_cost_per_process_( 403 kMaxOutstandingRequestsCostPerProcess), 404 filter_(NULL), 405 delegate_(NULL), 406 allow_cross_origin_auth_prompt_(false) { 407 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 408 DCHECK(!g_resource_dispatcher_host); 409 g_resource_dispatcher_host = this; 410 411 GetContentClient()->browser()->ResourceDispatcherHostCreated(); 412 413 ANNOTATE_BENIGN_RACE( 414 &last_user_gesture_time_, 415 "We don't care about the precise value, see http://crbug.com/92889"); 416 417 BrowserThread::PostTask(BrowserThread::IO, 418 FROM_HERE, 419 base::Bind(&ResourceDispatcherHostImpl::OnInit, 420 base::Unretained(this))); 421 422 update_load_states_timer_.reset( 423 new base::RepeatingTimer<ResourceDispatcherHostImpl>()); 424} 425 426ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { 427 DCHECK(outstanding_requests_stats_map_.empty()); 428 DCHECK(g_resource_dispatcher_host); 429 g_resource_dispatcher_host = NULL; 430} 431 432// static 433ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { 434 return g_resource_dispatcher_host; 435} 436 437void ResourceDispatcherHostImpl::SetDelegate( 438 ResourceDispatcherHostDelegate* delegate) { 439 delegate_ = delegate; 440} 441 442void ResourceDispatcherHostImpl::SetAllowCrossOriginAuthPrompt(bool value) { 443 allow_cross_origin_auth_prompt_ = value; 444} 445 446void ResourceDispatcherHostImpl::AddResourceContext(ResourceContext* context) { 447 active_resource_contexts_.insert(context); 448} 449 450void ResourceDispatcherHostImpl::RemoveResourceContext( 451 ResourceContext* context) { 452 CHECK(ContainsKey(active_resource_contexts_, context)); 453 active_resource_contexts_.erase(context); 454} 455 456void ResourceDispatcherHostImpl::ResumeResponseDeferredAtStart( 457 const GlobalRequestID& id) { 458 ResourceLoader* loader = GetLoader(id); 459 if (loader) { 460 // The response we were meant to resume could have already been canceled. 461 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 462 if (info->cross_site_handler()) 463 info->cross_site_handler()->ResumeResponseDeferredAtStart(id.request_id); 464 } 465} 466 467void ResourceDispatcherHostImpl::CancelRequestsForContext( 468 ResourceContext* context) { 469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 470 DCHECK(context); 471 472 CHECK(ContainsKey(active_resource_contexts_, context)); 473 474 // Note that request cancellation has side effects. Therefore, we gather all 475 // the requests to cancel first, and then we start cancelling. We assert at 476 // the end that there are no more to cancel since the context is about to go 477 // away. 478 typedef std::vector<linked_ptr<ResourceLoader> > LoaderList; 479 LoaderList loaders_to_cancel; 480 481 for (LoaderMap::iterator i = pending_loaders_.begin(); 482 i != pending_loaders_.end();) { 483 if (i->second->GetRequestInfo()->GetContext() == context) { 484 loaders_to_cancel.push_back(i->second); 485 IncrementOutstandingRequestsMemory(-1, *i->second->GetRequestInfo()); 486 pending_loaders_.erase(i++); 487 } else { 488 ++i; 489 } 490 } 491 492 for (BlockedLoadersMap::iterator i = blocked_loaders_map_.begin(); 493 i != blocked_loaders_map_.end();) { 494 BlockedLoadersList* loaders = i->second; 495 if (loaders->empty()) { 496 // This can happen if BlockRequestsForRoute() has been called for a route, 497 // but we haven't blocked any matching requests yet. 498 ++i; 499 continue; 500 } 501 ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo(); 502 if (info->GetContext() == context) { 503 blocked_loaders_map_.erase(i++); 504 for (BlockedLoadersList::const_iterator it = loaders->begin(); 505 it != loaders->end(); ++it) { 506 linked_ptr<ResourceLoader> loader = *it; 507 info = loader->GetRequestInfo(); 508 // We make the assumption that all requests on the list have the same 509 // ResourceContext. 510 DCHECK_EQ(context, info->GetContext()); 511 IncrementOutstandingRequestsMemory(-1, *info); 512 loaders_to_cancel.push_back(loader); 513 } 514 delete loaders; 515 } else { 516 ++i; 517 } 518 } 519 520#ifndef NDEBUG 521 for (LoaderList::iterator i = loaders_to_cancel.begin(); 522 i != loaders_to_cancel.end(); ++i) { 523 // There is no strict requirement that this be the case, but currently 524 // downloads, streams, detachable requests, and transferred requests are the 525 // only requests that aren't cancelled when the associated processes go 526 // away. It may be OK for this invariant to change in the future, but if 527 // this assertion fires without the invariant changing, then it's indicative 528 // of a leak. 529 DCHECK((*i)->GetRequestInfo()->IsDownload() || 530 (*i)->GetRequestInfo()->is_stream() || 531 ((*i)->GetRequestInfo()->detachable_handler() && 532 (*i)->GetRequestInfo()->detachable_handler()->is_detached()) || 533 (*i)->is_transferring()); 534 } 535#endif 536 537 loaders_to_cancel.clear(); 538 539 // Validate that no more requests for this context were added. 540 for (LoaderMap::const_iterator i = pending_loaders_.begin(); 541 i != pending_loaders_.end(); ++i) { 542 // http://crbug.com/90971 543 CHECK_NE(i->second->GetRequestInfo()->GetContext(), context); 544 } 545 546 for (BlockedLoadersMap::const_iterator i = blocked_loaders_map_.begin(); 547 i != blocked_loaders_map_.end(); ++i) { 548 BlockedLoadersList* loaders = i->second; 549 if (!loaders->empty()) { 550 ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo(); 551 // http://crbug.com/90971 552 CHECK_NE(info->GetContext(), context); 553 } 554 } 555} 556 557DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload( 558 scoped_ptr<net::URLRequest> request, 559 const Referrer& referrer, 560 bool is_content_initiated, 561 ResourceContext* context, 562 int child_id, 563 int route_id, 564 bool prefer_cache, 565 scoped_ptr<DownloadSaveInfo> save_info, 566 uint32 download_id, 567 const DownloadStartedCallback& started_callback) { 568 if (is_shutdown_) 569 return CallbackAndReturn(started_callback, 570 DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN); 571 572 const GURL& url = request->original_url(); 573 574 // http://crbug.com/90971 575 char url_buf[128]; 576 base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf)); 577 base::debug::Alias(url_buf); 578 CHECK(ContainsKey(active_resource_contexts_, context)); 579 580 SetReferrerForRequest(request.get(), referrer); 581 582 int extra_load_flags = net::LOAD_IS_DOWNLOAD; 583 if (prefer_cache) { 584 // If there is upload data attached, only retrieve from cache because there 585 // is no current mechanism to prompt the user for their consent for a 586 // re-post. For GETs, try to retrieve data from the cache and skip 587 // validating the entry if present. 588 if (request->get_upload() != NULL) 589 extra_load_flags |= net::LOAD_ONLY_FROM_CACHE; 590 else 591 extra_load_flags |= net::LOAD_PREFERRING_CACHE; 592 } else { 593 extra_load_flags |= net::LOAD_DISABLE_CACHE; 594 } 595 request->SetLoadFlags(request->load_flags() | extra_load_flags); 596 597 // We treat a download as a main frame load, and thus update the policy URL on 598 // redirects. 599 // 600 // TODO(davidben): Is this correct? If this came from a 601 // ViewHostMsg_DownloadUrl in a frame, should it have first-party URL set 602 // appropriately? 603 request->set_first_party_url_policy( 604 net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); 605 606 // Check if the renderer is permitted to request the requested URL. 607 if (!ChildProcessSecurityPolicyImpl::GetInstance()-> 608 CanRequestURL(child_id, url)) { 609 VLOG(1) << "Denied unauthorized download request for " 610 << url.possibly_invalid_spec(); 611 return CallbackAndReturn(started_callback, 612 DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST); 613 } 614 615 request_id_--; 616 617 const net::URLRequestContext* request_context = context->GetRequestContext(); 618 if (!request_context->job_factory()->IsHandledURL(url)) { 619 VLOG(1) << "Download request for unsupported protocol: " 620 << url.possibly_invalid_spec(); 621 return CallbackAndReturn(started_callback, 622 DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST); 623 } 624 625 ResourceRequestInfoImpl* extra_info = 626 CreateRequestInfo(child_id, route_id, true, context); 627 extra_info->AssociateWithRequest(request.get()); // Request takes ownership. 628 629 if (request->url().SchemeIs(url::kBlobScheme)) { 630 ChromeBlobStorageContext* blob_context = 631 GetChromeBlobStorageContextForResourceContext(context); 632 storage::BlobProtocolHandler::SetRequestedBlobDataHandle( 633 request.get(), 634 blob_context->context()->GetBlobDataFromPublicURL(request->url())); 635 } 636 637 // From this point forward, the |DownloadResourceHandler| is responsible for 638 // |started_callback|. 639 scoped_ptr<ResourceHandler> handler( 640 CreateResourceHandlerForDownload(request.get(), is_content_initiated, 641 true, download_id, save_info.Pass(), 642 started_callback)); 643 644 BeginRequestInternal(request.Pass(), handler.Pass()); 645 646 return DOWNLOAD_INTERRUPT_REASON_NONE; 647} 648 649void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( 650 net::URLRequest* request) { 651 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); 652 if (info) { 653 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); 654 if (loader) 655 loader->ClearLoginDelegate(); 656 } 657} 658 659void ResourceDispatcherHostImpl::Shutdown() { 660 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 661 BrowserThread::PostTask(BrowserThread::IO, 662 FROM_HERE, 663 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, 664 base::Unretained(this))); 665} 666 667scoped_ptr<ResourceHandler> 668ResourceDispatcherHostImpl::CreateResourceHandlerForDownload( 669 net::URLRequest* request, 670 bool is_content_initiated, 671 bool must_download, 672 uint32 id, 673 scoped_ptr<DownloadSaveInfo> save_info, 674 const DownloadUrlParameters::OnStartedCallback& started_cb) { 675 scoped_ptr<ResourceHandler> handler( 676 new DownloadResourceHandler(id, request, started_cb, save_info.Pass())); 677 if (delegate_) { 678 const ResourceRequestInfo* request_info( 679 ResourceRequestInfo::ForRequest(request)); 680 681 ScopedVector<ResourceThrottle> throttles; 682 delegate_->DownloadStarting( 683 request, request_info->GetContext(), request_info->GetChildID(), 684 request_info->GetRouteID(), request_info->GetRequestID(), 685 is_content_initiated, must_download, &throttles); 686 if (!throttles.empty()) { 687 handler.reset( 688 new ThrottlingResourceHandler( 689 handler.Pass(), request, throttles.Pass())); 690 } 691 } 692 return handler.Pass(); 693} 694 695scoped_ptr<ResourceHandler> 696ResourceDispatcherHostImpl::MaybeInterceptAsStream(net::URLRequest* request, 697 ResourceResponse* response, 698 std::string* payload) { 699 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); 700 const std::string& mime_type = response->head.mime_type; 701 702 GURL origin; 703 if (!delegate_ || 704 !delegate_->ShouldInterceptResourceAsStream(request, 705 mime_type, 706 &origin, 707 payload)) { 708 return scoped_ptr<ResourceHandler>(); 709 } 710 711 StreamContext* stream_context = 712 GetStreamContextForResourceContext(info->GetContext()); 713 714 scoped_ptr<StreamResourceHandler> handler( 715 new StreamResourceHandler(request, 716 stream_context->registry(), 717 origin)); 718 719 info->set_is_stream(true); 720 delegate_->OnStreamCreated( 721 request, 722 handler->stream()->CreateHandle( 723 request->url(), 724 mime_type, 725 response->head.headers)); 726 return handler.PassAs<ResourceHandler>(); 727} 728 729void ResourceDispatcherHostImpl::ClearSSLClientAuthHandlerForRequest( 730 net::URLRequest* request) { 731 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); 732 if (info) { 733 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); 734 if (loader) 735 loader->ClearSSLClientAuthHandler(); 736 } 737} 738 739ResourceDispatcherHostLoginDelegate* 740ResourceDispatcherHostImpl::CreateLoginDelegate( 741 ResourceLoader* loader, 742 net::AuthChallengeInfo* auth_info) { 743 if (!delegate_) 744 return NULL; 745 746 return delegate_->CreateLoginDelegate(auth_info, loader->request()); 747} 748 749bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader, 750 const GURL& url) { 751 if (!delegate_) 752 return false; 753 754 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 755 756 if (!IsResourceTypeFrame(info->GetResourceType())) 757 return false; 758 759 const net::URLRequestJobFactory* job_factory = 760 info->GetContext()->GetRequestContext()->job_factory(); 761 if (job_factory->IsHandledURL(url)) 762 return false; 763 764 return delegate_->HandleExternalProtocol( 765 url, info->GetChildID(), info->GetRouteID()); 766} 767 768void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { 769 // Make sure we have the load state monitor running 770 if (!update_load_states_timer_->IsRunning()) { 771 update_load_states_timer_->Start(FROM_HERE, 772 TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), 773 this, &ResourceDispatcherHostImpl::UpdateLoadStates); 774 } 775} 776 777void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader, 778 const GURL& new_url) { 779 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 780 781 int render_process_id, render_frame_host; 782 if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_host)) 783 return; 784 785 // Notify the observers on the UI thread. 786 scoped_ptr<ResourceRedirectDetails> detail(new ResourceRedirectDetails( 787 loader->request(), 788 GetCertID(loader->request(), info->GetChildID()), 789 new_url)); 790 BrowserThread::PostTask( 791 BrowserThread::UI, FROM_HERE, 792 base::Bind( 793 &NotifyRedirectOnUI, 794 render_process_id, render_frame_host, base::Passed(&detail))); 795} 796 797void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) { 798 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 799 800 if (loader->request()->was_fetched_via_proxy() && 801 loader->request()->was_fetched_via_spdy() && 802 loader->request()->url().SchemeIs(url::kHttpScheme)) { 803 scheduler_->OnReceivedSpdyProxiedHttpResponse( 804 info->GetChildID(), info->GetRouteID()); 805 } 806 807 int render_process_id, render_frame_host; 808 if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_host)) 809 return; 810 811 // Notify the observers on the UI thread. 812 scoped_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails( 813 loader->request(), 814 GetCertID(loader->request(), info->GetChildID()))); 815 BrowserThread::PostTask( 816 BrowserThread::UI, FROM_HERE, 817 base::Bind( 818 &NotifyResponseOnUI, 819 render_process_id, render_frame_host, base::Passed(&detail))); 820} 821 822void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) { 823 ResourceRequestInfo* info = loader->GetRequestInfo(); 824 825 // Record final result of all resource loads. 826 if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) { 827 // This enumeration has "3" appended to its name to distinguish it from 828 // older versions. 829 UMA_HISTOGRAM_SPARSE_SLOWLY( 830 "Net.ErrorCodesForMainFrame3", 831 -loader->request()->status().error()); 832 833 if (loader->request()->url().SchemeIsSecure()) { 834 if (loader->request()->url().host() == "www.google.com") { 835 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.ErrorCodesForHTTPSGoogleMainFrame2", 836 -loader->request()->status().error()); 837 } 838 839 int num_valid_scts = std::count_if( 840 loader->request()->ssl_info().signed_certificate_timestamps.begin(), 841 loader->request()->ssl_info().signed_certificate_timestamps.end(), 842 IsValidatedSCT); 843 UMA_HISTOGRAM_COUNTS_100( 844 "Net.CertificateTransparency.MainFrameValidSCTCount", num_valid_scts); 845 } 846 } else { 847 if (info->GetResourceType() == RESOURCE_TYPE_IMAGE) { 848 UMA_HISTOGRAM_SPARSE_SLOWLY( 849 "Net.ErrorCodesForImages", 850 -loader->request()->status().error()); 851 } 852 // This enumeration has "2" appended to distinguish it from older versions. 853 UMA_HISTOGRAM_SPARSE_SLOWLY( 854 "Net.ErrorCodesForSubresources2", 855 -loader->request()->status().error()); 856 } 857 858 if (loader->request()->url().SchemeIsSecure()) { 859 RecordCertificateHistograms(loader->request()->ssl_info(), 860 info->GetResourceType()); 861 } 862 863 if (delegate_) 864 delegate_->RequestComplete(loader->request()); 865 866 // Destroy the ResourceLoader. 867 RemovePendingRequest(info->GetChildID(), info->GetRequestID()); 868} 869 870void ResourceDispatcherHostImpl::OnInit() { 871 scheduler_.reset(new ResourceScheduler); 872 AppCacheInterceptor::EnsureRegistered(); 873} 874 875void ResourceDispatcherHostImpl::OnShutdown() { 876 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 877 878 is_shutdown_ = true; 879 pending_loaders_.clear(); 880 881 // Make sure we shutdown the timer now, otherwise by the time our destructor 882 // runs if the timer is still running the Task is deleted twice (once by 883 // the MessageLoop and the second time by RepeatingTimer). 884 update_load_states_timer_.reset(); 885 886 // Clear blocked requests if any left. 887 // Note that we have to do this in 2 passes as we cannot call 888 // CancelBlockedRequestsForRoute while iterating over 889 // blocked_loaders_map_, as it modifies it. 890 std::set<GlobalRoutingID> ids; 891 for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin(); 892 iter != blocked_loaders_map_.end(); ++iter) { 893 std::pair<std::set<GlobalRoutingID>::iterator, bool> result = 894 ids.insert(iter->first); 895 // We should not have duplicates. 896 DCHECK(result.second); 897 } 898 for (std::set<GlobalRoutingID>::const_iterator iter = ids.begin(); 899 iter != ids.end(); ++iter) { 900 CancelBlockedRequestsForRoute(iter->child_id, iter->route_id); 901 } 902 903 scheduler_.reset(); 904} 905 906bool ResourceDispatcherHostImpl::OnMessageReceived( 907 const IPC::Message& message, 908 ResourceMessageFilter* filter) { 909 filter_ = filter; 910 bool handled = true; 911 IPC_BEGIN_MESSAGE_MAP(ResourceDispatcherHostImpl, message) 912 IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource) 913 IPC_MESSAGE_HANDLER_DELAY_REPLY(ResourceHostMsg_SyncLoad, OnSyncLoad) 914 IPC_MESSAGE_HANDLER(ResourceHostMsg_ReleaseDownloadedFile, 915 OnReleaseDownloadedFile) 916 IPC_MESSAGE_HANDLER(ResourceHostMsg_DataDownloaded_ACK, OnDataDownloadedACK) 917 IPC_MESSAGE_HANDLER(ResourceHostMsg_UploadProgress_ACK, OnUploadProgressACK) 918 IPC_MESSAGE_HANDLER(ResourceHostMsg_CancelRequest, OnCancelRequest) 919 IPC_MESSAGE_UNHANDLED(handled = false) 920 IPC_END_MESSAGE_MAP() 921 922 if (!handled && IPC_MESSAGE_ID_CLASS(message.type()) == ResourceMsgStart) { 923 PickleIterator iter(message); 924 int request_id = -1; 925 bool ok = iter.ReadInt(&request_id); 926 DCHECK(ok); 927 GlobalRequestID id(filter_->child_id(), request_id); 928 DelegateMap::iterator it = delegate_map_.find(id); 929 if (it != delegate_map_.end()) { 930 ObserverList<ResourceMessageDelegate>::Iterator del_it(*it->second); 931 ResourceMessageDelegate* delegate; 932 while (!handled && (delegate = del_it.GetNext()) != NULL) { 933 handled = delegate->OnMessageReceived(message); 934 } 935 } 936 937 // As the unhandled resource message effectively has no consumer, mark it as 938 // handled to prevent needless propagation through the filter pipeline. 939 handled = true; 940 } 941 942 filter_ = NULL; 943 return handled; 944} 945 946void ResourceDispatcherHostImpl::OnRequestResource( 947 int routing_id, 948 int request_id, 949 const ResourceHostMsg_Request& request_data) { 950 BeginRequest(request_id, request_data, NULL, routing_id); 951} 952 953// Begins a resource request with the given params on behalf of the specified 954// child process. Responses will be dispatched through the given receiver. The 955// process ID is used to lookup WebContentsImpl from routing_id's in the case of 956// a request from a renderer. request_context is the cookie/cache context to be 957// used for this request. 958// 959// If sync_result is non-null, then a SyncLoad reply will be generated, else 960// a normal asynchronous set of response messages will be generated. 961void ResourceDispatcherHostImpl::OnSyncLoad( 962 int request_id, 963 const ResourceHostMsg_Request& request_data, 964 IPC::Message* sync_result) { 965 BeginRequest(request_id, request_data, sync_result, 966 sync_result->routing_id()); 967} 968 969void ResourceDispatcherHostImpl::UpdateRequestForTransfer( 970 int child_id, 971 int route_id, 972 int request_id, 973 const ResourceHostMsg_Request& request_data, 974 const linked_ptr<ResourceLoader>& loader) { 975 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 976 GlobalRoutingID old_routing_id( 977 request_data.transferred_request_child_id, info->GetRouteID()); 978 GlobalRequestID old_request_id(request_data.transferred_request_child_id, 979 request_data.transferred_request_request_id); 980 GlobalRoutingID new_routing_id(child_id, route_id); 981 GlobalRequestID new_request_id(child_id, request_id); 982 983 // Clear out data that depends on |info| before updating it. 984 IncrementOutstandingRequestsMemory(-1, *info); 985 OustandingRequestsStats empty_stats = { 0, 0 }; 986 OustandingRequestsStats old_stats = GetOutstandingRequestsStats(*info); 987 UpdateOutstandingRequestsStats(*info, empty_stats); 988 pending_loaders_.erase(old_request_id); 989 990 // ResourceHandlers should always get state related to the request from the 991 // ResourceRequestInfo rather than caching it locally. This lets us update 992 // the info object when a transfer occurs. 993 info->UpdateForTransfer(child_id, route_id, request_data.origin_pid, 994 request_id, request_data.parent_render_frame_id, 995 filter_->GetWeakPtr()); 996 997 // Update maps that used the old IDs, if necessary. Some transfers in tests 998 // do not actually use a different ID, so not all maps need to be updated. 999 pending_loaders_[new_request_id] = loader; 1000 UpdateOutstandingRequestsStats(*info, old_stats); 1001 IncrementOutstandingRequestsMemory(1, *info); 1002 if (old_routing_id != new_routing_id) { 1003 if (blocked_loaders_map_.find(old_routing_id) != 1004 blocked_loaders_map_.end()) { 1005 blocked_loaders_map_[new_routing_id] = 1006 blocked_loaders_map_[old_routing_id]; 1007 blocked_loaders_map_.erase(old_routing_id); 1008 } 1009 } 1010 if (old_request_id != new_request_id) { 1011 DelegateMap::iterator it = delegate_map_.find(old_request_id); 1012 if (it != delegate_map_.end()) { 1013 // Tell each delegate that the request ID has changed. 1014 ObserverList<ResourceMessageDelegate>::Iterator del_it(*it->second); 1015 ResourceMessageDelegate* delegate; 1016 while ((delegate = del_it.GetNext()) != NULL) { 1017 delegate->set_request_id(new_request_id); 1018 } 1019 // Now store the observer list under the new request ID. 1020 delegate_map_[new_request_id] = delegate_map_[old_request_id]; 1021 delegate_map_.erase(old_request_id); 1022 } 1023 } 1024 1025 AppCacheInterceptor::CompleteCrossSiteTransfer( 1026 loader->request(), 1027 child_id, 1028 request_data.appcache_host_id); 1029 1030 // We should have a CrossSiteResourceHandler to finish the transfer. 1031 DCHECK(info->cross_site_handler()); 1032} 1033 1034void ResourceDispatcherHostImpl::BeginRequest( 1035 int request_id, 1036 const ResourceHostMsg_Request& request_data, 1037 IPC::Message* sync_result, // only valid for sync 1038 int route_id) { 1039 int process_type = filter_->process_type(); 1040 int child_id = filter_->child_id(); 1041 1042 // Reject invalid priority. 1043 if (request_data.priority < net::MINIMUM_PRIORITY || 1044 request_data.priority > net::MAXIMUM_PRIORITY) { 1045 RecordAction(base::UserMetricsAction("BadMessageTerminate_RDH")); 1046 filter_->BadMessageReceived(); 1047 return; 1048 } 1049 1050 // If we crash here, figure out what URL the renderer was requesting. 1051 // http://crbug.com/91398 1052 char url_buf[128]; 1053 base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf)); 1054 base::debug::Alias(url_buf); 1055 1056 // If the request that's coming in is being transferred from another process, 1057 // we want to reuse and resume the old loader rather than start a new one. 1058 { 1059 LoaderMap::iterator it = pending_loaders_.find( 1060 GlobalRequestID(request_data.transferred_request_child_id, 1061 request_data.transferred_request_request_id)); 1062 if (it != pending_loaders_.end()) { 1063 // If the request is transferring to a new process, we can update our 1064 // state and let it resume with its existing ResourceHandlers. 1065 if (it->second->is_transferring()) { 1066 linked_ptr<ResourceLoader> deferred_loader = it->second; 1067 UpdateRequestForTransfer(child_id, route_id, request_id, 1068 request_data, deferred_loader); 1069 1070 deferred_loader->CompleteTransfer(); 1071 } else { 1072 RecordAction(base::UserMetricsAction("BadMessageTerminate_RDH")); 1073 filter_->BadMessageReceived(); 1074 } 1075 return; 1076 } 1077 } 1078 1079 ResourceContext* resource_context = NULL; 1080 net::URLRequestContext* request_context = NULL; 1081 filter_->GetContexts(request_data, &resource_context, &request_context); 1082 // http://crbug.com/90971 1083 CHECK(ContainsKey(active_resource_contexts_, resource_context)); 1084 1085 if (is_shutdown_ || 1086 !ShouldServiceRequest(process_type, child_id, request_data, 1087 filter_->file_system_context())) { 1088 AbortRequestBeforeItStarts(filter_, sync_result, request_id); 1089 return; 1090 } 1091 1092 // Allow the observer to block/handle the request. 1093 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, 1094 request_data.url, 1095 request_data.resource_type, 1096 resource_context)) { 1097 AbortRequestBeforeItStarts(filter_, sync_result, request_id); 1098 return; 1099 } 1100 1101 bool is_sync_load = sync_result != NULL; 1102 int load_flags = 1103 BuildLoadFlagsForRequest(request_data, child_id, is_sync_load); 1104 1105 // Sync loads should have maximum priority and should be the only 1106 // requets that have the ignore limits flag set. 1107 if (is_sync_load) { 1108 DCHECK_EQ(request_data.priority, net::MAXIMUM_PRIORITY); 1109 DCHECK_NE(load_flags & net::LOAD_IGNORE_LIMITS, 0); 1110 } else { 1111 DCHECK_EQ(load_flags & net::LOAD_IGNORE_LIMITS, 0); 1112 } 1113 1114 // Construct the request. 1115 net::CookieStore* cookie_store = 1116 GetContentClient()->browser()->OverrideCookieStoreForRenderProcess( 1117 child_id); 1118 scoped_ptr<net::URLRequest> new_request; 1119 new_request = request_context->CreateRequest( 1120 request_data.url, request_data.priority, NULL, cookie_store); 1121 1122 new_request->set_method(request_data.method); 1123 new_request->set_first_party_for_cookies( 1124 request_data.first_party_for_cookies); 1125 1126 // If the request is a MAIN_FRAME request, the first-party URL gets updated on 1127 // redirects. 1128 if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME) { 1129 new_request->set_first_party_url_policy( 1130 net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); 1131 } 1132 1133 const Referrer referrer(request_data.referrer, request_data.referrer_policy); 1134 SetReferrerForRequest(new_request.get(), referrer); 1135 1136 net::HttpRequestHeaders headers; 1137 headers.AddHeadersFromString(request_data.headers); 1138 new_request->SetExtraRequestHeaders(headers); 1139 1140 new_request->SetLoadFlags(load_flags); 1141 1142 storage::BlobStorageContext* blob_context = 1143 GetBlobStorageContext(filter_); 1144 // Resolve elements from request_body and prepare upload data. 1145 if (request_data.request_body.get()) { 1146 // Attaches the BlobDataHandles to request_body not to free the blobs and 1147 // any attached shareable files until upload completion. These data will be 1148 // used in UploadDataStream and ServiceWorkerURLRequestJob. 1149 AttachRequestBodyBlobDataHandles( 1150 request_data.request_body.get(), 1151 blob_context); 1152 new_request->set_upload(UploadDataStreamBuilder::Build( 1153 request_data.request_body.get(), 1154 blob_context, 1155 filter_->file_system_context(), 1156 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) 1157 .get())); 1158 } 1159 1160 bool allow_download = request_data.allow_download && 1161 IsResourceTypeFrame(request_data.resource_type); 1162 1163 // Make extra info and read footer (contains request ID). 1164 ResourceRequestInfoImpl* extra_info = 1165 new ResourceRequestInfoImpl( 1166 process_type, 1167 child_id, 1168 route_id, 1169 request_data.origin_pid, 1170 request_id, 1171 request_data.render_frame_id, 1172 request_data.is_main_frame, 1173 request_data.parent_is_main_frame, 1174 request_data.parent_render_frame_id, 1175 request_data.resource_type, 1176 request_data.transition_type, 1177 request_data.should_replace_current_entry, 1178 false, // is download 1179 false, // is stream 1180 allow_download, 1181 request_data.has_user_gesture, 1182 request_data.enable_load_timing, 1183 request_data.referrer_policy, 1184 request_data.visiblity_state, 1185 resource_context, 1186 filter_->GetWeakPtr(), 1187 !is_sync_load); 1188 // Request takes ownership. 1189 extra_info->AssociateWithRequest(new_request.get()); 1190 1191 if (new_request->url().SchemeIs(url::kBlobScheme)) { 1192 // Hang on to a reference to ensure the blob is not released prior 1193 // to the job being started. 1194 storage::BlobProtocolHandler::SetRequestedBlobDataHandle( 1195 new_request.get(), 1196 filter_->blob_storage_context()->context()->GetBlobDataFromPublicURL( 1197 new_request->url())); 1198 } 1199 1200 // Initialize the service worker handler for the request. 1201 ServiceWorkerRequestHandler::InitializeHandler( 1202 new_request.get(), 1203 filter_->service_worker_context(), 1204 blob_context, 1205 child_id, 1206 request_data.service_worker_provider_id, 1207 request_data.skip_service_worker, 1208 request_data.resource_type, 1209 request_data.request_body); 1210 1211 // Have the appcache associate its extra info with the request. 1212 AppCacheInterceptor::SetExtraRequestInfo( 1213 new_request.get(), filter_->appcache_service(), child_id, 1214 request_data.appcache_host_id, request_data.resource_type); 1215 1216 scoped_ptr<ResourceHandler> handler( 1217 CreateResourceHandler( 1218 new_request.get(), 1219 request_data, sync_result, route_id, process_type, child_id, 1220 resource_context)); 1221 1222 if (handler) 1223 BeginRequestInternal(new_request.Pass(), handler.Pass()); 1224} 1225 1226scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler( 1227 net::URLRequest* request, 1228 const ResourceHostMsg_Request& request_data, 1229 IPC::Message* sync_result, 1230 int route_id, 1231 int process_type, 1232 int child_id, 1233 ResourceContext* resource_context) { 1234 // Construct the IPC resource handler. 1235 scoped_ptr<ResourceHandler> handler; 1236 if (sync_result) { 1237 // download_to_file is not supported for synchronous requests. 1238 if (request_data.download_to_file) { 1239 RecordAction(base::UserMetricsAction("BadMessageTerminate_RDH")); 1240 filter_->BadMessageReceived(); 1241 return scoped_ptr<ResourceHandler>(); 1242 } 1243 1244 handler.reset(new SyncResourceHandler(request, sync_result, this)); 1245 } else { 1246 handler.reset(new AsyncResourceHandler(request, this)); 1247 1248 // The RedirectToFileResourceHandler depends on being next in the chain. 1249 if (request_data.download_to_file) { 1250 handler.reset( 1251 new RedirectToFileResourceHandler(handler.Pass(), request)); 1252 } 1253 } 1254 1255 // Prefetches and <a ping> requests outlive their child process. 1256 if (!sync_result && IsDetachableResourceType(request_data.resource_type)) { 1257 handler.reset(new DetachableResourceHandler( 1258 request, 1259 base::TimeDelta::FromMilliseconds(kDefaultDetachableCancelDelayMs), 1260 handler.Pass())); 1261 } 1262 1263 // Install a CrossSiteResourceHandler for all main frame requests. This will 1264 // let us check whether a transfer is required and pause for the unload 1265 // handler either if so or if a cross-process navigation is already under way. 1266 bool is_swappable_navigation = 1267 request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME; 1268 // If we are using --site-per-process, install it for subframes as well. 1269 if (!is_swappable_navigation && 1270 base::CommandLine::ForCurrentProcess()->HasSwitch( 1271 switches::kSitePerProcess)) { 1272 is_swappable_navigation = 1273 request_data.resource_type == RESOURCE_TYPE_SUB_FRAME; 1274 } 1275 if (is_swappable_navigation && process_type == PROCESS_TYPE_RENDERER) 1276 handler.reset(new CrossSiteResourceHandler(handler.Pass(), request)); 1277 1278 // Insert a buffered event handler before the actual one. 1279 handler.reset( 1280 new BufferedResourceHandler(handler.Pass(), this, request)); 1281 1282 ScopedVector<ResourceThrottle> throttles; 1283 if (delegate_) { 1284 delegate_->RequestBeginning(request, 1285 resource_context, 1286 filter_->appcache_service(), 1287 request_data.resource_type, 1288 &throttles); 1289 } 1290 1291 if (request->has_upload()) { 1292 // Block power save while uploading data. 1293 throttles.push_back(new PowerSaveBlockResourceThrottle()); 1294 } 1295 1296 throttles.push_back( 1297 scheduler_->ScheduleRequest(child_id, route_id, request).release()); 1298 1299 handler.reset( 1300 new ThrottlingResourceHandler(handler.Pass(), request, throttles.Pass())); 1301 1302 return handler.Pass(); 1303} 1304 1305void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) { 1306 UnregisterDownloadedTempFile(filter_->child_id(), request_id); 1307} 1308 1309void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) { 1310 // TODO(michaeln): maybe throttle DataDownloaded messages 1311} 1312 1313void ResourceDispatcherHostImpl::RegisterDownloadedTempFile( 1314 int child_id, int request_id, const base::FilePath& file_path) { 1315 scoped_refptr<ShareableFileReference> reference = 1316 ShareableFileReference::Get(file_path); 1317 DCHECK(reference.get()); 1318 1319 registered_temp_files_[child_id][request_id] = reference; 1320 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( 1321 child_id, reference->path()); 1322 1323 // When the temp file is deleted, revoke permissions that the renderer has 1324 // to that file. This covers an edge case where the file is deleted and then 1325 // the same name is re-used for some other purpose, we don't want the old 1326 // renderer to still have access to it. 1327 // 1328 // We do this when the file is deleted because the renderer can take a blob 1329 // reference to the temp file that outlives the url loaded that it was 1330 // loaded with to keep the file (and permissions) alive. 1331 reference->AddFinalReleaseCallback( 1332 base::Bind(&RemoveDownloadFileFromChildSecurityPolicy, 1333 child_id)); 1334} 1335 1336void ResourceDispatcherHostImpl::UnregisterDownloadedTempFile( 1337 int child_id, int request_id) { 1338 DeletableFilesMap& map = registered_temp_files_[child_id]; 1339 DeletableFilesMap::iterator found = map.find(request_id); 1340 if (found == map.end()) 1341 return; 1342 1343 map.erase(found); 1344 1345 // Note that we don't remove the security bits here. This will be done 1346 // when all file refs are deleted (see RegisterDownloadedTempFile). 1347} 1348 1349bool ResourceDispatcherHostImpl::Send(IPC::Message* message) { 1350 delete message; 1351 return false; 1352} 1353 1354void ResourceDispatcherHostImpl::OnUploadProgressACK(int request_id) { 1355 ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); 1356 if (loader) 1357 loader->OnUploadProgressACK(); 1358} 1359 1360// Note that this cancel is subtly different from the other 1361// CancelRequest methods in this file, which also tear down the loader. 1362void ResourceDispatcherHostImpl::OnCancelRequest(int request_id) { 1363 int child_id = filter_->child_id(); 1364 1365 // When the old renderer dies, it sends a message to us to cancel its 1366 // requests. 1367 if (IsTransferredNavigation(GlobalRequestID(child_id, request_id))) 1368 return; 1369 1370 ResourceLoader* loader = GetLoader(child_id, request_id); 1371 if (!loader) { 1372 // We probably want to remove this warning eventually, but I wanted to be 1373 // able to notice when this happens during initial development since it 1374 // should be rare and may indicate a bug. 1375 DVLOG(1) << "Canceling a request that wasn't found"; 1376 return; 1377 } 1378 1379 loader->CancelRequest(true); 1380} 1381 1382ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo( 1383 int child_id, 1384 int route_id, 1385 bool download, 1386 ResourceContext* context) { 1387 return new ResourceRequestInfoImpl( 1388 PROCESS_TYPE_RENDERER, 1389 child_id, 1390 route_id, 1391 0, 1392 request_id_, 1393 MSG_ROUTING_NONE, // render_frame_id 1394 false, // is_main_frame 1395 false, // parent_is_main_frame 1396 -1, // parent_render_frame_id 1397 RESOURCE_TYPE_SUB_RESOURCE, 1398 ui::PAGE_TRANSITION_LINK, 1399 false, // should_replace_current_entry 1400 download, // is_download 1401 false, // is_stream 1402 download, // allow_download 1403 false, // has_user_gesture 1404 false, // enable_load_timing 1405 blink::WebReferrerPolicyDefault, 1406 blink::WebPageVisibilityStateVisible, 1407 context, 1408 base::WeakPtr<ResourceMessageFilter>(), // filter 1409 true); // is_async 1410} 1411 1412void ResourceDispatcherHostImpl::OnRenderViewHostCreated( 1413 int child_id, 1414 int route_id, 1415 bool is_visible) { 1416 scheduler_->OnClientCreated(child_id, route_id, is_visible); 1417} 1418 1419void ResourceDispatcherHostImpl::OnRenderViewHostDeleted( 1420 int child_id, 1421 int route_id) { 1422 scheduler_->OnClientDeleted(child_id, route_id); 1423 CancelRequestsForRoute(child_id, route_id); 1424} 1425 1426void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id, 1427 int route_id, 1428 bool is_loading) { 1429 scheduler_->OnLoadingStateChanged(child_id, route_id, !is_loading); 1430} 1431 1432void ResourceDispatcherHostImpl::OnRenderViewHostWasHidden( 1433 int child_id, 1434 int route_id) { 1435 scheduler_->OnVisibilityChanged(child_id, route_id, false); 1436} 1437 1438void ResourceDispatcherHostImpl::OnRenderViewHostWasShown( 1439 int child_id, 1440 int route_id) { 1441 scheduler_->OnVisibilityChanged(child_id, route_id, true); 1442} 1443 1444// This function is only used for saving feature. 1445void ResourceDispatcherHostImpl::BeginSaveFile( 1446 const GURL& url, 1447 const Referrer& referrer, 1448 int child_id, 1449 int route_id, 1450 ResourceContext* context) { 1451 if (is_shutdown_) 1452 return; 1453 1454 // http://crbug.com/90971 1455 char url_buf[128]; 1456 base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf)); 1457 base::debug::Alias(url_buf); 1458 CHECK(ContainsKey(active_resource_contexts_, context)); 1459 1460 request_id_--; 1461 1462 const net::URLRequestContext* request_context = context->GetRequestContext(); 1463 bool known_proto = 1464 request_context->job_factory()->IsHandledURL(url); 1465 if (!known_proto) { 1466 // Since any URLs which have non-standard scheme have been filtered 1467 // by save manager(see GURL::SchemeIsStandard). This situation 1468 // should not happen. 1469 NOTREACHED(); 1470 return; 1471 } 1472 1473 net::CookieStore* cookie_store = 1474 GetContentClient()->browser()->OverrideCookieStoreForRenderProcess( 1475 child_id); 1476 scoped_ptr<net::URLRequest> request( 1477 request_context->CreateRequest(url, net::DEFAULT_PRIORITY, NULL, 1478 cookie_store)); 1479 1480 request->set_method("GET"); 1481 SetReferrerForRequest(request.get(), referrer); 1482 1483 // So far, for saving page, we need fetch content from cache, in the 1484 // future, maybe we can use a configuration to configure this behavior. 1485 request->SetLoadFlags(net::LOAD_PREFERRING_CACHE); 1486 1487 // Since we're just saving some resources we need, disallow downloading. 1488 ResourceRequestInfoImpl* extra_info = 1489 CreateRequestInfo(child_id, route_id, false, context); 1490 extra_info->AssociateWithRequest(request.get()); // Request takes ownership. 1491 1492 scoped_ptr<ResourceHandler> handler( 1493 new SaveFileResourceHandler(request.get(), 1494 child_id, 1495 route_id, 1496 url, 1497 save_file_manager_.get())); 1498 1499 BeginRequestInternal(request.Pass(), handler.Pass()); 1500} 1501 1502void ResourceDispatcherHostImpl::MarkAsTransferredNavigation( 1503 const GlobalRequestID& id) { 1504 GetLoader(id)->MarkAsTransferring(); 1505} 1506 1507void ResourceDispatcherHostImpl::CancelTransferringNavigation( 1508 const GlobalRequestID& id) { 1509 // Request should still exist and be in the middle of a transfer. 1510 DCHECK(IsTransferredNavigation(id)); 1511 RemovePendingRequest(id.child_id, id.request_id); 1512} 1513 1514void ResourceDispatcherHostImpl::ResumeDeferredNavigation( 1515 const GlobalRequestID& id) { 1516 ResourceLoader* loader = GetLoader(id); 1517 // The response we were meant to resume could have already been canceled. 1518 if (loader) 1519 loader->CompleteTransfer(); 1520} 1521 1522// The object died, so cancel and detach all requests associated with it except 1523// for downloads and detachable resources, which belong to the browser process 1524// even if initiated via a renderer. 1525void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) { 1526 CancelRequestsForRoute(child_id, -1 /* cancel all */); 1527 registered_temp_files_.erase(child_id); 1528} 1529 1530void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id, 1531 int route_id) { 1532 // Since pending_requests_ is a map, we first build up a list of all of the 1533 // matching requests to be cancelled, and then we cancel them. Since there 1534 // may be more than one request to cancel, we cannot simply hold onto the map 1535 // iterators found in the first loop. 1536 1537 // Find the global ID of all matching elements. 1538 bool any_requests_transferring = false; 1539 std::vector<GlobalRequestID> matching_requests; 1540 for (LoaderMap::const_iterator i = pending_loaders_.begin(); 1541 i != pending_loaders_.end(); ++i) { 1542 if (i->first.child_id != child_id) 1543 continue; 1544 1545 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); 1546 1547 GlobalRequestID id(child_id, i->first.request_id); 1548 DCHECK(id == i->first); 1549 // Don't cancel navigations that are expected to live beyond this process. 1550 if (IsTransferredNavigation(id)) 1551 any_requests_transferring = true; 1552 if (info->detachable_handler()) { 1553 info->detachable_handler()->Detach(); 1554 } else if (!info->IsDownload() && !info->is_stream() && 1555 !IsTransferredNavigation(id) && 1556 (route_id == -1 || route_id == info->GetRouteID())) { 1557 matching_requests.push_back(id); 1558 } 1559 } 1560 1561 // Remove matches. 1562 for (size_t i = 0; i < matching_requests.size(); ++i) { 1563 LoaderMap::iterator iter = pending_loaders_.find(matching_requests[i]); 1564 // Although every matching request was in pending_requests_ when we built 1565 // matching_requests, it is normal for a matching request to be not found 1566 // in pending_requests_ after we have removed some matching requests from 1567 // pending_requests_. For example, deleting a net::URLRequest that has 1568 // exclusive (write) access to an HTTP cache entry may unblock another 1569 // net::URLRequest that needs exclusive access to the same cache entry, and 1570 // that net::URLRequest may complete and remove itself from 1571 // pending_requests_. So we need to check that iter is not equal to 1572 // pending_requests_.end(). 1573 if (iter != pending_loaders_.end()) 1574 RemovePendingLoader(iter); 1575 } 1576 1577 // Don't clear the blocked loaders or offline policy maps if any of the 1578 // requests in route_id are being transferred to a new process, since those 1579 // maps will be updated with the new route_id after the transfer. Otherwise 1580 // we will lose track of this info when the old route goes away, before the 1581 // new one is created. 1582 if (any_requests_transferring) 1583 return; 1584 1585 // Now deal with blocked requests if any. 1586 if (route_id != -1) { 1587 if (blocked_loaders_map_.find(GlobalRoutingID(child_id, route_id)) != 1588 blocked_loaders_map_.end()) { 1589 CancelBlockedRequestsForRoute(child_id, route_id); 1590 } 1591 } else { 1592 // We have to do all render views for the process |child_id|. 1593 // Note that we have to do this in 2 passes as we cannot call 1594 // CancelBlockedRequestsForRoute while iterating over 1595 // blocked_loaders_map_, as it modifies it. 1596 std::set<int> route_ids; 1597 for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin(); 1598 iter != blocked_loaders_map_.end(); ++iter) { 1599 if (iter->first.child_id == child_id) 1600 route_ids.insert(iter->first.route_id); 1601 } 1602 for (std::set<int>::const_iterator iter = route_ids.begin(); 1603 iter != route_ids.end(); ++iter) { 1604 CancelBlockedRequestsForRoute(child_id, *iter); 1605 } 1606 } 1607} 1608 1609// Cancels the request and removes it from the list. 1610void ResourceDispatcherHostImpl::RemovePendingRequest(int child_id, 1611 int request_id) { 1612 LoaderMap::iterator i = pending_loaders_.find( 1613 GlobalRequestID(child_id, request_id)); 1614 if (i == pending_loaders_.end()) { 1615 NOTREACHED() << "Trying to remove a request that's not here"; 1616 return; 1617 } 1618 RemovePendingLoader(i); 1619} 1620 1621void ResourceDispatcherHostImpl::RemovePendingLoader( 1622 const LoaderMap::iterator& iter) { 1623 ResourceRequestInfoImpl* info = iter->second->GetRequestInfo(); 1624 1625 // Remove the memory credit that we added when pushing the request onto 1626 // the pending list. 1627 IncrementOutstandingRequestsMemory(-1, *info); 1628 1629 pending_loaders_.erase(iter); 1630 1631 // If we have no more pending requests, then stop the load state monitor 1632 if (pending_loaders_.empty() && update_load_states_timer_) 1633 update_load_states_timer_->Stop(); 1634} 1635 1636void ResourceDispatcherHostImpl::CancelRequest(int child_id, 1637 int request_id) { 1638 ResourceLoader* loader = GetLoader(child_id, request_id); 1639 if (!loader) { 1640 // We probably want to remove this warning eventually, but I wanted to be 1641 // able to notice when this happens during initial development since it 1642 // should be rare and may indicate a bug. 1643 DVLOG(1) << "Canceling a request that wasn't found"; 1644 return; 1645 } 1646 1647 RemovePendingRequest(child_id, request_id); 1648} 1649 1650ResourceDispatcherHostImpl::OustandingRequestsStats 1651ResourceDispatcherHostImpl::GetOutstandingRequestsStats( 1652 const ResourceRequestInfoImpl& info) { 1653 OutstandingRequestsStatsMap::iterator entry = 1654 outstanding_requests_stats_map_.find(info.GetChildID()); 1655 OustandingRequestsStats stats = { 0, 0 }; 1656 if (entry != outstanding_requests_stats_map_.end()) 1657 stats = entry->second; 1658 return stats; 1659} 1660 1661void ResourceDispatcherHostImpl::UpdateOutstandingRequestsStats( 1662 const ResourceRequestInfoImpl& info, 1663 const OustandingRequestsStats& stats) { 1664 if (stats.memory_cost == 0 && stats.num_requests == 0) 1665 outstanding_requests_stats_map_.erase(info.GetChildID()); 1666 else 1667 outstanding_requests_stats_map_[info.GetChildID()] = stats; 1668} 1669 1670ResourceDispatcherHostImpl::OustandingRequestsStats 1671ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemory( 1672 int count, 1673 const ResourceRequestInfoImpl& info) { 1674 DCHECK_EQ(1, abs(count)); 1675 1676 // Retrieve the previous value (defaulting to 0 if not found). 1677 OustandingRequestsStats stats = GetOutstandingRequestsStats(info); 1678 1679 // Insert/update the total; delete entries when their count reaches 0. 1680 stats.memory_cost += count * info.memory_cost(); 1681 DCHECK_GE(stats.memory_cost, 0); 1682 UpdateOutstandingRequestsStats(info, stats); 1683 1684 return stats; 1685} 1686 1687ResourceDispatcherHostImpl::OustandingRequestsStats 1688ResourceDispatcherHostImpl::IncrementOutstandingRequestsCount( 1689 int count, 1690 const ResourceRequestInfoImpl& info) { 1691 DCHECK_EQ(1, abs(count)); 1692 num_in_flight_requests_ += count; 1693 1694 OustandingRequestsStats stats = GetOutstandingRequestsStats(info); 1695 stats.num_requests += count; 1696 DCHECK_GE(stats.num_requests, 0); 1697 UpdateOutstandingRequestsStats(info, stats); 1698 1699 return stats; 1700} 1701 1702bool ResourceDispatcherHostImpl::HasSufficientResourcesForRequest( 1703 const net::URLRequest* request_) { 1704 const ResourceRequestInfoImpl* info = 1705 ResourceRequestInfoImpl::ForRequest(request_); 1706 OustandingRequestsStats stats = IncrementOutstandingRequestsCount(1, *info); 1707 1708 if (stats.num_requests > max_num_in_flight_requests_per_process_) 1709 return false; 1710 if (num_in_flight_requests_ > max_num_in_flight_requests_) 1711 return false; 1712 1713 return true; 1714} 1715 1716void ResourceDispatcherHostImpl::FinishedWithResourcesForRequest( 1717 const net::URLRequest* request_) { 1718 const ResourceRequestInfoImpl* info = 1719 ResourceRequestInfoImpl::ForRequest(request_); 1720 IncrementOutstandingRequestsCount(-1, *info); 1721} 1722 1723void ResourceDispatcherHostImpl::StartNavigationRequest( 1724 const NavigationRequestInfo& info, 1725 scoped_refptr<ResourceRequestBody> request_body, 1726 int64 navigation_request_id, 1727 int64 frame_node_id) { 1728 NOTIMPLEMENTED(); 1729} 1730 1731void ResourceDispatcherHostImpl::CancelNavigationRequest( 1732 int64 navigation_request_id, 1733 int64 frame_node_id) { 1734 NOTIMPLEMENTED(); 1735} 1736 1737// static 1738int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost( 1739 net::URLRequest* request) { 1740 // The following fields should be a minor size contribution (experimentally 1741 // on the order of 100). However since they are variable length, it could 1742 // in theory be a sizeable contribution. 1743 int strings_cost = request->extra_request_headers().ToString().size() + 1744 request->original_url().spec().size() + 1745 request->referrer().size() + 1746 request->method().size(); 1747 1748 // Note that this expression will typically be dominated by: 1749 // |kAvgBytesPerOutstandingRequest|. 1750 return kAvgBytesPerOutstandingRequest + strings_cost; 1751} 1752 1753void ResourceDispatcherHostImpl::BeginRequestInternal( 1754 scoped_ptr<net::URLRequest> request, 1755 scoped_ptr<ResourceHandler> handler) { 1756 DCHECK(!request->is_pending()); 1757 ResourceRequestInfoImpl* info = 1758 ResourceRequestInfoImpl::ForRequest(request.get()); 1759 1760 if ((TimeTicks::Now() - last_user_gesture_time_) < 1761 TimeDelta::FromMilliseconds(kUserGestureWindowMs)) { 1762 request->SetLoadFlags( 1763 request->load_flags() | net::LOAD_MAYBE_USER_GESTURE); 1764 } 1765 1766 // Add the memory estimate that starting this request will consume. 1767 info->set_memory_cost(CalculateApproximateMemoryCost(request.get())); 1768 1769 // If enqueing/starting this request will exceed our per-process memory 1770 // bound, abort it right away. 1771 OustandingRequestsStats stats = IncrementOutstandingRequestsMemory(1, *info); 1772 if (stats.memory_cost > max_outstanding_requests_cost_per_process_) { 1773 // We call "CancelWithError()" as a way of setting the net::URLRequest's 1774 // status -- it has no effect beyond this, since the request hasn't started. 1775 request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); 1776 1777 bool defer = false; 1778 handler->OnResponseCompleted(request->status(), std::string(), &defer); 1779 if (defer) { 1780 // TODO(darin): The handler is not ready for us to kill the request. Oops! 1781 NOTREACHED(); 1782 } 1783 1784 IncrementOutstandingRequestsMemory(-1, *info); 1785 1786 // A ResourceHandler must not outlive its associated URLRequest. 1787 handler.reset(); 1788 return; 1789 } 1790 1791 linked_ptr<ResourceLoader> loader( 1792 new ResourceLoader(request.Pass(), handler.Pass(), this)); 1793 1794 GlobalRoutingID id(info->GetGlobalRoutingID()); 1795 BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(id); 1796 if (iter != blocked_loaders_map_.end()) { 1797 // The request should be blocked. 1798 iter->second->push_back(loader); 1799 return; 1800 } 1801 1802 StartLoading(info, loader); 1803} 1804 1805void ResourceDispatcherHostImpl::StartLoading( 1806 ResourceRequestInfoImpl* info, 1807 const linked_ptr<ResourceLoader>& loader) { 1808 pending_loaders_[info->GetGlobalRequestID()] = loader; 1809 1810 loader->StartRequest(); 1811} 1812 1813void ResourceDispatcherHostImpl::OnUserGesture(WebContentsImpl* contents) { 1814 last_user_gesture_time_ = TimeTicks::Now(); 1815} 1816 1817net::URLRequest* ResourceDispatcherHostImpl::GetURLRequest( 1818 const GlobalRequestID& id) { 1819 ResourceLoader* loader = GetLoader(id); 1820 if (!loader) 1821 return NULL; 1822 1823 return loader->request(); 1824} 1825 1826namespace { 1827 1828// This function attempts to return the "more interesting" load state of |a| 1829// and |b|. We don't have temporal information about these load states 1830// (meaning we don't know when we transitioned into these states), so we just 1831// rank them according to how "interesting" the states are. 1832// 1833// We take advantage of the fact that the load states are an enumeration listed 1834// in the order in which they occur during the lifetime of a request, so we can 1835// regard states with larger numeric values as being further along toward 1836// completion. We regard those states as more interesting to report since they 1837// represent progress. 1838// 1839// For example, by this measure "tranferring data" is a more interesting state 1840// than "resolving host" because when we are transferring data we are actually 1841// doing something that corresponds to changes that the user might observe, 1842// whereas waiting for a host name to resolve implies being stuck. 1843// 1844const net::LoadStateWithParam& MoreInterestingLoadState( 1845 const net::LoadStateWithParam& a, const net::LoadStateWithParam& b) { 1846 return (a.state < b.state) ? b : a; 1847} 1848 1849// Carries information about a load state change. 1850struct LoadInfo { 1851 GURL url; 1852 net::LoadStateWithParam load_state; 1853 uint64 upload_position; 1854 uint64 upload_size; 1855}; 1856 1857// Map from ProcessID+RouteID pair to LoadState 1858typedef std::map<GlobalRoutingID, LoadInfo> LoadInfoMap; 1859 1860// Used to marshal calls to LoadStateChanged from the IO to UI threads. We do 1861// them all as a single callback to avoid spamming the UI thread. 1862void LoadInfoUpdateCallback(const LoadInfoMap& info_map) { 1863 LoadInfoMap::const_iterator i; 1864 for (i = info_map.begin(); i != info_map.end(); ++i) { 1865 RenderViewHostImpl* view = 1866 RenderViewHostImpl::FromID(i->first.child_id, i->first.route_id); 1867 if (view) // The view could be gone at this point. 1868 view->LoadStateChanged(i->second.url, i->second.load_state, 1869 i->second.upload_position, 1870 i->second.upload_size); 1871 } 1872} 1873 1874} // namespace 1875 1876void ResourceDispatcherHostImpl::UpdateLoadStates() { 1877 // Populate this map with load state changes, and then send them on to the UI 1878 // thread where they can be passed along to the respective RVHs. 1879 LoadInfoMap info_map; 1880 1881 LoaderMap::const_iterator i; 1882 1883 // Determine the largest upload size of all requests 1884 // in each View (good chance it's zero). 1885 std::map<GlobalRoutingID, uint64> largest_upload_size; 1886 for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) { 1887 net::URLRequest* request = i->second->request(); 1888 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); 1889 uint64 upload_size = request->GetUploadProgress().size(); 1890 if (request->GetLoadState().state != net::LOAD_STATE_SENDING_REQUEST) 1891 upload_size = 0; 1892 GlobalRoutingID id(info->GetGlobalRoutingID()); 1893 if (upload_size && largest_upload_size[id] < upload_size) 1894 largest_upload_size[id] = upload_size; 1895 } 1896 1897 for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) { 1898 net::URLRequest* request = i->second->request(); 1899 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); 1900 net::LoadStateWithParam load_state = request->GetLoadState(); 1901 net::UploadProgress progress = request->GetUploadProgress(); 1902 1903 // We also poll for upload progress on this timer and send upload 1904 // progress ipc messages to the plugin process. 1905 i->second->ReportUploadProgress(); 1906 1907 GlobalRoutingID id(info->GetGlobalRoutingID()); 1908 1909 // If a request is uploading data, ignore all other requests so that the 1910 // upload progress takes priority for being shown in the status bar. 1911 if (largest_upload_size.find(id) != largest_upload_size.end() && 1912 progress.size() < largest_upload_size[id]) 1913 continue; 1914 1915 net::LoadStateWithParam to_insert = load_state; 1916 LoadInfoMap::iterator existing = info_map.find(id); 1917 if (existing != info_map.end()) { 1918 to_insert = 1919 MoreInterestingLoadState(existing->second.load_state, load_state); 1920 if (to_insert.state == existing->second.load_state.state) 1921 continue; 1922 } 1923 LoadInfo& load_info = info_map[id]; 1924 load_info.url = request->url(); 1925 load_info.load_state = to_insert; 1926 load_info.upload_size = progress.size(); 1927 load_info.upload_position = progress.position(); 1928 } 1929 1930 if (info_map.empty()) 1931 return; 1932 1933 BrowserThread::PostTask( 1934 BrowserThread::UI, FROM_HERE, 1935 base::Bind(&LoadInfoUpdateCallback, info_map)); 1936} 1937 1938void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id, 1939 int route_id) { 1940 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1941 GlobalRoutingID key(child_id, route_id); 1942 DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) << 1943 "BlockRequestsForRoute called multiple time for the same RVH"; 1944 blocked_loaders_map_[key] = new BlockedLoadersList(); 1945} 1946 1947void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(int child_id, 1948 int route_id) { 1949 ProcessBlockedRequestsForRoute(child_id, route_id, false); 1950} 1951 1952void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(int child_id, 1953 int route_id) { 1954 ProcessBlockedRequestsForRoute(child_id, route_id, true); 1955} 1956 1957void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute( 1958 int child_id, 1959 int route_id, 1960 bool cancel_requests) { 1961 BlockedLoadersMap::iterator iter = blocked_loaders_map_.find( 1962 GlobalRoutingID(child_id, route_id)); 1963 if (iter == blocked_loaders_map_.end()) { 1964 // It's possible to reach here if the renderer crashed while an interstitial 1965 // page was showing. 1966 return; 1967 } 1968 1969 BlockedLoadersList* loaders = iter->second; 1970 1971 // Removing the vector from the map unblocks any subsequent requests. 1972 blocked_loaders_map_.erase(iter); 1973 1974 for (BlockedLoadersList::iterator loaders_iter = loaders->begin(); 1975 loaders_iter != loaders->end(); ++loaders_iter) { 1976 linked_ptr<ResourceLoader> loader = *loaders_iter; 1977 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 1978 if (cancel_requests) { 1979 IncrementOutstandingRequestsMemory(-1, *info); 1980 } else { 1981 StartLoading(info, loader); 1982 } 1983 } 1984 1985 delete loaders; 1986} 1987 1988ResourceDispatcherHostImpl::HttpAuthRelationType 1989ResourceDispatcherHostImpl::HttpAuthRelationTypeOf( 1990 const GURL& request_url, 1991 const GURL& first_party) { 1992 if (!first_party.is_valid()) 1993 return HTTP_AUTH_RELATION_TOP; 1994 1995 if (net::registry_controlled_domains::SameDomainOrHost( 1996 first_party, request_url, 1997 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) 1998 return HTTP_AUTH_RELATION_SAME_DOMAIN; 1999 2000 if (allow_cross_origin_auth_prompt()) 2001 return HTTP_AUTH_RELATION_ALLOWED_CROSS; 2002 2003 return HTTP_AUTH_RELATION_BLOCKED_CROSS; 2004} 2005 2006bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() { 2007 return allow_cross_origin_auth_prompt_; 2008} 2009 2010bool ResourceDispatcherHostImpl::IsTransferredNavigation( 2011 const GlobalRequestID& id) const { 2012 ResourceLoader* loader = GetLoader(id); 2013 return loader ? loader->is_transferring() : false; 2014} 2015 2016ResourceLoader* ResourceDispatcherHostImpl::GetLoader( 2017 const GlobalRequestID& id) const { 2018 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2019 2020 LoaderMap::const_iterator i = pending_loaders_.find(id); 2021 if (i == pending_loaders_.end()) 2022 return NULL; 2023 2024 return i->second.get(); 2025} 2026 2027ResourceLoader* ResourceDispatcherHostImpl::GetLoader(int child_id, 2028 int request_id) const { 2029 return GetLoader(GlobalRequestID(child_id, request_id)); 2030} 2031 2032void ResourceDispatcherHostImpl::RegisterResourceMessageDelegate( 2033 const GlobalRequestID& id, ResourceMessageDelegate* delegate) { 2034 DelegateMap::iterator it = delegate_map_.find(id); 2035 if (it == delegate_map_.end()) { 2036 it = delegate_map_.insert( 2037 std::make_pair(id, new ObserverList<ResourceMessageDelegate>)).first; 2038 } 2039 it->second->AddObserver(delegate); 2040} 2041 2042void ResourceDispatcherHostImpl::UnregisterResourceMessageDelegate( 2043 const GlobalRequestID& id, ResourceMessageDelegate* delegate) { 2044 DCHECK(ContainsKey(delegate_map_, id)); 2045 DelegateMap::iterator it = delegate_map_.find(id); 2046 DCHECK(it->second->HasObserver(delegate)); 2047 it->second->RemoveObserver(delegate); 2048 if (!it->second->might_have_observers()) { 2049 delete it->second; 2050 delegate_map_.erase(it); 2051 } 2052} 2053 2054int ResourceDispatcherHostImpl::BuildLoadFlagsForRequest( 2055 const ResourceHostMsg_Request& request_data, 2056 int child_id, 2057 bool is_sync_load) { 2058 int load_flags = request_data.load_flags; 2059 2060 // Although EV status is irrelevant to sub-frames and sub-resources, we have 2061 // to perform EV certificate verification on all resources because an HTTP 2062 // keep-alive connection created to load a sub-frame or a sub-resource could 2063 // be reused to load a main frame. 2064 load_flags |= net::LOAD_VERIFY_EV_CERT; 2065 if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME) { 2066 load_flags |= net::LOAD_MAIN_FRAME; 2067 } else if (request_data.resource_type == RESOURCE_TYPE_SUB_FRAME) { 2068 load_flags |= net::LOAD_SUB_FRAME; 2069 } else if (request_data.resource_type == RESOURCE_TYPE_PREFETCH) { 2070 load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); 2071 } else if (request_data.resource_type == RESOURCE_TYPE_FAVICON) { 2072 load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN; 2073 } else if (request_data.resource_type == RESOURCE_TYPE_IMAGE) { 2074 // Prevent third-party image content from prompting for login, as this 2075 // is often a scam to extract credentials for another domain from the user. 2076 // Only block image loads, as the attack applies largely to the "src" 2077 // property of the <img> tag. It is common for web properties to allow 2078 // untrusted values for <img src>; this is considered a fair thing for an 2079 // HTML sanitizer to do. Conversely, any HTML sanitizer that didn't 2080 // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags 2081 // would be considered vulnerable in and of itself. 2082 HttpAuthRelationType relation_type = HttpAuthRelationTypeOf( 2083 request_data.url, request_data.first_party_for_cookies); 2084 if (relation_type == HTTP_AUTH_RELATION_BLOCKED_CROSS) { 2085 load_flags |= (net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY | 2086 net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); 2087 } 2088 } 2089 2090 if (is_sync_load) 2091 load_flags |= net::LOAD_IGNORE_LIMITS; 2092 2093 ChildProcessSecurityPolicyImpl* policy = 2094 ChildProcessSecurityPolicyImpl::GetInstance(); 2095 if (!policy->CanSendCookiesForOrigin(child_id, request_data.url)) { 2096 load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | 2097 net::LOAD_DO_NOT_SEND_AUTH_DATA | 2098 net::LOAD_DO_NOT_SAVE_COOKIES); 2099 } 2100 2101 // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only 2102 // allow requesting them if requester has ReadRawCookies permission. 2103 if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) 2104 && !policy->CanReadRawCookies(child_id)) { 2105 VLOG(1) << "Denied unauthorized request for raw headers"; 2106 load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; 2107 } 2108 2109 // Add a flag to selectively bypass the data reduction proxy if the resource 2110 // type is not an image. 2111 if (request_data.resource_type != RESOURCE_TYPE_IMAGE) 2112 load_flags |= net::LOAD_BYPASS_DATA_REDUCTION_PROXY; 2113 2114 return load_flags; 2115} 2116 2117} // namespace content 2118