Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading |
| 6 | 6 |
| 7 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" | 7 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 37 #include "content/browser/renderer_host/cross_site_resource_handler.h" | 37 #include "content/browser/renderer_host/cross_site_resource_handler.h" |
| 38 #include "content/browser/renderer_host/redirect_to_file_resource_handler.h" | 38 #include "content/browser/renderer_host/redirect_to_file_resource_handler.h" |
| 39 #include "content/browser/renderer_host/render_view_host_delegate.h" | 39 #include "content/browser/renderer_host/render_view_host_delegate.h" |
| 40 #include "content/browser/renderer_host/render_view_host_impl.h" | 40 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 41 #include "content/browser/renderer_host/resource_message_filter.h" | 41 #include "content/browser/renderer_host/resource_message_filter.h" |
| 42 #include "content/browser/renderer_host/transfer_navigation_resource_throttle.h" | 42 #include "content/browser/renderer_host/transfer_navigation_resource_throttle.h" |
| 43 #include "content/browser/renderer_host/resource_request_info_impl.h" | 43 #include "content/browser/renderer_host/resource_request_info_impl.h" |
| 44 #include "content/browser/renderer_host/sync_resource_handler.h" | 44 #include "content/browser/renderer_host/sync_resource_handler.h" |
| 45 #include "content/browser/renderer_host/throttling_resource_handler.h" | 45 #include "content/browser/renderer_host/throttling_resource_handler.h" |
| 46 #include "content/browser/resource_context_impl.h" | 46 #include "content/browser/resource_context_impl.h" |
| 47 #include "content/browser/ssl/ssl_client_auth_handler.h" | |
| 48 #include "content/browser/ssl/ssl_manager.h" | |
| 49 #include "content/browser/worker_host/worker_service_impl.h" | 47 #include "content/browser/worker_host/worker_service_impl.h" |
| 50 #include "content/common/resource_messages.h" | 48 #include "content/common/resource_messages.h" |
| 51 #include "content/common/ssl_status_serialization.h" | 49 #include "content/common/ssl_status_serialization.h" |
| 52 #include "content/common/view_messages.h" | 50 #include "content/common/view_messages.h" |
| 53 #include "content/public/browser/browser_thread.h" | 51 #include "content/public/browser/browser_thread.h" |
| 54 #include "content/public/browser/content_browser_client.h" | 52 #include "content/public/browser/content_browser_client.h" |
| 55 #include "content/public/browser/download_manager.h" | 53 #include "content/public/browser/download_manager.h" |
| 56 #include "content/public/browser/global_request_id.h" | 54 #include "content/public/browser/global_request_id.h" |
| 57 #include "content/public/browser/notification_service.h" | 55 #include "content/public/browser/notification_service.h" |
| 58 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 56 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
| 59 #include "content/public/browser/resource_dispatcher_host_login_delegate.h" | |
| 60 #include "content/public/browser/resource_request_details.h" | 57 #include "content/public/browser/resource_request_details.h" |
| 61 #include "content/public/browser/resource_throttle.h" | 58 #include "content/public/browser/resource_throttle.h" |
| 59 #include "content/public/browser/user_metrics.h" | |
| 62 #include "content/public/common/content_switches.h" | 60 #include "content/public/common/content_switches.h" |
| 63 #include "content/public/common/process_type.h" | 61 #include "content/public/common/process_type.h" |
| 64 #include "content/public/common/url_constants.h" | 62 #include "content/public/common/url_constants.h" |
| 65 #include "net/base/auth.h" | 63 #include "net/base/auth.h" |
| 66 #include "net/base/cert_status_flags.h" | 64 #include "net/base/cert_status_flags.h" |
| 67 #include "net/base/load_flags.h" | 65 #include "net/base/load_flags.h" |
| 68 #include "net/base/mime_util.h" | 66 #include "net/base/mime_util.h" |
| 69 #include "net/base/net_errors.h" | 67 #include "net/base/net_errors.h" |
| 70 #include "net/base/registry_controlled_domain.h" | 68 #include "net/base/registry_controlled_domain.h" |
| 71 #include "net/base/request_priority.h" | 69 #include "net/base/request_priority.h" |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 NOTREACHED() << "Denied unauthorized upload of " | 184 NOTREACHED() << "Denied unauthorized upload of " |
| 187 << iter->file_path().value(); | 185 << iter->file_path().value(); |
| 188 return false; | 186 return false; |
| 189 } | 187 } |
| 190 } | 188 } |
| 191 } | 189 } |
| 192 | 190 |
| 193 return true; | 191 return true; |
| 194 } | 192 } |
| 195 | 193 |
| 196 void PopulateResourceResponse(net::URLRequest* request, | |
| 197 ResourceResponse* response) { | |
| 198 response->status = request->status(); | |
| 199 response->request_time = request->request_time(); | |
| 200 response->response_time = request->response_time(); | |
| 201 response->headers = request->response_headers(); | |
| 202 request->GetCharset(&response->charset); | |
| 203 response->content_length = request->GetExpectedContentSize(); | |
| 204 request->GetMimeType(&response->mime_type); | |
| 205 net::HttpResponseInfo response_info = request->response_info(); | |
| 206 response->was_fetched_via_spdy = response_info.was_fetched_via_spdy; | |
| 207 response->was_npn_negotiated = response_info.was_npn_negotiated; | |
| 208 response->npn_negotiated_protocol = response_info.npn_negotiated_protocol; | |
| 209 response->was_fetched_via_proxy = request->was_fetched_via_proxy(); | |
| 210 response->socket_address = request->GetSocketAddress(); | |
| 211 appcache::AppCacheInterceptor::GetExtraResponseInfo( | |
| 212 request, | |
| 213 &response->appcache_id, | |
| 214 &response->appcache_manifest_url); | |
| 215 } | |
| 216 | |
| 217 void RemoveDownloadFileFromChildSecurityPolicy(int child_id, | 194 void RemoveDownloadFileFromChildSecurityPolicy(int child_id, |
| 218 const FilePath& path) { | 195 const FilePath& path) { |
| 219 ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile( | 196 ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile( |
| 220 child_id, path); | 197 child_id, path); |
| 221 } | 198 } |
| 222 | 199 |
| 223 #if defined(OS_WIN) | 200 #if defined(OS_WIN) |
| 224 #pragma warning(disable: 4748) | 201 #pragma warning(disable: 4748) |
| 225 #pragma optimize("", off) | 202 #pragma optimize("", off) |
| 226 #endif | 203 #endif |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 net::Error net_error) { | 278 net::Error net_error) { |
| 302 if (started_cb.is_null()) | 279 if (started_cb.is_null()) |
| 303 return net_error; | 280 return net_error; |
| 304 BrowserThread::PostTask( | 281 BrowserThread::PostTask( |
| 305 BrowserThread::UI, FROM_HERE, | 282 BrowserThread::UI, FROM_HERE, |
| 306 base::Bind(started_cb, DownloadId::Invalid(), net_error)); | 283 base::Bind(started_cb, DownloadId::Invalid(), net_error)); |
| 307 | 284 |
| 308 return net_error; | 285 return net_error; |
| 309 } | 286 } |
| 310 | 287 |
| 288 int BuildLoadFlagsForRequest(const ResourceHostMsg_Request& request_data, | |
| 289 int child_id, bool is_sync_load) { | |
| 290 int load_flags = request_data.load_flags; | |
| 291 | |
| 292 // Although EV status is irrelevant to sub-frames and sub-resources, we have | |
| 293 // to perform EV certificate verification on all resources because an HTTP | |
| 294 // keep-alive connection created to load a sub-frame or a sub-resource could | |
| 295 // be reused to load a main frame. | |
| 296 load_flags |= net::LOAD_VERIFY_EV_CERT; | |
| 297 if (request_data.resource_type == ResourceType::MAIN_FRAME) { | |
| 298 load_flags |= net::LOAD_MAIN_FRAME; | |
| 299 } else if (request_data.resource_type == ResourceType::SUB_FRAME) { | |
| 300 load_flags |= net::LOAD_SUB_FRAME; | |
| 301 } else if (request_data.resource_type == ResourceType::PREFETCH) { | |
| 302 load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); | |
| 303 } else if (request_data.resource_type == ResourceType::FAVICON) { | |
| 304 load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN; | |
| 305 } | |
| 306 | |
| 307 if (is_sync_load) | |
| 308 load_flags |= net::LOAD_IGNORE_LIMITS; | |
| 309 | |
| 310 ChildProcessSecurityPolicyImpl* policy = | |
| 311 ChildProcessSecurityPolicyImpl::GetInstance(); | |
| 312 if (!policy->CanUseCookiesForOrigin(child_id, request_data.url)) { | |
| 313 load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | | |
| 314 net::LOAD_DO_NOT_SEND_AUTH_DATA | | |
| 315 net::LOAD_DO_NOT_SAVE_COOKIES); | |
| 316 } | |
| 317 | |
| 318 // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only | |
| 319 // allow requesting them if requester has ReadRawCookies permission. | |
| 320 if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) | |
| 321 && !policy->CanReadRawCookies(child_id)) { | |
| 322 VLOG(1) << "Denied unauthorized request for raw headers"; | |
| 323 load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; | |
| 324 } | |
| 325 | |
| 326 return load_flags; | |
| 327 } | |
| 328 | |
| 329 int GetCertID(net::URLRequest* request, int child_id) { | |
| 330 if (request->ssl_info().cert) { | |
| 331 return CertStore::GetInstance()->StoreCert(request->ssl_info().cert, | |
| 332 child_id); | |
| 333 } | |
| 334 return 0; | |
| 335 } | |
| 336 | |
| 337 template <class T> | |
| 338 void NotifyOnUI(int type, int render_process_id, int render_view_id, | |
| 339 scoped_ptr<T> detail) { | |
| 340 RenderViewHostImpl* host = | |
| 341 RenderViewHostImpl::FromID(render_process_id, render_view_id); | |
| 342 if (host) { | |
| 343 RenderViewHostDelegate* delegate = host->GetDelegate(); | |
| 344 NotificationService::current()->Notify( | |
| 345 type, Source<WebContents>(delegate->GetAsWebContents()), | |
| 346 Details<T>(detail.get())); | |
| 347 } | |
| 348 } | |
| 349 | |
| 311 } // namespace | 350 } // namespace |
| 312 | 351 |
| 313 // static | 352 // static |
| 314 ResourceDispatcherHost* ResourceDispatcherHost::Get() { | 353 ResourceDispatcherHost* ResourceDispatcherHost::Get() { |
| 315 return g_resource_dispatcher_host; | 354 return g_resource_dispatcher_host; |
| 316 } | 355 } |
| 317 | 356 |
| 318 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() | 357 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() |
| 319 : download_file_manager_(new DownloadFileManager(NULL)), | 358 : download_file_manager_(new DownloadFileManager(NULL)), |
| 320 save_file_manager_(new SaveFileManager()), | 359 save_file_manager_(new SaveFileManager()), |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 340 base::Bind(&appcache::AppCacheInterceptor::EnsureRegistered)); | 379 base::Bind(&appcache::AppCacheInterceptor::EnsureRegistered)); |
| 341 | 380 |
| 342 update_load_states_timer_.reset( | 381 update_load_states_timer_.reset( |
| 343 new base::RepeatingTimer<ResourceDispatcherHostImpl>()); | 382 new base::RepeatingTimer<ResourceDispatcherHostImpl>()); |
| 344 } | 383 } |
| 345 | 384 |
| 346 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { | 385 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { |
| 347 DCHECK(g_resource_dispatcher_host); | 386 DCHECK(g_resource_dispatcher_host); |
| 348 g_resource_dispatcher_host = NULL; | 387 g_resource_dispatcher_host = NULL; |
| 349 AsyncResourceHandler::GlobalCleanup(); | 388 AsyncResourceHandler::GlobalCleanup(); |
| 350 for (PendingRequestList::const_iterator i = pending_requests_.begin(); | |
| 351 i != pending_requests_.end(); ++i) { | |
| 352 transferred_navigations_.erase(i->first); | |
| 353 } | |
| 354 STLDeleteValues(&pending_requests_); | |
| 355 DCHECK(transferred_navigations_.empty()); | |
| 356 } | 389 } |
| 357 | 390 |
| 358 // static | 391 // static |
| 359 ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { | 392 ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { |
| 360 return g_resource_dispatcher_host; | 393 return g_resource_dispatcher_host; |
| 361 } | 394 } |
| 362 | 395 |
| 363 void ResourceDispatcherHostImpl::SetDelegate( | 396 void ResourceDispatcherHostImpl::SetDelegate( |
| 364 ResourceDispatcherHostDelegate* delegate) { | 397 ResourceDispatcherHostDelegate* delegate) { |
| 365 delegate_ = delegate; | 398 delegate_ = delegate; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 383 ResourceContext* context) { | 416 ResourceContext* context) { |
| 384 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 385 DCHECK(context); | 418 DCHECK(context); |
| 386 | 419 |
| 387 CHECK(ContainsKey(active_resource_contexts_, context)); | 420 CHECK(ContainsKey(active_resource_contexts_, context)); |
| 388 | 421 |
| 389 // Note that request cancellation has side effects. Therefore, we gather all | 422 // Note that request cancellation has side effects. Therefore, we gather all |
| 390 // the requests to cancel first, and then we start cancelling. We assert at | 423 // the requests to cancel first, and then we start cancelling. We assert at |
| 391 // the end that there are no more to cancel since the context is about to go | 424 // the end that there are no more to cancel since the context is about to go |
| 392 // away. | 425 // away. |
| 393 std::vector<net::URLRequest*> requests_to_cancel; | 426 typedef std::vector<linked_ptr<ResourceLoader> > LoaderList; |
| 394 for (PendingRequestList::iterator i = pending_requests_.begin(); | 427 LoaderList loaders_to_cancel; |
| 395 i != pending_requests_.end();) { | 428 |
| 396 ResourceRequestInfoImpl* info = | 429 for (LoaderMap::iterator i = pending_loaders_.begin(); |
| 397 ResourceRequestInfoImpl::ForRequest(i->second); | 430 i != pending_loaders_.end();) { |
| 398 if (info->GetContext() == context) { | 431 if (i->second->GetRequestInfo()->GetContext() == context) { |
| 399 requests_to_cancel.push_back(i->second); | 432 loaders_to_cancel.push_back(i->second); |
| 400 pending_requests_.erase(i++); | 433 pending_loaders_.erase(i++); |
| 401 } else { | 434 } else { |
| 402 ++i; | 435 ++i; |
| 403 } | 436 } |
| 404 } | 437 } |
| 405 | 438 |
| 406 for (BlockedRequestMap::iterator i = blocked_requests_map_.begin(); | 439 for (BlockedLoadersMap::iterator i = blocked_loaders_map_.begin(); |
| 407 i != blocked_requests_map_.end();) { | 440 i != blocked_loaders_map_.end();) { |
| 408 BlockedRequestsList* requests = i->second; | 441 BlockedLoadersList* loaders = i->second; |
| 409 if (requests->empty()) { | 442 if (loaders->empty()) { |
| 410 // This can happen if BlockRequestsForRoute() has been called for a route, | 443 // This can happen if BlockRequestsForRoute() has been called for a route, |
| 411 // but we haven't blocked any matching requests yet. | 444 // but we haven't blocked any matching requests yet. |
| 412 ++i; | 445 ++i; |
| 413 continue; | 446 continue; |
| 414 } | 447 } |
| 415 ResourceRequestInfoImpl* info = | 448 ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo(); |
| 416 ResourceRequestInfoImpl::ForRequest(requests->front()); | |
| 417 if (info->GetContext() == context) { | 449 if (info->GetContext() == context) { |
| 418 blocked_requests_map_.erase(i++); | 450 blocked_loaders_map_.erase(i++); |
| 419 for (BlockedRequestsList::const_iterator it = requests->begin(); | 451 for (BlockedLoadersList::const_iterator it = loaders->begin(); |
| 420 it != requests->end(); ++it) { | 452 it != loaders->end(); ++it) { |
| 421 net::URLRequest* request = *it; | 453 linked_ptr<ResourceLoader> loader = *it; |
| 422 info = ResourceRequestInfoImpl::ForRequest(request); | 454 info = loader->GetRequestInfo(); |
| 423 // We make the assumption that all requests on the list have the same | 455 // We make the assumption that all requests on the list have the same |
| 424 // ResourceContext. | 456 // ResourceContext. |
| 425 DCHECK_EQ(context, info->GetContext()); | 457 DCHECK_EQ(context, info->GetContext()); |
| 426 IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), | 458 IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), |
| 427 info->GetChildID()); | 459 info->GetChildID()); |
| 428 requests_to_cancel.push_back(request); | 460 loaders_to_cancel.push_back(loader); |
| 429 } | 461 } |
| 430 delete requests; | 462 delete loaders; |
| 431 } else { | 463 } else { |
| 432 ++i; | 464 ++i; |
| 433 } | 465 } |
| 434 } | 466 } |
| 435 | 467 |
| 436 for (std::vector<net::URLRequest*>::iterator i = requests_to_cancel.begin(); | 468 #ifndef NDEBUG |
| 437 i != requests_to_cancel.end(); ++i) { | 469 for (LoaderList::iterator i = loaders_to_cancel.begin(); |
| 438 net::URLRequest* request = *i; | 470 i != loaders_to_cancel.end(); ++i) { |
| 439 ResourceRequestInfoImpl* info = | |
| 440 ResourceRequestInfoImpl::ForRequest(request); | |
| 441 // There is no strict requirement that this be the case, but currently | 471 // There is no strict requirement that this be the case, but currently |
| 442 // downloads and transferred requests are the only requests that aren't | 472 // downloads and transferred requests are the only requests that aren't |
| 443 // cancelled when the associated processes go away. It may be OK for this | 473 // cancelled when the associated processes go away. It may be OK for this |
| 444 // invariant to change in the future, but if this assertion fires without | 474 // invariant to change in the future, but if this assertion fires without |
| 445 // the invariant changing, then it's indicative of a leak. | 475 // the invariant changing, then it's indicative of a leak. |
| 446 GlobalRequestID request_id(info->GetChildID(), info->GetRequestID()); | 476 DCHECK((*i)->GetRequestInfo()->is_download() || (*i)->is_transferring()); |
| 447 bool is_transferred = IsTransferredNavigation(request_id); | 477 } |
| 448 DCHECK(info->is_download() || is_transferred); | 478 #endif |
| 449 if (is_transferred) | 479 |
| 450 transferred_navigations_.erase(request_id); | 480 loaders_to_cancel.clear(); |
| 451 delete request; | 481 |
| 482 // Validate that no more requests for this context were added. | |
| 483 for (LoaderMap::const_iterator i = pending_loaders_.begin(); | |
| 484 i != pending_loaders_.end(); ++i) { | |
| 485 // http://crbug.com/90971 | |
| 486 CHECK_NE(i->second->GetRequestInfo()->GetContext(), context); | |
| 452 } | 487 } |
| 453 | 488 |
| 454 // Validate that no more requests for this context were added. | 489 for (BlockedLoadersMap::const_iterator i = blocked_loaders_map_.begin(); |
| 455 for (PendingRequestList::const_iterator i = pending_requests_.begin(); | 490 i != blocked_loaders_map_.end(); ++i) { |
| 456 i != pending_requests_.end(); ++i) { | 491 BlockedLoadersList* loaders = i->second; |
| 457 ResourceRequestInfoImpl* info = | 492 if (!loaders->empty()) { |
| 458 ResourceRequestInfoImpl::ForRequest(i->second); | 493 ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo(); |
| 459 // http://crbug.com/90971 | |
| 460 CHECK_NE(info->GetContext(), context); | |
| 461 } | |
| 462 | |
| 463 for (BlockedRequestMap::const_iterator i = blocked_requests_map_.begin(); | |
| 464 i != blocked_requests_map_.end(); ++i) { | |
| 465 BlockedRequestsList* requests = i->second; | |
| 466 if (!requests->empty()) { | |
| 467 ResourceRequestInfoImpl* info = | |
| 468 ResourceRequestInfoImpl::ForRequest(requests->front()); | |
| 469 // http://crbug.com/90971 | 494 // http://crbug.com/90971 |
| 470 CHECK_NE(info->GetContext(), context); | 495 CHECK_NE(info->GetContext(), context); |
| 471 } | 496 } |
| 472 } | 497 } |
| 473 } | 498 } |
| 474 | 499 |
| 475 net::Error ResourceDispatcherHostImpl::BeginDownload( | 500 net::Error ResourceDispatcherHostImpl::BeginDownload( |
| 476 scoped_ptr<net::URLRequest> request, | 501 scoped_ptr<net::URLRequest> request, |
| 477 bool is_content_initiated, | 502 bool is_content_initiated, |
| 478 ResourceContext* context, | 503 ResourceContext* context, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 is_content_initiated, save_info, | 552 is_content_initiated, save_info, |
| 528 started_callback)); | 553 started_callback)); |
| 529 | 554 |
| 530 if (!request_context->job_factory()->IsHandledURL(url)) { | 555 if (!request_context->job_factory()->IsHandledURL(url)) { |
| 531 VLOG(1) << "Download request for unsupported protocol: " | 556 VLOG(1) << "Download request for unsupported protocol: " |
| 532 << url.possibly_invalid_spec(); | 557 << url.possibly_invalid_spec(); |
| 533 return net::ERR_ACCESS_DENIED; | 558 return net::ERR_ACCESS_DENIED; |
| 534 } | 559 } |
| 535 | 560 |
| 536 ResourceRequestInfoImpl* extra_info = | 561 ResourceRequestInfoImpl* extra_info = |
| 537 CreateRequestInfo(handler.Pass(), child_id, route_id, true, context); | 562 CreateRequestInfo(child_id, route_id, true, context); |
| 538 extra_info->AssociateWithRequest(request.get()); // Request takes ownership. | 563 extra_info->AssociateWithRequest(request.get()); // Request takes ownership. |
| 539 | 564 |
| 540 request->set_delegate(this); | 565 BeginRequestInternal(request.Pass(), handler.Pass()); |
| 541 BeginRequestInternal(request.release()); | |
| 542 | 566 |
| 543 return net::OK; | 567 return net::OK; |
| 544 } | 568 } |
| 545 | 569 |
| 546 void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( | 570 void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( |
| 547 net::URLRequest* request) { | 571 net::URLRequest* request) { |
| 548 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | 572 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); |
| 549 if (info) | 573 if (info) { |
| 550 info->set_login_delegate(NULL); | 574 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); |
| 575 if (loader) | |
| 576 loader->ClearLoginDelegate(); | |
| 577 } | |
| 578 } | |
| 579 | |
| 580 ResourceDispatcherHostLoginDelegate* | |
| 581 ResourceDispatcherHostImpl::CreateLoginDelegate( | |
| 582 ResourceLoader* loader, | |
| 583 net::AuthChallengeInfo* auth_info) { | |
| 584 if (!delegate_) | |
| 585 return NULL; | |
| 586 | |
| 587 return delegate_->CreateLoginDelegate(auth_info, loader->request()); | |
| 588 } | |
| 589 | |
| 590 bool ResourceDispatcherHostImpl::AcceptAuthRequest( | |
| 591 ResourceLoader* loader, | |
| 592 net::AuthChallengeInfo* auth_info) { | |
| 593 if (delegate_ && !delegate_->AcceptAuthRequest(loader->request(), auth_info)) | |
| 594 return false; | |
| 595 | |
| 596 // Prevent third-party content from prompting for login, unless it is | |
| 597 // a proxy that is trying to authenticate. This is often the foundation | |
| 598 // of a scam to extract credentials for another domain from the user. | |
| 599 if (!auth_info->is_proxy) { | |
| 600 HttpAuthResourceType resource_type = | |
| 601 HttpAuthResourceTypeOf(loader->request()); | |
| 602 UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthResource", | |
| 603 resource_type, | |
| 604 HTTP_AUTH_RESOURCE_LAST); | |
| 605 | |
| 606 if (resource_type == HTTP_AUTH_RESOURCE_BLOCKED_CROSS) | |
| 607 return false; | |
| 608 } | |
| 609 | |
| 610 return true; | |
| 611 } | |
| 612 | |
| 613 bool ResourceDispatcherHostImpl::AcceptSSLClientCertificateRequest( | |
| 614 ResourceLoader* loader, | |
| 615 net::SSLCertRequestInfo* cert_info) { | |
| 616 if (delegate_ && !delegate_->AcceptSSLClientCertificateRequest( | |
| 617 loader->request(), cert_info)) { | |
| 618 return false; | |
| 619 } | |
| 620 | |
| 621 return true; | |
| 622 } | |
| 623 | |
| 624 bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader, | |
| 625 const GURL& url) { | |
| 626 if (!delegate_) | |
| 627 return false; | |
| 628 | |
| 629 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | |
| 630 | |
| 631 if (!ResourceType::IsFrame(info->GetResourceType())) | |
| 632 return false; | |
| 633 | |
| 634 const net::URLRequestJobFactory* job_factory = | |
| 635 info->GetContext()->GetRequestContext()->job_factory(); | |
| 636 if (job_factory->IsHandledURL(url)) | |
| 637 return false; | |
| 638 | |
| 639 delegate_->HandleExternalProtocol(url, info->GetChildID(), | |
| 640 info->GetRouteID()); | |
| 641 return true; | |
| 642 } | |
| 643 | |
| 644 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { | |
| 645 // Make sure we have the load state monitor running | |
| 646 if (!update_load_states_timer_->IsRunning()) { | |
| 647 update_load_states_timer_->Start(FROM_HERE, | |
| 648 TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), | |
| 649 this, &ResourceDispatcherHostImpl::UpdateLoadStates); | |
| 650 } | |
| 651 } | |
| 652 | |
| 653 void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader, | |
| 654 const GURL& new_url) { | |
| 655 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | |
| 656 | |
| 657 int render_process_id, render_view_id; | |
| 658 if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) | |
| 659 return; | |
| 660 | |
| 661 // Notify the observers on the UI thread. | |
| 662 scoped_ptr<ResourceRedirectDetails> detail(new ResourceRedirectDetails( | |
| 663 loader->request(), | |
| 664 GetCertID(loader->request(), info->GetChildID()), | |
| 665 new_url)); | |
| 666 BrowserThread::PostTask( | |
| 667 BrowserThread::UI, FROM_HERE, | |
| 668 base::Bind( | |
| 669 &NotifyOnUI<ResourceRedirectDetails>, | |
| 670 static_cast<int>(NOTIFICATION_RESOURCE_RECEIVED_REDIRECT), | |
| 671 render_process_id, render_view_id, base::Passed(&detail))); | |
| 672 } | |
| 673 | |
| 674 void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) { | |
| 675 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | |
| 676 | |
| 677 int render_process_id, render_view_id; | |
| 678 if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) | |
| 679 return; | |
| 680 | |
| 681 // Notify the observers on the UI thread. | |
| 682 scoped_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails( | |
| 683 loader->request(), | |
| 684 GetCertID(loader->request(), info->GetChildID()))); | |
| 685 BrowserThread::PostTask( | |
| 686 BrowserThread::UI, FROM_HERE, | |
| 687 base::Bind( | |
| 688 &NotifyOnUI<ResourceRequestDetails>, | |
| 689 static_cast<int>(NOTIFICATION_RESOURCE_RESPONSE_STARTED), | |
| 690 render_process_id, render_view_id, base::Passed(&detail))); | |
| 691 } | |
| 692 | |
| 693 void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) { | |
| 694 ResourceRequestInfo* info = loader->GetRequestInfo(); | |
| 695 | |
| 696 // Record final result of all resource loads. | |
| 697 if (info->GetResourceType() == ResourceType::MAIN_FRAME) { | |
| 698 // This enumeration has "3" appended to its name to distinguish it from | |
| 699 // older versions. | |
| 700 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 701 "Net.ErrorCodesForMainFrame3", | |
| 702 -loader->request()->status().error(), | |
| 703 base::CustomHistogram::ArrayToCustomRanges( | |
| 704 kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); | |
| 705 | |
| 706 if (loader->request()->url().SchemeIsSecure() && | |
| 707 loader->request()->url().host() == "www.google.com") { | |
| 708 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 709 "Net.ErrorCodesForHTTPSGoogleMainFrame2", | |
| 710 -loader->request()->status().error(), | |
| 711 base::CustomHistogram::ArrayToCustomRanges( | |
| 712 kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); | |
| 713 } | |
| 714 } else { | |
| 715 // This enumeration has "2" appended to distinguish it from older versions. | |
| 716 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 717 "Net.ErrorCodesForSubresources2", | |
| 718 -loader->request()->status().error(), | |
| 719 base::CustomHistogram::ArrayToCustomRanges( | |
| 720 kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); | |
| 721 } | |
| 722 | |
| 723 // Destroy the ResourceLoader. | |
| 724 RemovePendingRequest(info->GetChildID(), info->GetRequestID()); | |
| 551 } | 725 } |
| 552 | 726 |
| 553 void ResourceDispatcherHostImpl::Shutdown() { | 727 void ResourceDispatcherHostImpl::Shutdown() { |
| 554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 728 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 555 BrowserThread::PostTask(BrowserThread::IO, | 729 BrowserThread::PostTask(BrowserThread::IO, |
| 556 FROM_HERE, | 730 FROM_HERE, |
| 557 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, | 731 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, |
| 558 base::Unretained(this))); | 732 base::Unretained(this))); |
| 559 } | 733 } |
| 560 | 734 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 571 scoped_ptr<ResourceHandler> handler( | 745 scoped_ptr<ResourceHandler> handler( |
| 572 new DownloadResourceHandler(child_id, route_id, request_id, | 746 new DownloadResourceHandler(child_id, route_id, request_id, |
| 573 request->url(), download_file_manager_, | 747 request->url(), download_file_manager_, |
| 574 request, started_cb, save_info)); | 748 request, started_cb, save_info)); |
| 575 if (delegate_) { | 749 if (delegate_) { |
| 576 ScopedVector<ResourceThrottle> throttles; | 750 ScopedVector<ResourceThrottle> throttles; |
| 577 delegate_->DownloadStarting(request, context, child_id, route_id, | 751 delegate_->DownloadStarting(request, context, child_id, route_id, |
| 578 request_id, is_content_initiated, &throttles); | 752 request_id, is_content_initiated, &throttles); |
| 579 if (!throttles.empty()) { | 753 if (!throttles.empty()) { |
| 580 handler.reset( | 754 handler.reset( |
| 581 new ThrottlingResourceHandler(this, handler.Pass(), child_id, | 755 new ThrottlingResourceHandler(handler.Pass(), child_id, request_id, |
| 582 request_id, throttles.Pass())); | 756 throttles.Pass())); |
| 583 } | 757 } |
| 584 } | 758 } |
| 585 return handler.Pass(); | 759 return handler.Pass(); |
| 586 } | 760 } |
| 587 | 761 |
| 762 void ResourceDispatcherHostImpl::ClearSSLClientAuthHandlerForRequest( | |
| 763 net::URLRequest* request) { | |
| 764 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 765 if (info) { | |
| 766 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); | |
| 767 if (loader) | |
| 768 loader->ClearSSLClientAuthHandler(); | |
| 769 } | |
| 770 } | |
| 771 | |
| 588 // static | 772 // static |
| 589 bool ResourceDispatcherHostImpl::RenderViewForRequest( | 773 bool ResourceDispatcherHostImpl::RenderViewForRequest( |
| 590 const net::URLRequest* request, | 774 const net::URLRequest* request, |
| 591 int* render_process_id, | 775 int* render_process_id, |
| 592 int* render_view_id) { | 776 int* render_view_id) { |
| 593 const ResourceRequestInfoImpl* info = | 777 const ResourceRequestInfoImpl* info = |
| 594 ResourceRequestInfoImpl::ForRequest(request); | 778 ResourceRequestInfoImpl::ForRequest(request); |
| 595 if (!info) { | 779 if (!info) { |
| 596 *render_process_id = -1; | 780 *render_process_id = -1; |
| 597 *render_view_id = -1; | 781 *render_view_id = -1; |
| 598 return false; | 782 return false; |
| 599 } | 783 } |
| 600 | 784 |
| 601 return info->GetAssociatedRenderView(render_process_id, render_view_id); | 785 return info->GetAssociatedRenderView(render_process_id, render_view_id); |
| 602 } | 786 } |
| 603 | 787 |
| 604 void ResourceDispatcherHostImpl::OnShutdown() { | 788 void ResourceDispatcherHostImpl::OnShutdown() { |
| 605 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 789 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 790 | |
| 606 is_shutdown_ = true; | 791 is_shutdown_ = true; |
| 607 for (PendingRequestList::const_iterator i = pending_requests_.begin(); | 792 pending_loaders_.clear(); |
| 608 i != pending_requests_.end(); ++i) { | 793 |
| 609 transferred_navigations_.erase(i->first); | |
| 610 } | |
| 611 STLDeleteValues(&pending_requests_); | |
| 612 // Make sure we shutdown the timer now, otherwise by the time our destructor | 794 // Make sure we shutdown the timer now, otherwise by the time our destructor |
| 613 // runs if the timer is still running the Task is deleted twice (once by | 795 // runs if the timer is still running the Task is deleted twice (once by |
| 614 // the MessageLoop and the second time by RepeatingTimer). | 796 // the MessageLoop and the second time by RepeatingTimer). |
| 615 update_load_states_timer_.reset(); | 797 update_load_states_timer_.reset(); |
| 616 | 798 |
| 617 // Clear blocked requests if any left. | 799 // Clear blocked requests if any left. |
| 618 // Note that we have to do this in 2 passes as we cannot call | 800 // Note that we have to do this in 2 passes as we cannot call |
| 619 // CancelBlockedRequestsForRoute while iterating over | 801 // CancelBlockedRequestsForRoute while iterating over |
| 620 // blocked_requests_map_, as it modifies it. | 802 // blocked_loaders_map_, as it modifies it. |
| 621 std::set<ProcessRouteIDs> ids; | 803 std::set<ProcessRouteIDs> ids; |
| 622 for (BlockedRequestMap::const_iterator iter = blocked_requests_map_.begin(); | 804 for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin(); |
| 623 iter != blocked_requests_map_.end(); ++iter) { | 805 iter != blocked_loaders_map_.end(); ++iter) { |
| 624 std::pair<std::set<ProcessRouteIDs>::iterator, bool> result = | 806 std::pair<std::set<ProcessRouteIDs>::iterator, bool> result = |
| 625 ids.insert(iter->first); | 807 ids.insert(iter->first); |
| 626 // We should not have duplicates. | 808 // We should not have duplicates. |
| 627 DCHECK(result.second); | 809 DCHECK(result.second); |
| 628 } | 810 } |
| 629 for (std::set<ProcessRouteIDs>::const_iterator iter = ids.begin(); | 811 for (std::set<ProcessRouteIDs>::const_iterator iter = ids.begin(); |
| 630 iter != ids.end(); ++iter) { | 812 iter != ids.end(); ++iter) { |
| 631 CancelBlockedRequestsForRoute(iter->first, iter->second); | 813 CancelBlockedRequestsForRoute(iter->first, iter->second); |
| 632 } | 814 } |
| 633 } | 815 } |
| 634 | 816 |
| 635 bool ResourceDispatcherHostImpl::HandleExternalProtocol( | |
| 636 int request_id, | |
| 637 int child_id, | |
| 638 int route_id, | |
| 639 const GURL& url, | |
| 640 ResourceType::Type type, | |
| 641 const net::URLRequestJobFactory& job_factory, | |
| 642 ResourceHandler* handler) { | |
| 643 if (!ResourceType::IsFrame(type) || | |
| 644 job_factory.IsHandledURL(url)) { | |
| 645 return false; | |
| 646 } | |
| 647 | |
| 648 if (delegate_) | |
| 649 delegate_->HandleExternalProtocol(url, child_id, route_id); | |
| 650 | |
| 651 // This error code is special-cased in RenderViewImpl::didFailProvisionalLoad | |
| 652 // to not result in an error page. | |
| 653 handler->OnResponseCompleted( | |
| 654 request_id, | |
| 655 net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
| 656 net::ERR_UNKNOWN_URL_SCHEME), | |
| 657 std::string()); // No security info necessary. | |
| 658 return true; | |
| 659 } | |
| 660 | |
| 661 bool ResourceDispatcherHostImpl::OnMessageReceived( | 817 bool ResourceDispatcherHostImpl::OnMessageReceived( |
| 662 const IPC::Message& message, | 818 const IPC::Message& message, |
| 663 ResourceMessageFilter* filter, | 819 ResourceMessageFilter* filter, |
| 664 bool* message_was_ok) { | 820 bool* message_was_ok) { |
| 665 filter_ = filter; | 821 filter_ = filter; |
| 666 bool handled = true; | 822 bool handled = true; |
| 667 IPC_BEGIN_MESSAGE_MAP_EX(ResourceDispatcherHostImpl, message, *message_was_ok) | 823 IPC_BEGIN_MESSAGE_MAP_EX(ResourceDispatcherHostImpl, message, *message_was_ok) |
| 668 IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource) | 824 IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource) |
| 669 IPC_MESSAGE_HANDLER_DELAY_REPLY(ResourceHostMsg_SyncLoad, OnSyncLoad) | 825 IPC_MESSAGE_HANDLER_DELAY_REPLY(ResourceHostMsg_SyncLoad, OnSyncLoad) |
| 670 IPC_MESSAGE_HANDLER(ResourceHostMsg_ReleaseDownloadedFile, | 826 IPC_MESSAGE_HANDLER(ResourceHostMsg_ReleaseDownloadedFile, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 721 ProcessType process_type = filter_->process_type(); | 877 ProcessType process_type = filter_->process_type(); |
| 722 int child_id = filter_->child_id(); | 878 int child_id = filter_->child_id(); |
| 723 | 879 |
| 724 // If we crash here, figure out what URL the renderer was requesting. | 880 // If we crash here, figure out what URL the renderer was requesting. |
| 725 // http://crbug.com/91398 | 881 // http://crbug.com/91398 |
| 726 char url_buf[128]; | 882 char url_buf[128]; |
| 727 base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf)); | 883 base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf)); |
| 728 base::debug::Alias(url_buf); | 884 base::debug::Alias(url_buf); |
| 729 | 885 |
| 730 // If the request that's coming in is being transferred from another process, | 886 // If the request that's coming in is being transferred from another process, |
| 731 // we want to reuse and resume the old request rather than start a new one. | 887 // we want to reuse and resume the old loader rather than start a new one. |
| 732 net::URLRequest* deferred_request = NULL; | 888 linked_ptr<ResourceLoader> deferred_loader; |
| 733 | 889 { |
| 734 GlobalRequestID old_request_id(request_data.transferred_request_child_id, | 890 LoaderMap::iterator it = pending_loaders_.find( |
| 735 request_data.transferred_request_request_id); | 891 GlobalRequestID(request_data.transferred_request_child_id, |
| 736 TransferredNavigations::iterator iter = | 892 request_data.transferred_request_request_id)); |
| 737 transferred_navigations_.find(old_request_id); | 893 if (it != pending_loaders_.end()) { |
| 738 if (iter != transferred_navigations_.end()) { | 894 if (it->second->is_transferring()) { |
| 739 deferred_request = iter->second; | 895 deferred_loader = it->second; |
| 740 pending_requests_.erase(old_request_id); | 896 pending_loaders_.erase(it); |
| 741 transferred_navigations_.erase(iter); | 897 } else { |
| 898 RecordAction(UserMetricsAction("BadMessageTerminate_RDH")); | |
| 899 filter_->BadMessageReceived(); | |
| 900 return; | |
| 901 } | |
| 902 } | |
| 742 } | 903 } |
| 743 | 904 |
| 744 ResourceContext* resource_context = filter_->resource_context(); | 905 ResourceContext* resource_context = filter_->resource_context(); |
| 745 // http://crbug.com/90971 | 906 // http://crbug.com/90971 |
| 746 CHECK(ContainsKey(active_resource_contexts_, resource_context)); | 907 CHECK(ContainsKey(active_resource_contexts_, resource_context)); |
| 747 | 908 |
| 748 // Might need to resolve the blob references in the upload data. | 909 // Might need to resolve the blob references in the upload data. |
| 749 if (request_data.upload_data) { | 910 if (request_data.upload_data) { |
| 750 GetBlobStorageControllerForResourceContext(resource_context)-> | 911 GetBlobStorageControllerForResourceContext(resource_context)-> |
| 751 ResolveBlobReferencesInUploadData(request_data.upload_data.get()); | 912 ResolveBlobReferencesInUploadData(request_data.upload_data.get()); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 781 handler.reset(new AsyncResourceHandler( | 942 handler.reset(new AsyncResourceHandler( |
| 782 filter_, route_id, request_data.url, this)); | 943 filter_, route_id, request_data.url, this)); |
| 783 } | 944 } |
| 784 | 945 |
| 785 // The RedirectToFileResourceHandler depends on being next in the chain. | 946 // The RedirectToFileResourceHandler depends on being next in the chain. |
| 786 if (request_data.download_to_file) { | 947 if (request_data.download_to_file) { |
| 787 handler.reset( | 948 handler.reset( |
| 788 new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); | 949 new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); |
| 789 } | 950 } |
| 790 | 951 |
| 791 if (HandleExternalProtocol( | 952 int load_flags = |
| 792 request_id, child_id, route_id, request_data.url, | 953 BuildLoadFlagsForRequest(request_data, child_id, sync_result != NULL); |
| 793 request_data.resource_type, | |
| 794 *resource_context->GetRequestContext()->job_factory(), | |
| 795 handler.get())) { | |
| 796 return; | |
| 797 } | |
| 798 | 954 |
| 799 // Construct the request. | 955 // Construct the request. |
| 956 scoped_ptr<net::URLRequest> new_request; | |
| 800 net::URLRequest* request; | 957 net::URLRequest* request; |
| 801 if (deferred_request) { | 958 if (deferred_loader.get()) { |
| 802 request = deferred_request; | 959 request = deferred_loader->request(); |
| 803 } else { | 960 } else { |
| 804 request = new net::URLRequest(request_data.url, this); | 961 new_request.reset(new net::URLRequest(request_data.url, NULL)); |
| 962 request = new_request.get(); | |
| 963 | |
| 805 request->set_method(request_data.method); | 964 request->set_method(request_data.method); |
| 806 request->set_first_party_for_cookies(request_data.first_party_for_cookies); | 965 request->set_first_party_for_cookies(request_data.first_party_for_cookies); |
| 807 request->set_referrer(referrer.url.spec()); | 966 request->set_referrer(referrer.url.spec()); |
| 808 webkit_glue::ConfigureURLRequestForReferrerPolicy(request, referrer.policy); | 967 webkit_glue::ConfigureURLRequestForReferrerPolicy(request, |
| 968 referrer.policy); | |
| 809 net::HttpRequestHeaders headers; | 969 net::HttpRequestHeaders headers; |
| 810 headers.AddHeadersFromString(request_data.headers); | 970 headers.AddHeadersFromString(request_data.headers); |
| 811 request->SetExtraRequestHeaders(headers); | 971 request->SetExtraRequestHeaders(headers); |
| 812 } | 972 } |
| 813 | 973 |
| 814 int load_flags = request_data.load_flags; | 974 // TODO(darin): Do we really need all of these URLRequest setters in the |
| 815 // Although EV status is irrelevant to sub-frames and sub-resources, we have | 975 // transferred navigation case? |
| 816 // to perform EV certificate verification on all resources because an HTTP | |
| 817 // keep-alive connection created to load a sub-frame or a sub-resource could | |
| 818 // be reused to load a main frame. | |
| 819 load_flags |= net::LOAD_VERIFY_EV_CERT; | |
| 820 if (request_data.resource_type == ResourceType::MAIN_FRAME) { | |
| 821 load_flags |= net::LOAD_MAIN_FRAME; | |
| 822 } else if (request_data.resource_type == ResourceType::SUB_FRAME) { | |
| 823 load_flags |= net::LOAD_SUB_FRAME; | |
| 824 } else if (request_data.resource_type == ResourceType::PREFETCH) { | |
| 825 load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); | |
| 826 } else if (request_data.resource_type == ResourceType::FAVICON) { | |
| 827 load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN; | |
| 828 } | |
| 829 | |
| 830 if (sync_result) | |
| 831 load_flags |= net::LOAD_IGNORE_LIMITS; | |
| 832 | |
| 833 ChildProcessSecurityPolicyImpl* policy = | |
| 834 ChildProcessSecurityPolicyImpl::GetInstance(); | |
| 835 if (!policy->CanUseCookiesForOrigin(child_id, request_data.url)) { | |
| 836 load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | | |
| 837 net::LOAD_DO_NOT_SEND_AUTH_DATA | | |
| 838 net::LOAD_DO_NOT_SAVE_COOKIES); | |
| 839 } | |
| 840 | |
| 841 // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only | |
| 842 // allow requesting them if requester has ReadRawCookies permission. | |
| 843 if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) | |
| 844 && !policy->CanReadRawCookies(child_id)) { | |
| 845 VLOG(1) << "Denied unauthorized request for raw headers"; | |
| 846 load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; | |
| 847 } | |
| 848 | 976 |
| 849 request->set_load_flags(load_flags); | 977 request->set_load_flags(load_flags); |
| 850 | 978 |
| 851 request->set_context( | 979 request->set_context( |
| 852 filter_->GetURLRequestContext(request_data.resource_type)); | 980 filter_->GetURLRequestContext(request_data.resource_type)); |
| 853 request->set_priority(DetermineRequestPriority(request_data.resource_type)); | 981 request->set_priority(DetermineRequestPriority(request_data.resource_type)); |
| 854 | 982 |
| 855 // Set upload data. | 983 // Set upload data. |
| 856 uint64 upload_size = 0; | 984 uint64 upload_size = 0; |
| 857 if (request_data.upload_data) { | 985 if (request_data.upload_data) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 869 process_type == PROCESS_TYPE_RENDERER && | 997 process_type == PROCESS_TYPE_RENDERER && |
| 870 CrossSiteRequestManager::GetInstance()-> | 998 CrossSiteRequestManager::GetInstance()-> |
| 871 HasPendingCrossSiteRequest(child_id, route_id)) { | 999 HasPendingCrossSiteRequest(child_id, route_id)) { |
| 872 // Wrap the event handler to be sure the current page's onunload handler | 1000 // Wrap the event handler to be sure the current page's onunload handler |
| 873 // has a chance to run before we render the new page. | 1001 // has a chance to run before we render the new page. |
| 874 handler.reset( | 1002 handler.reset( |
| 875 new CrossSiteResourceHandler(handler.Pass(), child_id, route_id, this)); | 1003 new CrossSiteResourceHandler(handler.Pass(), child_id, route_id, this)); |
| 876 } | 1004 } |
| 877 | 1005 |
| 878 // Insert a buffered event handler before the actual one. | 1006 // Insert a buffered event handler before the actual one. |
| 879 handler.reset(new BufferedResourceHandler(handler.Pass(), this, request)); | 1007 handler.reset( |
| 1008 new BufferedResourceHandler(handler.Pass(), this, request)); | |
| 880 | 1009 |
| 881 ScopedVector<ResourceThrottle> throttles; | 1010 ScopedVector<ResourceThrottle> throttles; |
| 882 if (delegate_) { | 1011 if (delegate_) { |
| 883 bool is_continuation_of_transferred_request = | 1012 bool is_continuation_of_transferred_request = |
| 884 (deferred_request != NULL); | 1013 (deferred_loader.get() != NULL); |
| 885 | 1014 |
| 886 delegate_->RequestBeginning(request, | 1015 delegate_->RequestBeginning(request, |
| 887 resource_context, | 1016 resource_context, |
| 888 request_data.resource_type, | 1017 request_data.resource_type, |
| 889 child_id, | 1018 child_id, |
| 890 route_id, | 1019 route_id, |
| 891 is_continuation_of_transferred_request, | 1020 is_continuation_of_transferred_request, |
| 892 &throttles); | 1021 &throttles); |
| 893 } | 1022 } |
| 894 | 1023 |
| 895 if (request_data.resource_type == ResourceType::MAIN_FRAME) { | 1024 if (request_data.resource_type == ResourceType::MAIN_FRAME) { |
| 896 throttles.insert( | 1025 throttles.insert( |
| 897 throttles.begin(), new TransferNavigationResourceThrottle(request)); | 1026 throttles.begin(), |
| 1027 new TransferNavigationResourceThrottle(request)); | |
| 898 } | 1028 } |
| 899 | 1029 |
| 900 if (!throttles.empty()) { | 1030 if (!throttles.empty()) { |
| 901 handler.reset( | 1031 handler.reset( |
| 902 new ThrottlingResourceHandler(this, handler.Pass(), child_id, | 1032 new ThrottlingResourceHandler(handler.Pass(), child_id, request_id, |
| 903 request_id, throttles.Pass())); | 1033 throttles.Pass())); |
| 904 } | 1034 } |
| 905 | 1035 |
| 906 bool allow_download = request_data.allow_download && | 1036 bool allow_download = request_data.allow_download && |
| 907 ResourceType::IsFrame(request_data.resource_type); | 1037 ResourceType::IsFrame(request_data.resource_type); |
| 908 // Make extra info and read footer (contains request ID). | 1038 // Make extra info and read footer (contains request ID). |
| 909 ResourceRequestInfoImpl* extra_info = | 1039 ResourceRequestInfoImpl* extra_info = |
| 910 new ResourceRequestInfoImpl( | 1040 new ResourceRequestInfoImpl( |
| 911 handler.Pass(), | |
| 912 process_type, | 1041 process_type, |
| 913 child_id, | 1042 child_id, |
| 914 route_id, | 1043 route_id, |
| 915 request_data.origin_pid, | 1044 request_data.origin_pid, |
| 916 request_id, | 1045 request_id, |
| 917 request_data.is_main_frame, | 1046 request_data.is_main_frame, |
| 918 request_data.frame_id, | 1047 request_data.frame_id, |
| 919 request_data.parent_is_main_frame, | 1048 request_data.parent_is_main_frame, |
| 920 request_data.parent_frame_id, | 1049 request_data.parent_frame_id, |
| 921 request_data.resource_type, | 1050 request_data.resource_type, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 935 GetBlobStorageControllerForResourceContext(resource_context); | 1064 GetBlobStorageControllerForResourceContext(resource_context); |
| 936 extra_info->set_requested_blob_data( | 1065 extra_info->set_requested_blob_data( |
| 937 controller->GetBlobDataFromUrl(request->url())); | 1066 controller->GetBlobDataFromUrl(request->url())); |
| 938 } | 1067 } |
| 939 | 1068 |
| 940 // Have the appcache associate its extra info with the request. | 1069 // Have the appcache associate its extra info with the request. |
| 941 appcache::AppCacheInterceptor::SetExtraRequestInfo( | 1070 appcache::AppCacheInterceptor::SetExtraRequestInfo( |
| 942 request, ResourceContext::GetAppCacheService(resource_context), child_id, | 1071 request, ResourceContext::GetAppCacheService(resource_context), child_id, |
| 943 request_data.appcache_host_id, request_data.resource_type); | 1072 request_data.appcache_host_id, request_data.resource_type); |
| 944 | 1073 |
| 945 if (deferred_request) { | 1074 if (deferred_loader.get()) { |
| 946 // This is a request that has been transferred from another process, so | 1075 pending_loaders_[extra_info->GetGlobalRequestID()] = deferred_loader; |
| 947 // resume it rather than continuing the regular procedure for starting a | 1076 deferred_loader->CompleteTransfer(handler.Pass()); |
| 948 // request. Currently this is only done for redirects. | |
| 949 GlobalRequestID global_id(extra_info->GetChildID(), | |
| 950 extra_info->GetRequestID()); | |
| 951 pending_requests_[global_id] = request; | |
| 952 request->FollowDeferredRedirect(); | |
| 953 } else { | 1077 } else { |
| 954 BeginRequestInternal(request); | 1078 BeginRequestInternal(new_request.Pass(), handler.Pass()); |
| 955 } | 1079 } |
| 956 } | 1080 } |
| 957 | 1081 |
| 958 void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) { | 1082 void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) { |
| 959 DCHECK(pending_requests_.end() == | |
| 960 pending_requests_.find( | |
| 961 GlobalRequestID(filter_->child_id(), request_id))); | |
| 962 UnregisterDownloadedTempFile(filter_->child_id(), request_id); | 1083 UnregisterDownloadedTempFile(filter_->child_id(), request_id); |
| 963 } | 1084 } |
| 964 | 1085 |
| 965 void ResourceDispatcherHostImpl::OnDataReceivedACK(int request_id) { | 1086 void ResourceDispatcherHostImpl::OnDataReceivedACK(int request_id) { |
| 966 DataReceivedACK(filter_->child_id(), request_id); | 1087 DataReceivedACK(filter_->child_id(), request_id); |
| 967 } | 1088 } |
| 968 | 1089 |
| 969 void ResourceDispatcherHostImpl::DataReceivedACK(int child_id, | 1090 void ResourceDispatcherHostImpl::DataReceivedACK(int child_id, |
| 970 int request_id) { | 1091 int request_id) { |
| 971 PendingRequestList::iterator i = pending_requests_.find( | 1092 ResourceLoader* loader = GetLoader(child_id, request_id); |
| 972 GlobalRequestID(child_id, request_id)); | 1093 if (!loader) |
| 973 if (i == pending_requests_.end()) | |
| 974 return; | 1094 return; |
| 975 | 1095 |
| 976 ResourceRequestInfoImpl* info = | 1096 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
| 977 ResourceRequestInfoImpl::ForRequest(i->second); | |
| 978 | 1097 |
| 979 // Decrement the number of pending data messages. | 1098 // Decrement the number of pending data messages. |
| 980 info->DecrementPendingDataCount(); | 1099 info->DecrementPendingDataCount(); |
| 981 | 1100 |
| 982 // If the pending data count was higher than the max, resume the request. | 1101 // If the pending data count was higher than the max, resume the request. |
| 983 if (info->pending_data_count() == kMaxPendingDataMessages) { | 1102 if (info->pending_data_count() == kMaxPendingDataMessages) { |
| 984 // Decrement the pending data count one more time because we also | 1103 // Decrement the pending data count one more time because we also |
| 985 // incremented it before pausing the request. | 1104 // incremented it before pausing the request. |
| 986 info->DecrementPendingDataCount(); | 1105 info->DecrementPendingDataCount(); |
| 987 | 1106 |
| 988 // Resume the request. | 1107 // Resume the request. |
| 989 PauseRequest(child_id, request_id, false); | 1108 // TODO(darin): The AsyncResourceHandler should be responsible for resuming. |
| 1109 loader->Resume(); | |
| 990 } | 1110 } |
| 991 } | 1111 } |
| 992 | 1112 |
| 993 void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) { | 1113 void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) { |
| 994 // TODO(michaeln): maybe throttle DataDownloaded messages | 1114 // TODO(michaeln): maybe throttle DataDownloaded messages |
| 995 } | 1115 } |
| 996 | 1116 |
| 997 void ResourceDispatcherHostImpl::RegisterDownloadedTempFile( | 1117 void ResourceDispatcherHostImpl::RegisterDownloadedTempFile( |
| 998 int child_id, int request_id, ShareableFileReference* reference) { | 1118 int child_id, int request_id, ShareableFileReference* reference) { |
| 999 registered_temp_files_[child_id][request_id] = reference; | 1119 registered_temp_files_[child_id][request_id] = reference; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1025 // Note that we don't remove the security bits here. This will be done | 1145 // Note that we don't remove the security bits here. This will be done |
| 1026 // when all file refs are deleted (see RegisterDownloadedTempFile). | 1146 // when all file refs are deleted (see RegisterDownloadedTempFile). |
| 1027 } | 1147 } |
| 1028 | 1148 |
| 1029 bool ResourceDispatcherHostImpl::Send(IPC::Message* message) { | 1149 bool ResourceDispatcherHostImpl::Send(IPC::Message* message) { |
| 1030 delete message; | 1150 delete message; |
| 1031 return false; | 1151 return false; |
| 1032 } | 1152 } |
| 1033 | 1153 |
| 1034 void ResourceDispatcherHostImpl::OnUploadProgressACK(int request_id) { | 1154 void ResourceDispatcherHostImpl::OnUploadProgressACK(int request_id) { |
| 1035 int child_id = filter_->child_id(); | 1155 ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); |
| 1036 PendingRequestList::iterator i = pending_requests_.find( | 1156 if (loader) |
| 1037 GlobalRequestID(child_id, request_id)); | 1157 loader->OnUploadProgressACK(); |
| 1038 if (i == pending_requests_.end()) | |
| 1039 return; | |
| 1040 | |
| 1041 ResourceRequestInfoImpl* info = | |
| 1042 ResourceRequestInfoImpl::ForRequest(i->second); | |
| 1043 info->set_waiting_for_upload_progress_ack(false); | |
| 1044 } | 1158 } |
| 1045 | 1159 |
| 1046 void ResourceDispatcherHostImpl::OnCancelRequest(int request_id) { | 1160 void ResourceDispatcherHostImpl::OnCancelRequest(int request_id) { |
| 1047 CancelRequest(filter_->child_id(), request_id, true); | 1161 CancelRequest(filter_->child_id(), request_id, true); |
| 1048 } | 1162 } |
| 1049 | 1163 |
| 1050 void ResourceDispatcherHostImpl::OnFollowRedirect( | 1164 void ResourceDispatcherHostImpl::OnFollowRedirect( |
| 1051 int request_id, | 1165 int request_id, |
| 1052 bool has_new_first_party_for_cookies, | 1166 bool has_new_first_party_for_cookies, |
| 1053 const GURL& new_first_party_for_cookies) { | 1167 const GURL& new_first_party_for_cookies) { |
| 1054 FollowDeferredRedirect(filter_->child_id(), request_id, | 1168 ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); |
| 1055 has_new_first_party_for_cookies, | 1169 if (!loader) { |
| 1056 new_first_party_for_cookies); | 1170 DVLOG(1) << "OnFollowRedirect for invalid request"; |
| 1171 return; | |
| 1172 } | |
| 1173 | |
| 1174 loader->OnFollowRedirect(has_new_first_party_for_cookies, | |
| 1175 new_first_party_for_cookies); | |
| 1057 } | 1176 } |
| 1058 | 1177 |
| 1059 ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo( | 1178 ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo( |
| 1060 scoped_ptr<ResourceHandler> handler, | |
| 1061 int child_id, | 1179 int child_id, |
| 1062 int route_id, | 1180 int route_id, |
| 1063 bool download, | 1181 bool download, |
| 1064 ResourceContext* context) { | 1182 ResourceContext* context) { |
| 1065 return new ResourceRequestInfoImpl( | 1183 return new ResourceRequestInfoImpl( |
| 1066 handler.Pass(), | |
| 1067 PROCESS_TYPE_RENDERER, | 1184 PROCESS_TYPE_RENDERER, |
| 1068 child_id, | 1185 child_id, |
| 1069 route_id, | 1186 route_id, |
| 1070 0, | 1187 0, |
| 1071 request_id_, | 1188 request_id_, |
| 1072 false, // is_main_frame | 1189 false, // is_main_frame |
| 1073 -1, // frame_id | 1190 -1, // frame_id |
| 1074 false, // parent_is_main_frame | 1191 false, // parent_is_main_frame |
| 1075 -1, // parent_frame_id | 1192 -1, // parent_frame_id |
| 1076 ResourceType::SUB_RESOURCE, | 1193 ResourceType::SUB_RESOURCE, |
| 1077 PAGE_TRANSITION_LINK, | 1194 PAGE_TRANSITION_LINK, |
| 1078 0, // upload_size | 1195 0, // upload_size |
| 1079 download, // is_download | 1196 download, // is_download |
| 1080 download, // allow_download | 1197 download, // allow_download |
| 1081 false, // has_user_gesture | 1198 false, // has_user_gesture |
| 1082 WebKit::WebReferrerPolicyDefault, | 1199 WebKit::WebReferrerPolicyDefault, |
| 1083 context); | 1200 context); |
| 1084 } | 1201 } |
| 1085 | 1202 |
| 1086 void ResourceDispatcherHostImpl::OnSwapOutACK( | 1203 void ResourceDispatcherHostImpl::OnSwapOutACK( |
| 1087 const ViewMsg_SwapOut_Params& params) { | 1204 const ViewMsg_SwapOut_Params& params) { |
| 1088 // Closes for cross-site transitions are handled such that the cross-site | 1205 // Closes for cross-site transitions are handled such that the cross-site |
| 1089 // transition continues. | 1206 // transition continues. |
| 1090 GlobalRequestID global_id(params.new_render_process_host_id, | 1207 ResourceLoader* loader = GetLoader(params.new_render_process_host_id, |
| 1091 params.new_request_id); | 1208 params.new_request_id); |
| 1092 PendingRequestList::iterator i = pending_requests_.find(global_id); | 1209 if (loader) { |
| 1093 if (i != pending_requests_.end()) { | |
| 1094 // The response we were meant to resume could have already been canceled. | 1210 // The response we were meant to resume could have already been canceled. |
| 1095 ResourceRequestInfoImpl* info = | 1211 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
| 1096 ResourceRequestInfoImpl::ForRequest(i->second); | |
| 1097 if (info->cross_site_handler()) | 1212 if (info->cross_site_handler()) |
| 1098 info->cross_site_handler()->ResumeResponse(); | 1213 info->cross_site_handler()->ResumeResponse(); |
| 1099 } | 1214 } |
| 1215 | |
| 1100 // Update the RenderViewHost's internal state after the ACK. | 1216 // Update the RenderViewHost's internal state after the ACK. |
| 1101 BrowserThread::PostTask( | 1217 BrowserThread::PostTask( |
| 1102 BrowserThread::UI, | 1218 BrowserThread::UI, |
| 1103 FROM_HERE, | 1219 FROM_HERE, |
| 1104 base::Bind(&OnSwapOutACKHelper, | 1220 base::Bind(&OnSwapOutACKHelper, |
| 1105 params.closing_process_id, | 1221 params.closing_process_id, |
| 1106 params.closing_route_id)); | 1222 params.closing_route_id)); |
| 1107 } | 1223 } |
| 1108 | 1224 |
| 1109 void ResourceDispatcherHostImpl::OnDidLoadResourceFromMemoryCache( | 1225 void ResourceDispatcherHostImpl::OnDidLoadResourceFromMemoryCache( |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1146 bool known_proto = | 1262 bool known_proto = |
| 1147 request_context->job_factory()->IsHandledURL(url); | 1263 request_context->job_factory()->IsHandledURL(url); |
| 1148 if (!known_proto) { | 1264 if (!known_proto) { |
| 1149 // Since any URLs which have non-standard scheme have been filtered | 1265 // Since any URLs which have non-standard scheme have been filtered |
| 1150 // by save manager(see GURL::SchemeIsStandard). This situation | 1266 // by save manager(see GURL::SchemeIsStandard). This situation |
| 1151 // should not happen. | 1267 // should not happen. |
| 1152 NOTREACHED(); | 1268 NOTREACHED(); |
| 1153 return; | 1269 return; |
| 1154 } | 1270 } |
| 1155 | 1271 |
| 1156 net::URLRequest* request = new net::URLRequest(url, this); | 1272 scoped_ptr<net::URLRequest> request(new net::URLRequest(url, NULL)); |
| 1157 request->set_method("GET"); | 1273 request->set_method("GET"); |
| 1158 request->set_referrer(MaybeStripReferrer(referrer.url).spec()); | 1274 request->set_referrer(MaybeStripReferrer(referrer.url).spec()); |
| 1159 webkit_glue::ConfigureURLRequestForReferrerPolicy(request, referrer.policy); | 1275 webkit_glue::ConfigureURLRequestForReferrerPolicy(request.get(), |
| 1276 referrer.policy); | |
| 1160 // So far, for saving page, we need fetch content from cache, in the | 1277 // So far, for saving page, we need fetch content from cache, in the |
| 1161 // future, maybe we can use a configuration to configure this behavior. | 1278 // future, maybe we can use a configuration to configure this behavior. |
| 1162 request->set_load_flags(net::LOAD_PREFERRING_CACHE); | 1279 request->set_load_flags(net::LOAD_PREFERRING_CACHE); |
| 1163 request->set_context(context->GetRequestContext()); | 1280 request->set_context(context->GetRequestContext()); |
| 1164 | 1281 |
| 1165 // Since we're just saving some resources we need, disallow downloading. | 1282 // Since we're just saving some resources we need, disallow downloading. |
| 1166 ResourceRequestInfoImpl* extra_info = | 1283 ResourceRequestInfoImpl* extra_info = |
| 1167 CreateRequestInfo(handler.Pass(), child_id, route_id, false, context); | 1284 CreateRequestInfo(child_id, route_id, false, context); |
| 1168 extra_info->AssociateWithRequest(request); // Request takes ownership. | 1285 extra_info->AssociateWithRequest(request.get()); // Request takes ownership. |
| 1169 | 1286 |
| 1170 BeginRequestInternal(request); | 1287 BeginRequestInternal(request.Pass(), handler.Pass()); |
| 1171 } | 1288 } |
| 1172 | 1289 |
| 1173 void ResourceDispatcherHostImpl::FollowDeferredRedirect( | 1290 bool ResourceDispatcherHostImpl::WillSendData(int child_id, int request_id, |
| 1174 int child_id, | 1291 bool* defer) { |
| 1175 int request_id, | 1292 ResourceLoader* loader = GetLoader(child_id, request_id); |
| 1176 bool has_new_first_party_for_cookies, | 1293 if (!loader) { |
| 1177 const GURL& new_first_party_for_cookies) { | |
| 1178 PendingRequestList::iterator i = pending_requests_.find( | |
| 1179 GlobalRequestID(child_id, request_id)); | |
| 1180 if (i == pending_requests_.end() || !i->second->status().is_success()) { | |
| 1181 DVLOG(1) << "FollowDeferredRedirect for invalid request"; | |
| 1182 return; | |
| 1183 } | |
| 1184 | |
| 1185 if (has_new_first_party_for_cookies) | |
| 1186 i->second->set_first_party_for_cookies(new_first_party_for_cookies); | |
| 1187 i->second->FollowDeferredRedirect(); | |
| 1188 } | |
| 1189 | |
| 1190 void ResourceDispatcherHostImpl::StartDeferredRequest(int child_id, | |
| 1191 int request_id) { | |
| 1192 GlobalRequestID global_id(child_id, request_id); | |
| 1193 PendingRequestList::iterator i = pending_requests_.find(global_id); | |
| 1194 if (i == pending_requests_.end()) { | |
| 1195 // The request may have been destroyed | |
| 1196 LOG(WARNING) << "Trying to resume a non-existent request (" | |
| 1197 << child_id << ", " << request_id << ")"; | |
| 1198 return; | |
| 1199 } | |
| 1200 | |
| 1201 // TODO(eroman): are there other considerations for paused or blocked | |
| 1202 // requests? | |
| 1203 | |
| 1204 StartRequest(i->second); | |
| 1205 } | |
| 1206 | |
| 1207 void ResourceDispatcherHostImpl::ResumeDeferredRequest(int child_id, | |
| 1208 int request_id) { | |
| 1209 PauseRequest(child_id, request_id, false); | |
| 1210 } | |
| 1211 | |
| 1212 bool ResourceDispatcherHostImpl::WillSendData(int child_id, | |
| 1213 int request_id) { | |
| 1214 PendingRequestList::iterator i = pending_requests_.find( | |
| 1215 GlobalRequestID(child_id, request_id)); | |
| 1216 if (i == pending_requests_.end()) { | |
| 1217 NOTREACHED() << "WillSendData for invalid request"; | 1294 NOTREACHED() << "WillSendData for invalid request"; |
| 1218 return false; | 1295 return false; |
| 1219 } | 1296 } |
| 1220 | 1297 |
| 1221 ResourceRequestInfoImpl* info = | 1298 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
| 1222 ResourceRequestInfoImpl::ForRequest(i->second); | |
| 1223 | 1299 |
| 1224 info->IncrementPendingDataCount(); | 1300 info->IncrementPendingDataCount(); |
| 1225 if (info->pending_data_count() > kMaxPendingDataMessages) { | 1301 if (info->pending_data_count() > kMaxPendingDataMessages) { |
| 1226 // We reached the max number of data messages that can be sent to | 1302 // We reached the max number of data messages that can be sent to |
| 1227 // the renderer for a given request. Pause the request and wait for | 1303 // the renderer for a given request. Pause the request and wait for |
| 1228 // the renderer to start processing them before resuming it. | 1304 // the renderer to start processing them before resuming it. |
| 1229 PauseRequest(child_id, request_id, true); | 1305 *defer = true; |
| 1230 return false; | 1306 return false; |
| 1231 } | 1307 } |
| 1232 | 1308 |
| 1233 return true; | 1309 return true; |
| 1234 } | 1310 } |
| 1235 | 1311 |
| 1236 void ResourceDispatcherHostImpl::MarkAsTransferredNavigation( | 1312 void ResourceDispatcherHostImpl::MarkAsTransferredNavigation( |
| 1237 net::URLRequest* transferred_request) { | 1313 const GlobalRequestID& id) { |
| 1238 ResourceRequestInfoImpl* info = | 1314 ResourceLoader* loader = GetLoader(id); |
| 1239 ResourceRequestInfoImpl::ForRequest(transferred_request); | 1315 CHECK(loader); |
|
jam
2012/06/14 01:10:22
nit: this isn't needed, it'll crash below which wi
| |
| 1240 | 1316 |
| 1241 GlobalRequestID transferred_request_id(info->GetChildID(), | 1317 loader->MarkAsTransferring(); |
| 1242 info->GetRequestID()); | |
| 1243 transferred_navigations_[transferred_request_id] = transferred_request; | |
| 1244 | |
| 1245 // If an URLRequest is transferred to a new RenderViewHost, its | |
| 1246 // ResourceHandler should not receive any notifications because it may | |
| 1247 // depend on the state of the old RVH. We set a ResourceHandler that only | |
| 1248 // allows canceling requests, because on shutdown of the RDH all pending | |
| 1249 // requests are canceled. The RVH of requests that are being transferred may | |
| 1250 // be gone by that time. If the request is resumed, the ResoureHandlers are | |
| 1251 // substituted again. | |
| 1252 info->InsertDoomedResourceHandler(); | |
| 1253 } | 1318 } |
| 1254 | 1319 |
| 1255 int ResourceDispatcherHostImpl::GetOutstandingRequestsMemoryCost( | 1320 int ResourceDispatcherHostImpl::GetOutstandingRequestsMemoryCost( |
| 1256 int child_id) const { | 1321 int child_id) const { |
| 1257 OutstandingRequestsMemoryCostMap::const_iterator entry = | 1322 OutstandingRequestsMemoryCostMap::const_iterator entry = |
| 1258 outstanding_requests_memory_cost_map_.find(child_id); | 1323 outstanding_requests_memory_cost_map_.find(child_id); |
| 1259 return (entry == outstanding_requests_memory_cost_map_.end()) ? | 1324 return (entry == outstanding_requests_memory_cost_map_.end()) ? |
| 1260 0 : entry->second; | 1325 0 : entry->second; |
| 1261 } | 1326 } |
| 1262 | 1327 |
| 1263 // The object died, so cancel and detach all requests associated with it except | 1328 // The object died, so cancel and detach all requests associated with it except |
| 1264 // for downloads, which belong to the browser process even if initiated via a | 1329 // for downloads, which belong to the browser process even if initiated via a |
| 1265 // renderer. | 1330 // renderer. |
| 1266 void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) { | 1331 void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) { |
| 1267 CancelRequestsForRoute(child_id, -1 /* cancel all */); | 1332 CancelRequestsForRoute(child_id, -1 /* cancel all */); |
| 1268 registered_temp_files_.erase(child_id); | 1333 registered_temp_files_.erase(child_id); |
| 1269 } | 1334 } |
| 1270 | 1335 |
| 1271 void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id, | 1336 void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id, |
| 1272 int route_id) { | 1337 int route_id) { |
| 1273 // Since pending_requests_ is a map, we first build up a list of all of the | 1338 // Since pending_requests_ is a map, we first build up a list of all of the |
| 1274 // matching requests to be cancelled, and then we cancel them. Since there | 1339 // matching requests to be cancelled, and then we cancel them. Since there |
| 1275 // may be more than one request to cancel, we cannot simply hold onto the map | 1340 // may be more than one request to cancel, we cannot simply hold onto the map |
| 1276 // iterators found in the first loop. | 1341 // iterators found in the first loop. |
| 1277 | 1342 |
| 1278 // Find the global ID of all matching elements. | 1343 // Find the global ID of all matching elements. |
| 1279 std::vector<GlobalRequestID> matching_requests; | 1344 std::vector<GlobalRequestID> matching_requests; |
| 1280 for (PendingRequestList::const_iterator i = pending_requests_.begin(); | 1345 for (LoaderMap::const_iterator i = pending_loaders_.begin(); |
| 1281 i != pending_requests_.end(); ++i) { | 1346 i != pending_loaders_.end(); ++i) { |
| 1282 if (i->first.child_id == child_id) { | 1347 if (i->first.child_id != child_id) |
| 1283 ResourceRequestInfoImpl* info = | 1348 continue; |
| 1284 ResourceRequestInfoImpl::ForRequest(i->second); | 1349 |
| 1285 GlobalRequestID id(child_id, i->first.request_id); | 1350 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); |
| 1286 DCHECK(id == i->first); | 1351 |
| 1287 // Don't cancel navigations that are transferring to another process, | 1352 GlobalRequestID id(child_id, i->first.request_id); |
| 1288 // since they belong to another process now. | 1353 DCHECK(id == i->first); |
| 1289 if (!info->is_download() && | 1354 |
| 1290 (transferred_navigations_.find(id) == | 1355 // Don't cancel navigations that are transferring to another process, |
| 1291 transferred_navigations_.end()) && | 1356 // since they belong to another process now. |
| 1292 (route_id == -1 || route_id == info->GetRouteID())) { | 1357 if (!info->is_download() && !IsTransferredNavigation(id) && |
| 1293 matching_requests.push_back( | 1358 (route_id == -1 || route_id == info->GetRouteID())) { |
| 1294 GlobalRequestID(child_id, i->first.request_id)); | 1359 matching_requests.push_back(id); |
| 1295 } | |
| 1296 } | 1360 } |
| 1297 } | 1361 } |
| 1298 | 1362 |
| 1299 // Remove matches. | 1363 // Remove matches. |
| 1300 for (size_t i = 0; i < matching_requests.size(); ++i) { | 1364 for (size_t i = 0; i < matching_requests.size(); ++i) { |
| 1301 PendingRequestList::iterator iter = | 1365 LoaderMap::iterator iter = pending_loaders_.find(matching_requests[i]); |
| 1302 pending_requests_.find(matching_requests[i]); | |
| 1303 // Although every matching request was in pending_requests_ when we built | 1366 // Although every matching request was in pending_requests_ when we built |
| 1304 // matching_requests, it is normal for a matching request to be not found | 1367 // matching_requests, it is normal for a matching request to be not found |
| 1305 // in pending_requests_ after we have removed some matching requests from | 1368 // in pending_requests_ after we have removed some matching requests from |
| 1306 // pending_requests_. For example, deleting a net::URLRequest that has | 1369 // pending_requests_. For example, deleting a net::URLRequest that has |
| 1307 // exclusive (write) access to an HTTP cache entry may unblock another | 1370 // exclusive (write) access to an HTTP cache entry may unblock another |
| 1308 // net::URLRequest that needs exclusive access to the same cache entry, and | 1371 // net::URLRequest that needs exclusive access to the same cache entry, and |
| 1309 // that net::URLRequest may complete and remove itself from | 1372 // that net::URLRequest may complete and remove itself from |
| 1310 // pending_requests_. So we need to check that iter is not equal to | 1373 // pending_requests_. So we need to check that iter is not equal to |
| 1311 // pending_requests_.end(). | 1374 // pending_requests_.end(). |
| 1312 if (iter != pending_requests_.end()) | 1375 if (iter != pending_loaders_.end()) |
| 1313 RemovePendingRequest(iter); | 1376 RemovePendingLoader(iter); |
| 1314 } | 1377 } |
| 1315 | 1378 |
| 1316 // Now deal with blocked requests if any. | 1379 // Now deal with blocked requests if any. |
| 1317 if (route_id != -1) { | 1380 if (route_id != -1) { |
| 1318 if (blocked_requests_map_.find(std::pair<int, int>(child_id, route_id)) != | 1381 if (blocked_loaders_map_.find(ProcessRouteIDs(child_id, route_id)) != |
| 1319 blocked_requests_map_.end()) { | 1382 blocked_loaders_map_.end()) { |
| 1320 CancelBlockedRequestsForRoute(child_id, route_id); | 1383 CancelBlockedRequestsForRoute(child_id, route_id); |
| 1321 } | 1384 } |
| 1322 } else { | 1385 } else { |
| 1323 // We have to do all render views for the process |child_id|. | 1386 // We have to do all render views for the process |child_id|. |
| 1324 // Note that we have to do this in 2 passes as we cannot call | 1387 // Note that we have to do this in 2 passes as we cannot call |
| 1325 // CancelBlockedRequestsForRoute while iterating over | 1388 // CancelBlockedRequestsForRoute while iterating over |
| 1326 // blocked_requests_map_, as it modifies it. | 1389 // blocked_loaders_map_, as it modifies it. |
| 1327 std::set<int> route_ids; | 1390 std::set<int> route_ids; |
| 1328 for (BlockedRequestMap::const_iterator iter = blocked_requests_map_.begin(); | 1391 for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin(); |
| 1329 iter != blocked_requests_map_.end(); ++iter) { | 1392 iter != blocked_loaders_map_.end(); ++iter) { |
| 1330 if (iter->first.first == child_id) | 1393 if (iter->first.first == child_id) |
| 1331 route_ids.insert(iter->first.second); | 1394 route_ids.insert(iter->first.second); |
| 1332 } | 1395 } |
| 1333 for (std::set<int>::const_iterator iter = route_ids.begin(); | 1396 for (std::set<int>::const_iterator iter = route_ids.begin(); |
| 1334 iter != route_ids.end(); ++iter) { | 1397 iter != route_ids.end(); ++iter) { |
| 1335 CancelBlockedRequestsForRoute(child_id, *iter); | 1398 CancelBlockedRequestsForRoute(child_id, *iter); |
| 1336 } | 1399 } |
| 1337 } | 1400 } |
| 1338 } | 1401 } |
| 1339 | 1402 |
| 1340 // Cancels the request and removes it from the list. | 1403 // Cancels the request and removes it from the list. |
| 1341 void ResourceDispatcherHostImpl::RemovePendingRequest(int child_id, | 1404 void ResourceDispatcherHostImpl::RemovePendingRequest(int child_id, |
| 1342 int request_id) { | 1405 int request_id) { |
| 1343 PendingRequestList::iterator i = pending_requests_.find( | 1406 LoaderMap::iterator i = pending_loaders_.find( |
| 1344 GlobalRequestID(child_id, request_id)); | 1407 GlobalRequestID(child_id, request_id)); |
| 1345 if (i == pending_requests_.end()) { | 1408 if (i == pending_loaders_.end()) { |
| 1346 NOTREACHED() << "Trying to remove a request that's not here"; | 1409 NOTREACHED() << "Trying to remove a request that's not here"; |
| 1347 return; | 1410 return; |
| 1348 } | 1411 } |
| 1349 RemovePendingRequest(i); | 1412 RemovePendingLoader(i); |
| 1350 } | 1413 } |
| 1351 | 1414 |
| 1352 void ResourceDispatcherHostImpl::RemovePendingRequest( | 1415 void ResourceDispatcherHostImpl::RemovePendingLoader( |
| 1353 const PendingRequestList::iterator& iter) { | 1416 const LoaderMap::iterator& iter) { |
| 1354 ResourceRequestInfoImpl* info = | 1417 ResourceRequestInfoImpl* info = iter->second->GetRequestInfo(); |
| 1355 ResourceRequestInfoImpl::ForRequest(iter->second); | |
| 1356 | 1418 |
| 1357 // Remove the memory credit that we added when pushing the request onto | 1419 // Remove the memory credit that we added when pushing the request onto |
| 1358 // the pending list. | 1420 // the pending list. |
| 1359 IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), | 1421 IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), |
| 1360 info->GetChildID()); | 1422 info->GetChildID()); |
| 1361 | 1423 |
| 1362 // Notify interested parties that the request object is going away. | 1424 pending_loaders_.erase(iter); |
| 1363 if (info->login_delegate()) | |
| 1364 info->login_delegate()->OnRequestCancelled(); | |
| 1365 if (info->ssl_client_auth_handler()) | |
| 1366 info->ssl_client_auth_handler()->OnRequestCancelled(); | |
| 1367 transferred_navigations_.erase( | |
| 1368 GlobalRequestID(info->GetChildID(), info->GetRequestID())); | |
| 1369 | |
| 1370 delete iter->second; | |
| 1371 pending_requests_.erase(iter); | |
| 1372 | 1425 |
| 1373 // If we have no more pending requests, then stop the load state monitor | 1426 // If we have no more pending requests, then stop the load state monitor |
| 1374 if (pending_requests_.empty() && update_load_states_timer_.get()) | 1427 if (pending_loaders_.empty() && update_load_states_timer_.get()) |
| 1375 update_load_states_timer_->Stop(); | 1428 update_load_states_timer_->Stop(); |
| 1376 } | 1429 } |
| 1377 | 1430 |
| 1378 // net::URLRequest::Delegate --------------------------------------------------- | |
| 1379 | |
| 1380 void ResourceDispatcherHostImpl::OnReceivedRedirect(net::URLRequest* request, | |
| 1381 const GURL& new_url, | |
| 1382 bool* defer_redirect) { | |
| 1383 VLOG(1) << "OnReceivedRedirect: " << request->url().spec(); | |
| 1384 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1385 | |
| 1386 DCHECK(request->status().is_success()); | |
| 1387 | |
| 1388 if (info->process_type() != PROCESS_TYPE_PLUGIN && | |
| 1389 !ChildProcessSecurityPolicyImpl::GetInstance()-> | |
| 1390 CanRequestURL(info->GetChildID(), new_url)) { | |
| 1391 VLOG(1) << "Denied unauthorized request for " | |
| 1392 << new_url.possibly_invalid_spec(); | |
| 1393 | |
| 1394 // Tell the renderer that this request was disallowed. | |
| 1395 CancelRequestInternal(request, false); | |
| 1396 return; | |
| 1397 } | |
| 1398 | |
| 1399 NotifyReceivedRedirect(request, info->GetChildID(), new_url); | |
| 1400 | |
| 1401 if (HandleExternalProtocol(info->GetRequestID(), info->GetChildID(), | |
| 1402 info->GetRouteID(), new_url, | |
| 1403 info->GetResourceType(), | |
| 1404 *request->context()->job_factory(), | |
| 1405 info->resource_handler())) { | |
| 1406 // The request is complete so we can remove it. | |
| 1407 RemovePendingRequest(info->GetChildID(), info->GetRequestID()); | |
| 1408 return; | |
| 1409 } | |
| 1410 | |
| 1411 scoped_refptr<ResourceResponse> response(new ResourceResponse); | |
| 1412 PopulateResourceResponse(request, response); | |
| 1413 if (!info->resource_handler()->OnRequestRedirected(info->GetRequestID(), | |
| 1414 new_url, | |
| 1415 response, defer_redirect)) | |
| 1416 CancelRequestInternal(request, false); | |
| 1417 } | |
| 1418 | |
| 1419 void ResourceDispatcherHostImpl::OnAuthRequired( | |
| 1420 net::URLRequest* request, | |
| 1421 net::AuthChallengeInfo* auth_info) { | |
| 1422 if (request->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) { | |
| 1423 request->CancelAuth(); | |
| 1424 return; | |
| 1425 } | |
| 1426 | |
| 1427 if (delegate_ && !delegate_->AcceptAuthRequest(request, auth_info)) { | |
| 1428 request->CancelAuth(); | |
| 1429 return; | |
| 1430 } | |
| 1431 | |
| 1432 // Prevent third-party content from prompting for login, unless it is | |
| 1433 // a proxy that is trying to authenticate. This is often the foundation | |
| 1434 // of a scam to extract credentials for another domain from the user. | |
| 1435 if (!auth_info->is_proxy) { | |
| 1436 HttpAuthResourceType resource_type = HttpAuthResourceTypeOf(request); | |
| 1437 UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthResource", | |
| 1438 resource_type, | |
| 1439 HTTP_AUTH_RESOURCE_LAST); | |
| 1440 | |
| 1441 if (resource_type == HTTP_AUTH_RESOURCE_BLOCKED_CROSS) { | |
| 1442 request->CancelAuth(); | |
| 1443 return; | |
| 1444 } | |
| 1445 } | |
| 1446 | |
| 1447 | |
| 1448 // Create a login dialog on the UI thread to get authentication data, | |
| 1449 // or pull from cache and continue on the IO thread. | |
| 1450 // TODO(mpcomplete): We should block the parent tab while waiting for | |
| 1451 // authentication. | |
| 1452 // That would also solve the problem of the net::URLRequest being cancelled | |
| 1453 // before we receive authentication. | |
| 1454 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1455 DCHECK(!info->login_delegate()) << | |
| 1456 "OnAuthRequired called with login_delegate pending"; | |
| 1457 if (delegate_) { | |
| 1458 info->set_login_delegate(delegate_->CreateLoginDelegate( | |
| 1459 auth_info, request)); | |
| 1460 } | |
| 1461 if (!info->login_delegate()) | |
| 1462 request->CancelAuth(); | |
| 1463 } | |
| 1464 | |
| 1465 void ResourceDispatcherHostImpl::OnCertificateRequested( | |
| 1466 net::URLRequest* request, | |
| 1467 net::SSLCertRequestInfo* cert_request_info) { | |
| 1468 DCHECK(request); | |
| 1469 if (delegate_ && !delegate_->AcceptSSLClientCertificateRequest( | |
| 1470 request, cert_request_info)) { | |
| 1471 request->Cancel(); | |
| 1472 return; | |
| 1473 } | |
| 1474 | |
| 1475 if (cert_request_info->client_certs.empty()) { | |
| 1476 // No need to query the user if there are no certs to choose from. | |
| 1477 request->ContinueWithCertificate(NULL); | |
| 1478 return; | |
| 1479 } | |
| 1480 | |
| 1481 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1482 DCHECK(!info->ssl_client_auth_handler()) << | |
| 1483 "OnCertificateRequested called with ssl_client_auth_handler pending"; | |
| 1484 info->set_ssl_client_auth_handler( | |
| 1485 new SSLClientAuthHandler(request, cert_request_info)); | |
| 1486 info->ssl_client_auth_handler()->SelectCertificate(); | |
| 1487 } | |
| 1488 | |
| 1489 void ResourceDispatcherHostImpl::OnSSLCertificateError( | |
| 1490 net::URLRequest* request, | |
| 1491 const net::SSLInfo& ssl_info, | |
| 1492 bool is_hsts_host) { | |
| 1493 DCHECK(request); | |
| 1494 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1495 DCHECK(info); | |
| 1496 GlobalRequestID request_id(info->GetChildID(), info->GetRequestID()); | |
| 1497 int render_process_id; | |
| 1498 int render_view_id; | |
| 1499 if(!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) | |
| 1500 NOTREACHED(); | |
| 1501 SSLManager::OnSSLCertificateError( | |
| 1502 AsWeakPtr(), request_id, info->GetResourceType(), request->url(), | |
| 1503 render_process_id, render_view_id, ssl_info, is_hsts_host); | |
| 1504 } | |
| 1505 | |
| 1506 void ResourceDispatcherHostImpl::OnResponseStarted(net::URLRequest* request) { | |
| 1507 VLOG(1) << "OnResponseStarted: " << request->url().spec(); | |
| 1508 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1509 | |
| 1510 if (request->status().is_success()) { | |
| 1511 if (PauseRequestIfNeeded(info)) { | |
| 1512 VLOG(1) << "OnResponseStarted pausing: " << request->url().spec(); | |
| 1513 return; | |
| 1514 } | |
| 1515 | |
| 1516 // We want to send a final upload progress message prior to sending | |
| 1517 // the response complete message even if we're waiting for an ack to | |
| 1518 // to a previous upload progress message. | |
| 1519 info->set_waiting_for_upload_progress_ack(false); | |
| 1520 MaybeUpdateUploadProgress(info, request); | |
| 1521 | |
| 1522 if (!CompleteResponseStarted(request)) { | |
| 1523 CancelRequestInternal(request, false); | |
| 1524 } else { | |
| 1525 // Check if the handler paused the request in their OnResponseStarted. | |
| 1526 if (PauseRequestIfNeeded(info)) { | |
| 1527 VLOG(1) << "OnResponseStarted pausing2: " << request->url().spec(); | |
| 1528 return; | |
| 1529 } | |
| 1530 | |
| 1531 StartReading(request); | |
| 1532 } | |
| 1533 } else { | |
| 1534 ResponseCompleted(request); | |
| 1535 } | |
| 1536 } | |
| 1537 | |
| 1538 bool ResourceDispatcherHostImpl::CompleteResponseStarted( | |
| 1539 net::URLRequest* request) { | |
| 1540 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1541 | |
| 1542 scoped_refptr<ResourceResponse> response(new ResourceResponse); | |
| 1543 PopulateResourceResponse(request, response); | |
| 1544 | |
| 1545 if (request->ssl_info().cert) { | |
| 1546 int cert_id = | |
| 1547 CertStore::GetInstance()->StoreCert(request->ssl_info().cert, | |
| 1548 info->GetChildID()); | |
| 1549 response->security_info = SerializeSecurityInfo( | |
| 1550 cert_id, request->ssl_info().cert_status, | |
| 1551 request->ssl_info().security_bits, | |
| 1552 request->ssl_info().connection_status); | |
| 1553 } else { | |
| 1554 // We should not have any SSL state. | |
| 1555 DCHECK(!request->ssl_info().cert_status && | |
| 1556 request->ssl_info().security_bits == -1 && | |
| 1557 !request->ssl_info().connection_status); | |
| 1558 } | |
| 1559 | |
| 1560 NotifyResponseStarted(request, info->GetChildID()); | |
| 1561 info->set_called_on_response_started(true); | |
| 1562 | |
| 1563 bool defer = false; | |
| 1564 if (!info->resource_handler()->OnResponseStarted(info->GetRequestID(), | |
| 1565 response.get(), | |
| 1566 &defer)) | |
| 1567 return false; | |
| 1568 | |
| 1569 if (defer) | |
| 1570 PauseRequest(info->GetChildID(), info->GetRequestID(), true); | |
| 1571 | |
| 1572 return true; | |
| 1573 } | |
| 1574 | |
| 1575 void ResourceDispatcherHostImpl::CancelRequest(int child_id, | 1431 void ResourceDispatcherHostImpl::CancelRequest(int child_id, |
| 1576 int request_id, | 1432 int request_id, |
| 1577 bool from_renderer) { | 1433 bool from_renderer) { |
| 1578 GlobalRequestID id(child_id, request_id); | |
| 1579 if (from_renderer) { | 1434 if (from_renderer) { |
| 1580 // When the old renderer dies, it sends a message to us to cancel its | 1435 // When the old renderer dies, it sends a message to us to cancel its |
| 1581 // requests. | 1436 // requests. |
| 1582 if (transferred_navigations_.find(id) != transferred_navigations_.end()) | 1437 if (IsTransferredNavigation(GlobalRequestID(child_id, request_id))) |
| 1583 return; | 1438 return; |
| 1584 } | 1439 } |
| 1585 | 1440 |
| 1586 PendingRequestList::iterator i = pending_requests_.find(id); | 1441 ResourceLoader* loader = GetLoader(child_id, request_id); |
| 1587 if (i == pending_requests_.end()) { | 1442 if (!loader) { |
| 1588 // We probably want to remove this warning eventually, but I wanted to be | 1443 // We probably want to remove this warning eventually, but I wanted to be |
| 1589 // able to notice when this happens during initial development since it | 1444 // able to notice when this happens during initial development since it |
| 1590 // should be rare and may indicate a bug. | 1445 // should be rare and may indicate a bug. |
| 1591 DVLOG(1) << "Canceling a request that wasn't found"; | 1446 DVLOG(1) << "Canceling a request that wasn't found"; |
| 1592 return; | 1447 return; |
| 1593 } | 1448 } |
| 1594 net::URLRequest* request = i->second; | |
| 1595 | 1449 |
| 1596 bool started_before_cancel = request->is_pending(); | 1450 loader->CancelRequest(from_renderer); |
| 1597 if (CancelRequestInternal(request, from_renderer) && | |
| 1598 !started_before_cancel) { | |
| 1599 // If the request isn't in flight, then we won't get an asynchronous | |
| 1600 // notification from the request, so we have to signal ourselves to finish | |
| 1601 // this request. | |
| 1602 MessageLoop::current()->PostTask( | |
| 1603 FROM_HERE, | |
| 1604 base::Bind(&ResourceDispatcherHostImpl::CallResponseCompleted, | |
| 1605 base::Unretained(this), | |
| 1606 child_id, | |
| 1607 request_id)); | |
| 1608 } | |
| 1609 } | |
| 1610 | |
| 1611 bool ResourceDispatcherHostImpl::CancelRequestInternal(net::URLRequest* request, | |
| 1612 bool from_renderer) { | |
| 1613 VLOG(1) << "CancelRequest: " << request->url().spec(); | |
| 1614 | |
| 1615 // WebKit will send us a cancel for downloads since it no longer handles them. | |
| 1616 // In this case, ignore the cancel since we handle downloads in the browser. | |
| 1617 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1618 if (!from_renderer || !info->is_download()) { | |
| 1619 if (info->login_delegate()) { | |
| 1620 info->login_delegate()->OnRequestCancelled(); | |
| 1621 info->set_login_delegate(NULL); | |
| 1622 } | |
| 1623 if (info->ssl_client_auth_handler()) { | |
| 1624 info->ssl_client_auth_handler()->OnRequestCancelled(); | |
| 1625 info->set_ssl_client_auth_handler(NULL); | |
| 1626 } | |
| 1627 request->Cancel(); | |
| 1628 // Our callers assume |request| is valid after we return. | |
| 1629 DCHECK(IsValidRequest(request)); | |
| 1630 return true; | |
| 1631 } | |
| 1632 | |
| 1633 // Do not remove from the pending requests, as the request will still | |
| 1634 // call AllDataReceived, and may even have more data before it does | |
| 1635 // that. | |
| 1636 return false; | |
| 1637 } | 1451 } |
| 1638 | 1452 |
| 1639 int ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemoryCost( | 1453 int ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemoryCost( |
| 1640 int cost, | 1454 int cost, |
| 1641 int child_id) { | 1455 int child_id) { |
| 1642 // Retrieve the previous value (defaulting to 0 if not found). | 1456 // Retrieve the previous value (defaulting to 0 if not found). |
| 1643 OutstandingRequestsMemoryCostMap::iterator prev_entry = | 1457 OutstandingRequestsMemoryCostMap::iterator prev_entry = |
| 1644 outstanding_requests_memory_cost_map_.find(child_id); | 1458 outstanding_requests_memory_cost_map_.find(child_id); |
| 1645 int new_cost = 0; | 1459 int new_cost = 0; |
| 1646 if (prev_entry != outstanding_requests_memory_cost_map_.end()) | 1460 if (prev_entry != outstanding_requests_memory_cost_map_.end()) |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1667 request->original_url().spec().size() + | 1481 request->original_url().spec().size() + |
| 1668 request->referrer().size() + | 1482 request->referrer().size() + |
| 1669 request->method().size(); | 1483 request->method().size(); |
| 1670 | 1484 |
| 1671 // Note that this expression will typically be dominated by: | 1485 // Note that this expression will typically be dominated by: |
| 1672 // |kAvgBytesPerOutstandingRequest|. | 1486 // |kAvgBytesPerOutstandingRequest|. |
| 1673 return kAvgBytesPerOutstandingRequest + strings_cost; | 1487 return kAvgBytesPerOutstandingRequest + strings_cost; |
| 1674 } | 1488 } |
| 1675 | 1489 |
| 1676 void ResourceDispatcherHostImpl::BeginRequestInternal( | 1490 void ResourceDispatcherHostImpl::BeginRequestInternal( |
| 1677 net::URLRequest* request) { | 1491 scoped_ptr<net::URLRequest> request, |
| 1492 scoped_ptr<ResourceHandler> handler) { | |
| 1678 DCHECK(!request->is_pending()); | 1493 DCHECK(!request->is_pending()); |
| 1679 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | 1494 ResourceRequestInfoImpl* info = |
| 1495 ResourceRequestInfoImpl::ForRequest(request.get()); | |
| 1680 | 1496 |
| 1681 if ((TimeTicks::Now() - last_user_gesture_time_) < | 1497 if ((TimeTicks::Now() - last_user_gesture_time_) < |
| 1682 TimeDelta::FromMilliseconds(kUserGestureWindowMs)) { | 1498 TimeDelta::FromMilliseconds(kUserGestureWindowMs)) { |
| 1683 request->set_load_flags( | 1499 request->set_load_flags( |
| 1684 request->load_flags() | net::LOAD_MAYBE_USER_GESTURE); | 1500 request->load_flags() | net::LOAD_MAYBE_USER_GESTURE); |
| 1685 } | 1501 } |
| 1686 | 1502 |
| 1687 // Add the memory estimate that starting this request will consume. | 1503 // Add the memory estimate that starting this request will consume. |
| 1688 info->set_memory_cost(CalculateApproximateMemoryCost(request)); | 1504 info->set_memory_cost(CalculateApproximateMemoryCost(request.get())); |
| 1689 int memory_cost = IncrementOutstandingRequestsMemoryCost(info->memory_cost(), | 1505 int memory_cost = IncrementOutstandingRequestsMemoryCost(info->memory_cost(), |
| 1690 info->GetChildID()); | 1506 info->GetChildID()); |
| 1691 | 1507 |
| 1692 // If enqueing/starting this request will exceed our per-process memory | 1508 // If enqueing/starting this request will exceed our per-process memory |
| 1693 // bound, abort it right away. | 1509 // bound, abort it right away. |
| 1694 if (memory_cost > max_outstanding_requests_cost_per_process_) { | 1510 if (memory_cost > max_outstanding_requests_cost_per_process_) { |
| 1695 // We call "CancelWithError()" as a way of setting the net::URLRequest's | 1511 // We call "CancelWithError()" as a way of setting the net::URLRequest's |
| 1696 // status -- it has no effect beyond this, since the request hasn't started. | 1512 // status -- it has no effect beyond this, since the request hasn't started. |
| 1697 request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); | 1513 request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); |
| 1698 | 1514 |
| 1699 // TODO(eroman): this is kinda funky -- we insert the unstarted request into | 1515 if (!handler->OnResponseCompleted(info->GetRequestID(), request->status(), |
| 1700 // |pending_requests_| simply to please ResponseCompleted(). | 1516 std::string())) { |
| 1701 GlobalRequestID global_id(info->GetChildID(), info->GetRequestID()); | 1517 // TODO(darin): The handler is not ready for us to kill the request. Oops! |
| 1702 pending_requests_[global_id] = request; | 1518 NOTREACHED(); |
| 1703 ResponseCompleted(request); | 1519 } |
| 1520 | |
| 1521 IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), | |
| 1522 info->GetChildID()); | |
| 1704 return; | 1523 return; |
| 1705 } | 1524 } |
| 1706 | 1525 |
| 1707 std::pair<int, int> pair_id(info->GetChildID(), info->GetRouteID()); | 1526 linked_ptr<ResourceLoader> loader( |
| 1708 BlockedRequestMap::const_iterator iter = blocked_requests_map_.find(pair_id); | 1527 new ResourceLoader(request.Pass(), handler.Pass(), this)); |
| 1709 if (iter != blocked_requests_map_.end()) { | 1528 |
| 1529 ProcessRouteIDs pair_id(info->GetChildID(), info->GetRouteID()); | |
| 1530 BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(pair_id); | |
| 1531 if (iter != blocked_loaders_map_.end()) { | |
| 1710 // The request should be blocked. | 1532 // The request should be blocked. |
| 1711 iter->second->push_back(request); | 1533 iter->second->push_back(loader); |
| 1712 return; | 1534 return; |
| 1713 } | 1535 } |
| 1714 | 1536 |
| 1715 GlobalRequestID global_id(info->GetChildID(), info->GetRequestID()); | 1537 StartLoading(info, loader); |
| 1716 pending_requests_[global_id] = request; | |
| 1717 | |
| 1718 // Give the resource handlers an opportunity to delay the net::URLRequest from | |
| 1719 // being started. | |
| 1720 // | |
| 1721 // There are three cases: | |
| 1722 // | |
| 1723 // (1) if OnWillStart() returns false, the request is cancelled (regardless | |
| 1724 // of whether |defer_start| was set). | |
| 1725 // (2) If |defer_start| was set to true, then the request is not added | |
| 1726 // into the resource queue, and will only be started in response to | |
| 1727 // calling StartDeferredRequest(). | |
| 1728 // (3) If |defer_start| is not set, then the request is inserted into | |
| 1729 // the resource_queue_ (which may pause it further, or start it). | |
| 1730 bool defer_start = false; | |
| 1731 if (!info->resource_handler()->OnWillStart( | |
| 1732 info->GetRequestID(), request->url(), | |
| 1733 &defer_start)) { | |
| 1734 CancelRequestInternal(request, false); | |
| 1735 return; | |
| 1736 } | |
| 1737 | |
| 1738 if (!defer_start) | |
| 1739 StartRequest(request); | |
| 1740 } | 1538 } |
| 1741 | 1539 |
| 1742 void ResourceDispatcherHostImpl::StartRequest(net::URLRequest* request) { | 1540 void ResourceDispatcherHostImpl::StartLoading( |
| 1743 request->Start(); | 1541 ResourceRequestInfoImpl* info, |
| 1542 const linked_ptr<ResourceLoader>& loader) { | |
| 1543 pending_loaders_[info->GetGlobalRequestID()] = loader; | |
| 1744 | 1544 |
| 1745 // Make sure we have the load state monitor running | 1545 loader->StartRequest(); |
| 1746 if (!update_load_states_timer_->IsRunning()) { | |
| 1747 update_load_states_timer_->Start(FROM_HERE, | |
| 1748 TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), | |
| 1749 this, &ResourceDispatcherHostImpl::UpdateLoadStates); | |
| 1750 } | |
| 1751 } | |
| 1752 | |
| 1753 bool ResourceDispatcherHostImpl::PauseRequestIfNeeded( | |
| 1754 ResourceRequestInfoImpl* info) { | |
| 1755 if (info->pause_count() > 0) | |
| 1756 info->set_is_paused(true); | |
| 1757 return info->is_paused(); | |
| 1758 } | |
| 1759 | |
| 1760 void ResourceDispatcherHostImpl::PauseRequest(int child_id, | |
| 1761 int request_id, | |
| 1762 bool pause) { | |
| 1763 GlobalRequestID global_id(child_id, request_id); | |
| 1764 PendingRequestList::iterator i = pending_requests_.find(global_id); | |
| 1765 if (i == pending_requests_.end()) { | |
| 1766 DVLOG(1) << "Pausing a request that wasn't found"; | |
| 1767 return; | |
| 1768 } | |
| 1769 | |
| 1770 ResourceRequestInfoImpl* info = | |
| 1771 ResourceRequestInfoImpl::ForRequest(i->second); | |
| 1772 int pause_count = info->pause_count() + (pause ? 1 : -1); | |
| 1773 if (pause_count < 0) { | |
| 1774 NOTREACHED(); // Unbalanced call to pause. | |
| 1775 return; | |
| 1776 } | |
| 1777 info->set_pause_count(pause_count); | |
| 1778 | |
| 1779 VLOG(1) << "To pause (" << pause << "): " << i->second->url().spec(); | |
| 1780 | |
| 1781 // If we're resuming, kick the request to start reading again. Run the read | |
| 1782 // asynchronously to avoid recursion problems. | |
| 1783 if (info->pause_count() == 0) { | |
| 1784 MessageLoop::current()->PostTask(FROM_HERE, | |
| 1785 base::Bind(&ResourceDispatcherHostImpl::ResumeRequest, | |
| 1786 AsWeakPtr(), global_id)); | |
| 1787 } | |
| 1788 } | |
| 1789 | |
| 1790 void ResourceDispatcherHostImpl::ResumeRequest( | |
| 1791 const GlobalRequestID& request_id) { | |
| 1792 PendingRequestList::iterator i = pending_requests_.find(request_id); | |
| 1793 if (i == pending_requests_.end()) // The request may have been destroyed | |
| 1794 return; | |
| 1795 | |
| 1796 net::URLRequest* request = i->second; | |
| 1797 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1798 | |
| 1799 // We may already be unpaused, or the pause count may have increased since we | |
| 1800 // posted the task to call ResumeRequest. | |
| 1801 if (!info->is_paused()) | |
| 1802 return; | |
| 1803 info->set_is_paused(false); | |
| 1804 if (PauseRequestIfNeeded(info)) | |
| 1805 return; | |
| 1806 | |
| 1807 VLOG(1) << "Resuming: \"" << i->second->url().spec() << "\"" | |
| 1808 << " paused_read_bytes = " << info->paused_read_bytes() | |
| 1809 << " called response started = " << info->called_on_response_started() | |
| 1810 << " started reading = " << info->has_started_reading(); | |
| 1811 | |
| 1812 if (info->called_on_response_started()) { | |
| 1813 if (info->has_started_reading()) { | |
| 1814 OnReadCompleted(i->second, info->paused_read_bytes()); | |
| 1815 } else { | |
| 1816 StartReading(request); | |
| 1817 } | |
| 1818 } else { | |
| 1819 OnResponseStarted(i->second); | |
| 1820 } | |
| 1821 } | |
| 1822 | |
| 1823 void ResourceDispatcherHostImpl::StartReading(net::URLRequest* request) { | |
| 1824 // Start reading. | |
| 1825 int bytes_read = 0; | |
| 1826 if (Read(request, &bytes_read)) { | |
| 1827 OnReadCompleted(request, bytes_read); | |
| 1828 } else if (!request->status().is_io_pending()) { | |
| 1829 DCHECK(!ResourceRequestInfoImpl::ForRequest(request)->is_paused()); | |
| 1830 // If the error is not an IO pending, then we're done reading. | |
| 1831 ResponseCompleted(request); | |
| 1832 } | |
| 1833 } | |
| 1834 | |
| 1835 bool ResourceDispatcherHostImpl::Read(net::URLRequest* request, | |
| 1836 int* bytes_read) { | |
| 1837 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1838 DCHECK(!info->is_paused()); | |
| 1839 | |
| 1840 net::IOBuffer* buf; | |
| 1841 int buf_size; | |
| 1842 if (!info->resource_handler()->OnWillRead(info->GetRequestID(), | |
| 1843 &buf, &buf_size, -1)) { | |
| 1844 return false; | |
| 1845 } | |
| 1846 | |
| 1847 DCHECK(buf); | |
| 1848 DCHECK(buf_size > 0); | |
| 1849 | |
| 1850 info->set_has_started_reading(true); | |
| 1851 return request->Read(buf, buf_size, bytes_read); | |
| 1852 } | |
| 1853 | |
| 1854 void ResourceDispatcherHostImpl::OnReadCompleted(net::URLRequest* request, | |
| 1855 int bytes_read) { | |
| 1856 DCHECK(request); | |
| 1857 VLOG(1) << "OnReadCompleted: \"" << request->url().spec() << "\"" | |
| 1858 << " bytes_read = " << bytes_read; | |
| 1859 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1860 | |
| 1861 // bytes_read == -1 always implies an error, so we want to skip the pause | |
| 1862 // checks and just call ResponseCompleted. | |
| 1863 if (bytes_read == -1) { | |
| 1864 DCHECK(!request->status().is_success()); | |
| 1865 | |
| 1866 ResponseCompleted(request); | |
| 1867 return; | |
| 1868 } | |
| 1869 | |
| 1870 // OnReadCompleted can be called without Read (e.g., for chrome:// URLs). | |
| 1871 // Make sure we know that a read has begun. | |
| 1872 info->set_has_started_reading(true); | |
| 1873 | |
| 1874 if (PauseRequestIfNeeded(info)) { | |
| 1875 info->set_paused_read_bytes(bytes_read); | |
| 1876 VLOG(1) << "OnReadCompleted pausing: \"" << request->url().spec() << "\"" | |
| 1877 << " bytes_read = " << bytes_read; | |
| 1878 return; | |
| 1879 } | |
| 1880 | |
| 1881 if (request->status().is_success() && CompleteRead(request, &bytes_read)) { | |
| 1882 // The request can be paused if we realize that the renderer is not | |
| 1883 // servicing messages fast enough. | |
| 1884 if (info->pause_count() == 0 && | |
| 1885 Read(request, &bytes_read) && | |
| 1886 request->status().is_success()) { | |
| 1887 if (bytes_read == 0) { | |
| 1888 CompleteRead(request, &bytes_read); | |
| 1889 } else { | |
| 1890 // Force the next CompleteRead / Read pair to run as a separate task. | |
| 1891 // This avoids a fast, large network request from monopolizing the IO | |
| 1892 // thread and starving other IO operations from running. | |
| 1893 VLOG(1) << "OnReadCompleted postponing: \"" | |
| 1894 << request->url().spec() << "\"" | |
| 1895 << " bytes_read = " << bytes_read; | |
| 1896 info->set_paused_read_bytes(bytes_read); | |
| 1897 info->set_is_paused(true); | |
| 1898 GlobalRequestID id(info->GetChildID(), info->GetRequestID()); | |
| 1899 MessageLoop::current()->PostTask( | |
| 1900 FROM_HERE, | |
| 1901 base::Bind(&ResourceDispatcherHostImpl::ResumeRequest, | |
| 1902 AsWeakPtr(), id)); | |
| 1903 return; | |
| 1904 } | |
| 1905 } | |
| 1906 } | |
| 1907 | |
| 1908 if (PauseRequestIfNeeded(info)) { | |
| 1909 info->set_paused_read_bytes(bytes_read); | |
| 1910 VLOG(1) << "OnReadCompleted (CompleteRead) pausing: \"" | |
| 1911 << request->url().spec() << "\"" | |
| 1912 << " bytes_read = " << bytes_read; | |
| 1913 return; | |
| 1914 } | |
| 1915 | |
| 1916 // If the status is not IO pending then we've either finished (success) or we | |
| 1917 // had an error. Either way, we're done! | |
| 1918 if (!request->status().is_io_pending()) | |
| 1919 ResponseCompleted(request); | |
| 1920 } | |
| 1921 | |
| 1922 bool ResourceDispatcherHostImpl::CompleteRead(net::URLRequest* request, | |
| 1923 int* bytes_read) { | |
| 1924 if (!request || !request->status().is_success()) { | |
| 1925 NOTREACHED(); | |
| 1926 return false; | |
| 1927 } | |
| 1928 | |
| 1929 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1930 | |
| 1931 bool defer = false; | |
| 1932 if (!info->resource_handler()->OnReadCompleted(info->GetRequestID(), | |
| 1933 bytes_read, &defer)) { | |
| 1934 CancelRequestInternal(request, false); | |
| 1935 return false; | |
| 1936 } | |
| 1937 | |
| 1938 if (defer) | |
| 1939 PauseRequest(info->GetChildID(), info->GetRequestID(), true); | |
| 1940 | |
| 1941 return *bytes_read != 0; | |
| 1942 } | |
| 1943 | |
| 1944 void ResourceDispatcherHostImpl::ResponseCompleted(net::URLRequest* request) { | |
| 1945 VLOG(1) << "ResponseCompleted: " << request->url().spec(); | |
| 1946 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 1947 | |
| 1948 // Record final result of all resource loads. | |
| 1949 if (info->GetResourceType() == ResourceType::MAIN_FRAME) { | |
| 1950 // This enumeration has "3" appended to its name to distinguish it from | |
| 1951 // older versions. | |
| 1952 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 1953 "Net.ErrorCodesForMainFrame3", | |
| 1954 -request->status().error(), | |
| 1955 base::CustomHistogram::ArrayToCustomRanges( | |
| 1956 kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); | |
| 1957 | |
| 1958 if (request->url().SchemeIsSecure() && | |
| 1959 request->url().host() == "www.google.com") { | |
| 1960 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 1961 "Net.ErrorCodesForHTTPSGoogleMainFrame2", | |
| 1962 -request->status().error(), | |
| 1963 base::CustomHistogram::ArrayToCustomRanges( | |
| 1964 kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); | |
| 1965 } | |
| 1966 } else { | |
| 1967 // This enumeration has "2" appended to distinguish it from older versions. | |
| 1968 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 1969 "Net.ErrorCodesForSubresources2", | |
| 1970 -request->status().error(), | |
| 1971 base::CustomHistogram::ArrayToCustomRanges( | |
| 1972 kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); | |
| 1973 } | |
| 1974 | |
| 1975 std::string security_info; | |
| 1976 const net::SSLInfo& ssl_info = request->ssl_info(); | |
| 1977 if (ssl_info.cert != NULL) { | |
| 1978 int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert, | |
| 1979 info->GetChildID()); | |
| 1980 security_info = SerializeSecurityInfo( | |
| 1981 cert_id, ssl_info.cert_status, ssl_info.security_bits, | |
| 1982 ssl_info.connection_status); | |
| 1983 } | |
| 1984 | |
| 1985 if (info->resource_handler()->OnResponseCompleted(info->GetRequestID(), | |
| 1986 request->status(), | |
| 1987 security_info)) { | |
| 1988 | |
| 1989 // The request is complete so we can remove it. | |
| 1990 RemovePendingRequest(info->GetChildID(), info->GetRequestID()); | |
| 1991 } | |
| 1992 // If the handler's OnResponseCompleted returns false, we are deferring the | |
| 1993 // call until later. We will notify the world and clean up when we resume. | |
| 1994 } | |
| 1995 | |
| 1996 void ResourceDispatcherHostImpl::CallResponseCompleted(int child_id, | |
| 1997 int request_id) { | |
| 1998 PendingRequestList::iterator i = pending_requests_.find( | |
| 1999 GlobalRequestID(child_id, request_id)); | |
| 2000 if (i != pending_requests_.end()) | |
| 2001 ResponseCompleted(i->second); | |
| 2002 } | |
| 2003 | |
| 2004 // SSLErrorHandler::Delegate --------------------------------------------------- | |
| 2005 | |
| 2006 void ResourceDispatcherHostImpl::CancelSSLRequest( | |
| 2007 const GlobalRequestID& id, | |
| 2008 int error, | |
| 2009 const net::SSLInfo* ssl_info) { | |
| 2010 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 2011 net::URLRequest* request = GetURLRequest(id); | |
| 2012 // The request can be NULL if it was cancelled by the renderer (as the | |
| 2013 // request of the user navigating to a new page from the location bar). | |
| 2014 if (!request || !request->is_pending()) | |
| 2015 return; | |
| 2016 DVLOG(1) << "CancelSSLRequest() url: " << request->url().spec(); | |
| 2017 if (ssl_info) | |
| 2018 request->CancelWithSSLError(error, *ssl_info); | |
| 2019 else | |
| 2020 request->CancelWithError(error); | |
| 2021 } | |
| 2022 | |
| 2023 void ResourceDispatcherHostImpl::ContinueSSLRequest( | |
| 2024 const GlobalRequestID& id) { | |
| 2025 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 2026 net::URLRequest* request = GetURLRequest(id); | |
| 2027 // The request can be NULL if it was cancelled by the renderer (as the | |
| 2028 // request of the user navigating to a new page from the location bar). | |
| 2029 if (!request) | |
| 2030 return; | |
| 2031 DVLOG(1) << "ContinueSSLRequest() url: " << request->url().spec(); | |
| 2032 request->ContinueDespiteLastError(); | |
| 2033 } | 1546 } |
| 2034 | 1547 |
| 2035 void ResourceDispatcherHostImpl::OnUserGesture(WebContentsImpl* contents) { | 1548 void ResourceDispatcherHostImpl::OnUserGesture(WebContentsImpl* contents) { |
| 2036 last_user_gesture_time_ = TimeTicks::Now(); | 1549 last_user_gesture_time_ = TimeTicks::Now(); |
| 2037 } | 1550 } |
| 2038 | 1551 |
| 2039 net::URLRequest* ResourceDispatcherHostImpl::GetURLRequest( | 1552 net::URLRequest* ResourceDispatcherHostImpl::GetURLRequest( |
| 2040 const GlobalRequestID& request_id) const { | 1553 const GlobalRequestID& id) { |
| 2041 // This should be running in the IO loop. | 1554 ResourceLoader* loader = GetLoader(id); |
| 2042 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 1555 if (!loader) |
| 2043 | |
| 2044 PendingRequestList::const_iterator i = pending_requests_.find(request_id); | |
| 2045 if (i == pending_requests_.end()) | |
| 2046 return NULL; | 1556 return NULL; |
| 2047 | 1557 |
| 2048 return i->second; | 1558 return loader->request(); |
| 2049 } | |
| 2050 | |
| 2051 static int GetCertID(net::URLRequest* request, int child_id) { | |
| 2052 if (request->ssl_info().cert) { | |
| 2053 return CertStore::GetInstance()->StoreCert(request->ssl_info().cert, | |
| 2054 child_id); | |
| 2055 } | |
| 2056 return 0; | |
| 2057 } | |
| 2058 | |
| 2059 void ResourceDispatcherHostImpl::NotifyResponseStarted(net::URLRequest* request, | |
| 2060 int child_id) { | |
| 2061 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 2062 | |
| 2063 int render_process_id, render_view_id; | |
| 2064 if (!RenderViewForRequest(request, &render_process_id, &render_view_id)) | |
| 2065 return; | |
| 2066 | |
| 2067 // Notify the observers on the UI thread. | |
| 2068 ResourceRequestDetails* detail = new ResourceRequestDetails( | |
| 2069 request, GetCertID(request, child_id)); | |
| 2070 BrowserThread::PostTask( | |
| 2071 BrowserThread::UI, FROM_HERE, | |
| 2072 base::Bind( | |
| 2073 &ResourceDispatcherHostImpl::NotifyOnUI<ResourceRequestDetails>, | |
| 2074 static_cast<int>(NOTIFICATION_RESOURCE_RESPONSE_STARTED), | |
| 2075 render_process_id, render_view_id, detail)); | |
| 2076 } | |
| 2077 | |
| 2078 void ResourceDispatcherHostImpl::NotifyReceivedRedirect( | |
| 2079 net::URLRequest* request, | |
| 2080 int child_id, | |
| 2081 const GURL& new_url) { | |
| 2082 int render_process_id, render_view_id; | |
| 2083 if (!RenderViewForRequest(request, &render_process_id, &render_view_id)) | |
| 2084 return; | |
| 2085 | |
| 2086 // Notify the observers on the UI thread. | |
| 2087 ResourceRedirectDetails* detail = new ResourceRedirectDetails( | |
| 2088 request, GetCertID(request, child_id), new_url); | |
| 2089 BrowserThread::PostTask( | |
| 2090 BrowserThread::UI, FROM_HERE, | |
| 2091 base::Bind( | |
| 2092 &ResourceDispatcherHostImpl::NotifyOnUI<ResourceRedirectDetails>, | |
| 2093 static_cast<int>(NOTIFICATION_RESOURCE_RECEIVED_REDIRECT), | |
| 2094 render_process_id, render_view_id, detail)); | |
| 2095 } | |
| 2096 | |
| 2097 template <class T> | |
| 2098 void ResourceDispatcherHostImpl::NotifyOnUI(int type, | |
| 2099 int render_process_id, | |
| 2100 int render_view_id, | |
| 2101 T* detail) { | |
| 2102 RenderViewHostImpl* rvh = | |
| 2103 RenderViewHostImpl::FromID(render_process_id, render_view_id); | |
| 2104 if (rvh) { | |
| 2105 RenderViewHostDelegate* rvhd = rvh->GetDelegate(); | |
| 2106 NotificationService::current()->Notify( | |
| 2107 type, Source<WebContents>(rvhd->GetAsWebContents()), | |
| 2108 Details<T>(detail)); | |
| 2109 } | |
| 2110 delete detail; | |
| 2111 } | 1559 } |
| 2112 | 1560 |
| 2113 namespace { | 1561 namespace { |
| 2114 | 1562 |
| 2115 // This function attempts to return the "more interesting" load state of |a| | 1563 // This function attempts to return the "more interesting" load state of |a| |
| 2116 // and |b|. We don't have temporal information about these load states | 1564 // and |b|. We don't have temporal information about these load states |
| 2117 // (meaning we don't know when we transitioned into these states), so we just | 1565 // (meaning we don't know when we transitioned into these states), so we just |
| 2118 // rank them according to how "interesting" the states are. | 1566 // rank them according to how "interesting" the states are. |
| 2119 // | 1567 // |
| 2120 // We take advantage of the fact that the load states are an enumeration listed | 1568 // We take advantage of the fact that the load states are an enumeration listed |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2158 } | 1606 } |
| 2159 } | 1607 } |
| 2160 | 1608 |
| 2161 } // namespace | 1609 } // namespace |
| 2162 | 1610 |
| 2163 void ResourceDispatcherHostImpl::UpdateLoadStates() { | 1611 void ResourceDispatcherHostImpl::UpdateLoadStates() { |
| 2164 // Populate this map with load state changes, and then send them on to the UI | 1612 // Populate this map with load state changes, and then send them on to the UI |
| 2165 // thread where they can be passed along to the respective RVHs. | 1613 // thread where they can be passed along to the respective RVHs. |
| 2166 LoadInfoMap info_map; | 1614 LoadInfoMap info_map; |
| 2167 | 1615 |
| 2168 PendingRequestList::const_iterator i; | 1616 LoaderMap::const_iterator i; |
| 2169 | 1617 |
| 2170 // Determine the largest upload size of all requests | 1618 // Determine the largest upload size of all requests |
| 2171 // in each View (good chance it's zero). | 1619 // in each View (good chance it's zero). |
| 2172 std::map<std::pair<int, int>, uint64> largest_upload_size; | 1620 std::map<std::pair<int, int>, uint64> largest_upload_size; |
| 2173 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { | 1621 for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) { |
| 2174 net::URLRequest* request = i->second; | 1622 net::URLRequest* request = i->second->request(); |
| 2175 ResourceRequestInfoImpl* info = | 1623 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); |
| 2176 ResourceRequestInfoImpl::ForRequest(request); | |
| 2177 uint64 upload_size = info->GetUploadSize(); | 1624 uint64 upload_size = info->GetUploadSize(); |
| 2178 if (request->GetLoadState().state != net::LOAD_STATE_SENDING_REQUEST) | 1625 if (request->GetLoadState().state != net::LOAD_STATE_SENDING_REQUEST) |
| 2179 upload_size = 0; | 1626 upload_size = 0; |
| 2180 std::pair<int, int> key(info->GetChildID(), info->GetRouteID()); | 1627 std::pair<int, int> key(info->GetChildID(), info->GetRouteID()); |
| 2181 if (upload_size && largest_upload_size[key] < upload_size) | 1628 if (upload_size && largest_upload_size[key] < upload_size) |
| 2182 largest_upload_size[key] = upload_size; | 1629 largest_upload_size[key] = upload_size; |
| 2183 } | 1630 } |
| 2184 | 1631 |
| 2185 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { | 1632 for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) { |
| 2186 net::URLRequest* request = i->second; | 1633 net::URLRequest* request = i->second->request(); |
| 1634 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); | |
| 2187 net::LoadStateWithParam load_state = request->GetLoadState(); | 1635 net::LoadStateWithParam load_state = request->GetLoadState(); |
| 2188 ResourceRequestInfoImpl* info = | |
| 2189 ResourceRequestInfoImpl::ForRequest(request); | |
| 2190 std::pair<int, int> key(info->GetChildID(), info->GetRouteID()); | |
| 2191 | 1636 |
| 2192 // We also poll for upload progress on this timer and send upload | 1637 // We also poll for upload progress on this timer and send upload |
| 2193 // progress ipc messages to the plugin process. | 1638 // progress ipc messages to the plugin process. |
| 2194 MaybeUpdateUploadProgress(info, request); | 1639 i->second->ReportUploadProgress(); |
| 1640 | |
| 1641 std::pair<int, int> key(info->GetChildID(), info->GetRouteID()); | |
| 2195 | 1642 |
| 2196 // If a request is uploading data, ignore all other requests so that the | 1643 // If a request is uploading data, ignore all other requests so that the |
| 2197 // upload progress takes priority for being shown in the status bar. | 1644 // upload progress takes priority for being shown in the status bar. |
| 2198 if (largest_upload_size.find(key) != largest_upload_size.end() && | 1645 if (largest_upload_size.find(key) != largest_upload_size.end() && |
| 2199 info->GetUploadSize() < largest_upload_size[key]) | 1646 info->GetUploadSize() < largest_upload_size[key]) |
| 2200 continue; | 1647 continue; |
| 2201 | 1648 |
| 2202 net::LoadStateWithParam to_insert = load_state; | 1649 net::LoadStateWithParam to_insert = load_state; |
| 2203 LoadInfoMap::iterator existing = info_map.find(key); | 1650 LoadInfoMap::iterator existing = info_map.find(key); |
| 2204 if (existing != info_map.end()) { | 1651 if (existing != info_map.end()) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 2215 } | 1662 } |
| 2216 | 1663 |
| 2217 if (info_map.empty()) | 1664 if (info_map.empty()) |
| 2218 return; | 1665 return; |
| 2219 | 1666 |
| 2220 BrowserThread::PostTask( | 1667 BrowserThread::PostTask( |
| 2221 BrowserThread::UI, FROM_HERE, | 1668 BrowserThread::UI, FROM_HERE, |
| 2222 base::Bind(&LoadInfoUpdateCallback, info_map)); | 1669 base::Bind(&LoadInfoUpdateCallback, info_map)); |
| 2223 } | 1670 } |
| 2224 | 1671 |
| 2225 // Calls the ResourceHandler to send upload progress messages to the renderer. | |
| 2226 void ResourceDispatcherHostImpl::MaybeUpdateUploadProgress( | |
| 2227 ResourceRequestInfoImpl *info, | |
| 2228 net::URLRequest *request) { | |
| 2229 | |
| 2230 if (!info->GetUploadSize() || info->waiting_for_upload_progress_ack()) | |
| 2231 return; | |
| 2232 | |
| 2233 uint64 size = info->GetUploadSize(); | |
| 2234 uint64 position = request->GetUploadProgress(); | |
| 2235 if (position == info->last_upload_position()) | |
| 2236 return; // no progress made since last time | |
| 2237 | |
| 2238 const uint64 kHalfPercentIncrements = 200; | |
| 2239 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); | |
| 2240 | |
| 2241 uint64 amt_since_last = position - info->last_upload_position(); | |
| 2242 TimeDelta time_since_last = TimeTicks::Now() - info->last_upload_ticks(); | |
| 2243 | |
| 2244 bool is_finished = (size == position); | |
| 2245 bool enough_new_progress = (amt_since_last > (size / kHalfPercentIncrements)); | |
| 2246 bool too_much_time_passed = time_since_last > kOneSecond; | |
| 2247 | |
| 2248 if (is_finished || enough_new_progress || too_much_time_passed) { | |
| 2249 if (request->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) { | |
| 2250 info->resource_handler()->OnUploadProgress(info->GetRequestID(), | |
| 2251 position, size); | |
| 2252 info->set_waiting_for_upload_progress_ack(true); | |
| 2253 } | |
| 2254 info->set_last_upload_ticks(TimeTicks::Now()); | |
| 2255 info->set_last_upload_position(position); | |
| 2256 } | |
| 2257 } | |
| 2258 | |
| 2259 void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id, | 1672 void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id, |
| 2260 int route_id) { | 1673 int route_id) { |
| 2261 std::pair<int, int> key(child_id, route_id); | 1674 ProcessRouteIDs key(child_id, route_id); |
| 2262 DCHECK(blocked_requests_map_.find(key) == blocked_requests_map_.end()) << | 1675 DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) << |
| 2263 "BlockRequestsForRoute called multiple time for the same RVH"; | 1676 "BlockRequestsForRoute called multiple time for the same RVH"; |
| 2264 blocked_requests_map_[key] = new BlockedRequestsList(); | 1677 blocked_loaders_map_[key] = new BlockedLoadersList(); |
| 2265 } | 1678 } |
| 2266 | 1679 |
| 2267 void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(int child_id, | 1680 void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(int child_id, |
| 2268 int route_id) { | 1681 int route_id) { |
| 2269 ProcessBlockedRequestsForRoute(child_id, route_id, false); | 1682 ProcessBlockedRequestsForRoute(child_id, route_id, false); |
| 2270 } | 1683 } |
| 2271 | 1684 |
| 2272 void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(int child_id, | 1685 void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(int child_id, |
| 2273 int route_id) { | 1686 int route_id) { |
| 2274 ProcessBlockedRequestsForRoute(child_id, route_id, true); | 1687 ProcessBlockedRequestsForRoute(child_id, route_id, true); |
| 2275 } | 1688 } |
| 2276 | 1689 |
| 2277 void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute( | 1690 void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute( |
| 2278 int child_id, | 1691 int child_id, |
| 2279 int route_id, | 1692 int route_id, |
| 2280 bool cancel_requests) { | 1693 bool cancel_requests) { |
| 2281 BlockedRequestMap::iterator iter = blocked_requests_map_.find( | 1694 BlockedLoadersMap::iterator iter = blocked_loaders_map_.find( |
| 2282 std::pair<int, int>(child_id, route_id)); | 1695 std::pair<int, int>(child_id, route_id)); |
| 2283 if (iter == blocked_requests_map_.end()) { | 1696 if (iter == blocked_loaders_map_.end()) { |
| 2284 // It's possible to reach here if the renderer crashed while an interstitial | 1697 // It's possible to reach here if the renderer crashed while an interstitial |
| 2285 // page was showing. | 1698 // page was showing. |
| 2286 return; | 1699 return; |
| 2287 } | 1700 } |
| 2288 | 1701 |
| 2289 BlockedRequestsList* requests = iter->second; | 1702 BlockedLoadersList* loaders = iter->second; |
| 2290 | 1703 |
| 2291 // Removing the vector from the map unblocks any subsequent requests. | 1704 // Removing the vector from the map unblocks any subsequent requests. |
| 2292 blocked_requests_map_.erase(iter); | 1705 blocked_loaders_map_.erase(iter); |
| 2293 | 1706 |
| 2294 for (BlockedRequestsList::iterator req_iter = requests->begin(); | 1707 for (BlockedLoadersList::iterator loaders_iter = loaders->begin(); |
| 2295 req_iter != requests->end(); ++req_iter) { | 1708 loaders_iter != loaders->end(); ++loaders_iter) { |
| 2296 // Remove the memory credit that we added when pushing the request onto | 1709 linked_ptr<ResourceLoader> loader = *loaders_iter; |
| 2297 // the blocked list. | 1710 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
| 2298 net::URLRequest* request = *req_iter; | 1711 if (cancel_requests) { |
| 2299 ResourceRequestInfoImpl* info = | 1712 IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), |
| 2300 ResourceRequestInfoImpl::ForRequest(request); | 1713 info->GetChildID()); |
| 2301 IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), | 1714 } else { |
| 2302 info->GetChildID()); | 1715 StartLoading(info, loader); |
| 2303 if (cancel_requests) | 1716 } |
| 2304 delete request; | |
| 2305 else | |
| 2306 BeginRequestInternal(request); | |
| 2307 } | 1717 } |
| 2308 | 1718 |
| 2309 delete requests; | 1719 delete loaders; |
| 2310 } | |
| 2311 | |
| 2312 bool ResourceDispatcherHostImpl::IsValidRequest(net::URLRequest* request) { | |
| 2313 if (!request) | |
| 2314 return false; | |
| 2315 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | |
| 2316 return pending_requests_.find( | |
| 2317 GlobalRequestID(info->GetChildID(), info->GetRequestID())) != | |
| 2318 pending_requests_.end(); | |
| 2319 } | 1720 } |
| 2320 | 1721 |
| 2321 ResourceDispatcherHostImpl::HttpAuthResourceType | 1722 ResourceDispatcherHostImpl::HttpAuthResourceType |
| 2322 ResourceDispatcherHostImpl::HttpAuthResourceTypeOf(net::URLRequest* request) { | 1723 ResourceDispatcherHostImpl::HttpAuthResourceTypeOf(net::URLRequest* request) { |
| 2323 // Use the same critera as for cookies to determine the sub-resource type | 1724 // Use the same critera as for cookies to determine the sub-resource type |
| 2324 // that is requesting to be authenticated. | 1725 // that is requesting to be authenticated. |
| 2325 if (!request->first_party_for_cookies().is_valid()) | 1726 if (!request->first_party_for_cookies().is_valid()) |
| 2326 return HTTP_AUTH_RESOURCE_TOP; | 1727 return HTTP_AUTH_RESOURCE_TOP; |
| 2327 | 1728 |
| 2328 if (net::RegistryControlledDomainService::SameDomainOrHost( | 1729 if (net::RegistryControlledDomainService::SameDomainOrHost( |
| 2329 request->first_party_for_cookies(), request->url())) | 1730 request->first_party_for_cookies(), request->url())) |
| 2330 return HTTP_AUTH_RESOURCE_SAME_DOMAIN; | 1731 return HTTP_AUTH_RESOURCE_SAME_DOMAIN; |
| 2331 | 1732 |
| 2332 if (allow_cross_origin_auth_prompt()) | 1733 if (allow_cross_origin_auth_prompt()) |
| 2333 return HTTP_AUTH_RESOURCE_ALLOWED_CROSS; | 1734 return HTTP_AUTH_RESOURCE_ALLOWED_CROSS; |
| 2334 | 1735 |
| 2335 return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; | 1736 return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; |
| 2336 } | 1737 } |
| 2337 | 1738 |
| 2338 bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() { | 1739 bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() { |
| 2339 return allow_cross_origin_auth_prompt_; | 1740 return allow_cross_origin_auth_prompt_; |
| 2340 } | 1741 } |
| 2341 | 1742 |
| 2342 bool ResourceDispatcherHostImpl::IsTransferredNavigation( | 1743 bool ResourceDispatcherHostImpl::IsTransferredNavigation( |
| 2343 const GlobalRequestID& transferred_request_id) const { | 1744 const GlobalRequestID& id) const { |
| 2344 return transferred_navigations_.find(transferred_request_id) != | 1745 ResourceLoader* loader = GetLoader(id); |
| 2345 transferred_navigations_.end(); | 1746 return loader ? loader->is_transferring() : false; |
| 1747 } | |
| 1748 | |
| 1749 ResourceLoader* ResourceDispatcherHostImpl::GetLoader( | |
| 1750 const GlobalRequestID& id) const { | |
| 1751 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 1752 | |
| 1753 LoaderMap::const_iterator i = pending_loaders_.find(id); | |
| 1754 if (i == pending_loaders_.end()) | |
| 1755 return NULL; | |
| 1756 | |
| 1757 return i->second.get(); | |
| 1758 } | |
| 1759 | |
| 1760 ResourceLoader* ResourceDispatcherHostImpl::GetLoader(int child_id, | |
| 1761 int request_id) const { | |
| 1762 return GetLoader(GlobalRequestID(child_id, request_id)); | |
| 2346 } | 1763 } |
| 2347 | 1764 |
| 2348 } // namespace content | 1765 } // namespace content |
| OLD | NEW |