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

Side by Side Diff: content/browser/renderer_host/resource_dispatcher_host_impl.cc

Issue 10501004: Refactor the guts of ResourceDispatcherHostImpl into a new class named (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698