| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/browser/renderer_host/resource_dispatcher_host.h" | 7 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "chrome/browser/download/download_request_manager.h" | 22 #include "chrome/browser/download/download_request_manager.h" |
| 23 #include "chrome/browser/download/save_file_manager.h" | 23 #include "chrome/browser/download/save_file_manager.h" |
| 24 #include "chrome/browser/extensions/user_script_listener.h" | 24 #include "chrome/browser/extensions/user_script_listener.h" |
| 25 #include "chrome/browser/external_protocol_handler.h" | 25 #include "chrome/browser/external_protocol_handler.h" |
| 26 #include "chrome/browser/in_process_webkit/webkit_thread.h" | 26 #include "chrome/browser/in_process_webkit/webkit_thread.h" |
| 27 #include "chrome/browser/login_prompt.h" | 27 #include "chrome/browser/login_prompt.h" |
| 28 #include "chrome/browser/net/chrome_url_request_context.h" | 28 #include "chrome/browser/net/chrome_url_request_context.h" |
| 29 #include "chrome/browser/net/url_request_tracking.h" | 29 #include "chrome/browser/net/url_request_tracking.h" |
| 30 #include "chrome/browser/plugin_service.h" | 30 #include "chrome/browser/plugin_service.h" |
| 31 #include "chrome/browser/privacy_blacklist/blacklist.h" | 31 #include "chrome/browser/privacy_blacklist/blacklist.h" |
| 32 #include "chrome/browser/privacy_blacklist/blacklist_listener.h" |
| 33 #include "chrome/browser/privacy_blacklist/blacklist_manager.h" |
| 34 #include "chrome/browser/privacy_blacklist/blacklist_request_info.h" |
| 32 #include "chrome/browser/profile.h" | 35 #include "chrome/browser/profile.h" |
| 33 #include "chrome/browser/renderer_host/async_resource_handler.h" | 36 #include "chrome/browser/renderer_host/async_resource_handler.h" |
| 34 #include "chrome/browser/renderer_host/buffered_resource_handler.h" | 37 #include "chrome/browser/renderer_host/buffered_resource_handler.h" |
| 35 #include "chrome/browser/renderer_host/cross_site_resource_handler.h" | 38 #include "chrome/browser/renderer_host/cross_site_resource_handler.h" |
| 36 #include "chrome/browser/renderer_host/download_resource_handler.h" | 39 #include "chrome/browser/renderer_host/download_resource_handler.h" |
| 37 #include "chrome/browser/renderer_host/global_request_id.h" | 40 #include "chrome/browser/renderer_host/global_request_id.h" |
| 38 #include "chrome/browser/renderer_host/render_view_host.h" | 41 #include "chrome/browser/renderer_host/render_view_host.h" |
| 39 #include "chrome/browser/renderer_host/render_view_host_delegate.h" | 42 #include "chrome/browser/renderer_host/render_view_host_delegate.h" |
| 40 #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" | 43 #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" |
| 41 #include "chrome/browser/renderer_host/resource_queue.h" | 44 #include "chrome/browser/renderer_host/resource_queue.h" |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 safe_browsing_(new SafeBrowsingService), | 256 safe_browsing_(new SafeBrowsingService), |
| 254 socket_stream_dispatcher_host_(new SocketStreamDispatcherHost), | 257 socket_stream_dispatcher_host_(new SocketStreamDispatcherHost), |
| 255 webkit_thread_(new WebKitThread), | 258 webkit_thread_(new WebKitThread), |
| 256 request_id_(-1), | 259 request_id_(-1), |
| 257 ALLOW_THIS_IN_INITIALIZER_LIST(method_runner_(this)), | 260 ALLOW_THIS_IN_INITIALIZER_LIST(method_runner_(this)), |
| 258 is_shutdown_(false), | 261 is_shutdown_(false), |
| 259 max_outstanding_requests_cost_per_process_( | 262 max_outstanding_requests_cost_per_process_( |
| 260 kMaxOutstandingRequestsCostPerProcess), | 263 kMaxOutstandingRequestsCostPerProcess), |
| 261 receiver_(NULL) { | 264 receiver_(NULL) { |
| 262 ResourceQueue::DelegateSet resource_queue_delegates; | 265 ResourceQueue::DelegateSet resource_queue_delegates; |
| 266 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 267 switches::kEnablePrivacyBlacklists)) { |
| 268 blacklist_listener_ = new BlacklistListener(&resource_queue_); |
| 269 resource_queue_delegates.insert(blacklist_listener_.get()); |
| 270 } |
| 263 resource_queue_delegates.insert(user_script_listener_.get()); | 271 resource_queue_delegates.insert(user_script_listener_.get()); |
| 264 resource_queue_.Initialize(resource_queue_delegates); | 272 resource_queue_.Initialize(resource_queue_delegates); |
| 265 } | 273 } |
| 266 | 274 |
| 267 ResourceDispatcherHost::~ResourceDispatcherHost() { | 275 ResourceDispatcherHost::~ResourceDispatcherHost() { |
| 268 AsyncResourceHandler::GlobalCleanup(); | 276 AsyncResourceHandler::GlobalCleanup(); |
| 269 STLDeleteValues(&pending_requests_); | 277 STLDeleteValues(&pending_requests_); |
| 270 | 278 |
| 271 // Clear blocked requests if any left. | 279 // Clear blocked requests if any left. |
| 272 // Note that we have to do this in 2 passes as we cannot call | 280 // Note that we have to do this in 2 passes as we cannot call |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 // Tell the renderer that this request was disallowed. | 425 // Tell the renderer that this request was disallowed. |
| 418 receiver_->Send(new ViewMsg_Resource_RequestComplete( | 426 receiver_->Send(new ViewMsg_Resource_RequestComplete( |
| 419 route_id, | 427 route_id, |
| 420 request_id, | 428 request_id, |
| 421 status, | 429 status, |
| 422 std::string())); // No security info needed, connection was not | 430 std::string())); // No security info needed, connection was not |
| 423 // established. | 431 // established. |
| 424 } | 432 } |
| 425 return; | 433 return; |
| 426 } | 434 } |
| 427 std::string url = request_data.url.spec(); | |
| 428 | |
| 429 // Note that context can still be NULL here when running unit tests. | |
| 430 Blacklist::Match* match = context && context->GetBlacklist() ? | |
| 431 context->GetBlacklist()->findMatch(request_data.url) : NULL; | |
| 432 if (match && match->IsBlocked(request_data.url)) { | |
| 433 // This is a special path where calling happens without the URLRequest | |
| 434 // being created, so we must delete the match ourselves. Ensures this | |
| 435 // happens by using a scoped pointer. | |
| 436 scoped_ptr<Blacklist::Match> match_scope(match); | |
| 437 | |
| 438 URLRequestStatus status(URLRequestStatus::SUCCESS, 0); | |
| 439 std::string data = | |
| 440 request_data.resource_type != ResourceType::SUB_RESOURCE ? | |
| 441 blocked_.GetHTML(url, match) : blocked_.GetImage(match); | |
| 442 std::string headers = blocked_.GetHeaders(url); | |
| 443 | |
| 444 if (sync_result) { | |
| 445 SyncLoadResult result; | |
| 446 result.status = status; | |
| 447 result.final_url = request_data.url; | |
| 448 result.data.swap(data); | |
| 449 ViewHostMsg_SyncLoad::WriteReplyParams(sync_result, result); | |
| 450 receiver_->Send(sync_result); | |
| 451 } else { | |
| 452 bool success = false; | |
| 453 base::SharedMemory shared; | |
| 454 if (shared.Create(std::wstring(), false, false, data.size())) { | |
| 455 if (shared.Map(data.size())) { | |
| 456 std::copy(data.c_str(), data.c_str() + data.size(), | |
| 457 static_cast<std::string::value_type*>(shared.memory())); | |
| 458 base::SharedMemoryHandle handle; | |
| 459 if (shared.GiveToProcess(receiver_->handle(), &handle)) { | |
| 460 ResourceResponseHead header; | |
| 461 header.mime_type = "text/html"; | |
| 462 header.content_length = -1; | |
| 463 header.status = status; | |
| 464 header.headers = new net::HttpResponseHeaders(headers); | |
| 465 receiver_->Send(new ViewMsg_Resource_ReceivedResponse( | |
| 466 route_id, request_id, header)); | |
| 467 receiver_->Send(new ViewMsg_Resource_DataReceived( | |
| 468 route_id, request_id, handle, data.size())); | |
| 469 receiver_->Send(new ViewMsg_Resource_RequestComplete( | |
| 470 route_id, request_id, status, std::string())); | |
| 471 success = true; | |
| 472 } | |
| 473 } | |
| 474 } | |
| 475 if (!success) { | |
| 476 // Cannot send a substitution response, just cancel. | |
| 477 receiver_->Send(new ViewMsg_Resource_RequestComplete( | |
| 478 route_id, | |
| 479 request_id, | |
| 480 URLRequestStatus(URLRequestStatus::CANCELED, net::ERR_ABORTED), | |
| 481 std::string())); | |
| 482 } | |
| 483 } | |
| 484 return; | |
| 485 } | |
| 486 | 435 |
| 487 // To fetch a blocked resource, convert the unblock URL to the original one. | |
| 488 GURL gurl = request_data.url.scheme() != chrome::kUnblockScheme ? | |
| 489 request_data.url : GURL(blocked_.GetOriginalURL(url)); | |
| 490 | |
| 491 // Ensure the Chrome plugins are loaded, as they may intercept network | 436 // Ensure the Chrome plugins are loaded, as they may intercept network |
| 492 // requests. Does nothing if they are already loaded. | 437 // requests. Does nothing if they are already loaded. |
| 493 // TODO(mpcomplete): This takes 200 ms! Investigate parallelizing this by | 438 // TODO(mpcomplete): This takes 200 ms! Investigate parallelizing this by |
| 494 // starting the load earlier in a BG thread. | 439 // starting the load earlier in a BG thread. |
| 495 PluginService::GetInstance()->LoadChromePlugins(this); | 440 PluginService::GetInstance()->LoadChromePlugins(this); |
| 496 | 441 |
| 497 // Construct the event handler. | 442 // Construct the event handler. |
| 498 scoped_refptr<ResourceHandler> handler; | 443 scoped_refptr<ResourceHandler> handler; |
| 499 if (sync_result) { | 444 if (sync_result) { |
| 500 handler = new SyncResourceHandler(receiver_, gurl, sync_result); | 445 handler = new SyncResourceHandler(receiver_, request_data.url, sync_result); |
| 501 } else { | 446 } else { |
| 502 handler = new AsyncResourceHandler(receiver_, | 447 handler = new AsyncResourceHandler(receiver_, |
| 503 child_id, | 448 child_id, |
| 504 route_id, | 449 route_id, |
| 505 receiver_->handle(), | 450 receiver_->handle(), |
| 506 gurl, | 451 request_data.url, |
| 507 this); | 452 this); |
| 508 } | 453 } |
| 509 | 454 |
| 510 if (HandleExternalProtocol(request_id, child_id, route_id, | 455 if (HandleExternalProtocol(request_id, child_id, route_id, |
| 511 gurl, request_data.resource_type, | 456 request_data.url, request_data.resource_type, |
| 512 handler)) { | 457 handler)) { |
| 513 return; | 458 return; |
| 514 } | 459 } |
| 515 | 460 |
| 516 // Construct the request. | 461 // Construct the request. |
| 517 URLRequest* request = new URLRequest(gurl, this); | 462 URLRequest* request = new URLRequest(request_data.url, this); |
| 518 if (match) { | |
| 519 request->SetUserData(&Blacklist::kRequestDataKey, match); | |
| 520 } | |
| 521 request->set_method(request_data.method); | 463 request->set_method(request_data.method); |
| 522 request->set_first_party_for_cookies(request_data.first_party_for_cookies); | 464 request->set_first_party_for_cookies(request_data.first_party_for_cookies); |
| 523 | 465 request->set_referrer(request_data.referrer.spec()); |
| 524 if (!match || !(match->attributes() & Blacklist::kDontSendReferrer)) | |
| 525 request->set_referrer(request_data.referrer.spec()); | |
| 526 | |
| 527 request->SetExtraRequestHeaders(request_data.headers); | 466 request->SetExtraRequestHeaders(request_data.headers); |
| 528 | 467 |
| 529 int load_flags = request_data.load_flags; | 468 int load_flags = request_data.load_flags; |
| 530 // EV certificate verification could be expensive. We don't want to spend | 469 // EV certificate verification could be expensive. We don't want to spend |
| 531 // time performing EV certificate verification on all resources because | 470 // time performing EV certificate verification on all resources because |
| 532 // EV status is irrelevant to sub-frames and sub-resources. | 471 // EV status is irrelevant to sub-frames and sub-resources. |
| 533 if (request_data.resource_type == ResourceType::MAIN_FRAME) | 472 if (request_data.resource_type == ResourceType::MAIN_FRAME) |
| 534 load_flags |= net::LOAD_VERIFY_EV_CERT; | 473 load_flags |= net::LOAD_VERIFY_EV_CERT; |
| 535 request->set_load_flags(load_flags); | 474 request->set_load_flags(load_flags); |
| 536 request->set_context(context); | 475 request->set_context(context); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 558 uint64 upload_size = 0; | 497 uint64 upload_size = 0; |
| 559 if (request_data.upload_data) { | 498 if (request_data.upload_data) { |
| 560 request->set_upload(request_data.upload_data); | 499 request->set_upload(request_data.upload_data); |
| 561 upload_size = request_data.upload_data->GetContentLength(); | 500 upload_size = request_data.upload_data->GetContentLength(); |
| 562 } | 501 } |
| 563 | 502 |
| 564 // Install a CrossSiteResourceHandler if this request is coming from a | 503 // Install a CrossSiteResourceHandler if this request is coming from a |
| 565 // RenderViewHost with a pending cross-site request. We only check this for | 504 // RenderViewHost with a pending cross-site request. We only check this for |
| 566 // MAIN_FRAME requests. Unblock requests only come from a blocked page, do | 505 // MAIN_FRAME requests. Unblock requests only come from a blocked page, do |
| 567 // not count as cross-site, otherwise it gets blocked indefinitely. | 506 // not count as cross-site, otherwise it gets blocked indefinitely. |
| 568 if (request_data.url.scheme() != chrome::kUnblockScheme && | 507 if (request_data.resource_type == ResourceType::MAIN_FRAME && |
| 569 request_data.resource_type == ResourceType::MAIN_FRAME && | |
| 570 process_type == ChildProcessInfo::RENDER_PROCESS && | 508 process_type == ChildProcessInfo::RENDER_PROCESS && |
| 571 Singleton<CrossSiteRequestManager>::get()-> | 509 Singleton<CrossSiteRequestManager>::get()-> |
| 572 HasPendingCrossSiteRequest(child_id, route_id)) { | 510 HasPendingCrossSiteRequest(child_id, route_id)) { |
| 573 // Wrap the event handler to be sure the current page's onunload handler | 511 // Wrap the event handler to be sure the current page's onunload handler |
| 574 // has a chance to run before we render the new page. | 512 // has a chance to run before we render the new page. |
| 575 handler = new CrossSiteResourceHandler(handler, | 513 handler = new CrossSiteResourceHandler(handler, |
| 576 child_id, | 514 child_id, |
| 577 route_id, | 515 route_id, |
| 578 this); | 516 this); |
| 579 } | 517 } |
| 580 | 518 |
| 581 if (safe_browsing_->enabled() && | 519 if (safe_browsing_->enabled() && |
| 582 safe_browsing_->CanCheckUrl(gurl)) { | 520 safe_browsing_->CanCheckUrl(request_data.url)) { |
| 583 handler = new SafeBrowsingResourceHandler(handler, | 521 handler = new SafeBrowsingResourceHandler(handler, |
| 584 child_id, | 522 child_id, |
| 585 route_id, | 523 route_id, |
| 586 gurl, | 524 request_data.url, |
| 587 request_data.resource_type, | 525 request_data.resource_type, |
| 588 safe_browsing_, | 526 safe_browsing_, |
| 589 this, | 527 this, |
| 590 receiver_); | 528 receiver_); |
| 591 } | 529 } |
| 592 | 530 |
| 593 // Insert a buffered event handler before the actual one. | 531 // Insert a buffered event handler before the actual one. |
| 594 handler = new BufferedResourceHandler(handler, this, request); | 532 handler = new BufferedResourceHandler(handler, this, request); |
| 595 | 533 |
| 596 // Make extra info and read footer (contains request ID). | 534 // Make extra info and read footer (contains request ID). |
| (...skipping 14 matching lines...) Expand all Loading... |
| 611 request_data.host_render_view_id); | 549 request_data.host_render_view_id); |
| 612 SetRequestInfo(request, extra_info); // Request takes ownership. | 550 SetRequestInfo(request, extra_info); // Request takes ownership. |
| 613 chrome_browser_net::SetOriginProcessUniqueIDForRequest( | 551 chrome_browser_net::SetOriginProcessUniqueIDForRequest( |
| 614 request_data.origin_child_id, request); | 552 request_data.origin_child_id, request); |
| 615 | 553 |
| 616 // Have the appcache associate its extra info with the request. | 554 // Have the appcache associate its extra info with the request. |
| 617 appcache::AppCacheInterceptor::SetExtraRequestInfo( | 555 appcache::AppCacheInterceptor::SetExtraRequestInfo( |
| 618 request, context ? context->appcache_service() : NULL, child_id, | 556 request, context ? context->appcache_service() : NULL, child_id, |
| 619 request_data.appcache_host_id, request_data.resource_type); | 557 request_data.appcache_host_id, request_data.resource_type); |
| 620 | 558 |
| 559 // Associate Privacy Blacklist information with the request. |
| 560 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 561 switches::kEnablePrivacyBlacklists)) { |
| 562 request->SetUserData(&BlacklistRequestInfo::kURLRequestDataKey, |
| 563 new BlacklistRequestInfo(request_data.url, request_data.resource_type, |
| 564 context ? context->GetBlacklistManager() : NULL)); |
| 565 } |
| 566 |
| 621 BeginRequestInternal(request); | 567 BeginRequestInternal(request); |
| 622 } | 568 } |
| 623 | 569 |
| 624 void ResourceDispatcherHost::OnDataReceivedACK(int request_id) { | 570 void ResourceDispatcherHost::OnDataReceivedACK(int request_id) { |
| 625 DataReceivedACK(receiver_->id(), request_id); | 571 DataReceivedACK(receiver_->id(), request_id); |
| 626 } | 572 } |
| 627 | 573 |
| 628 void ResourceDispatcherHost::DataReceivedACK(int child_id, | 574 void ResourceDispatcherHost::DataReceivedACK(int child_id, |
| 629 int request_id) { | 575 int request_id) { |
| 630 PendingRequestList::iterator i = pending_requests_.find( | 576 PendingRequestList::iterator i = pending_requests_.find( |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 OnResponseCompleted(request); | 1086 OnResponseCompleted(request); |
| 1141 } | 1087 } |
| 1142 } | 1088 } |
| 1143 | 1089 |
| 1144 bool ResourceDispatcherHost::CompleteResponseStarted(URLRequest* request) { | 1090 bool ResourceDispatcherHost::CompleteResponseStarted(URLRequest* request) { |
| 1145 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); | 1091 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
| 1146 | 1092 |
| 1147 scoped_refptr<ResourceResponse> response = new ResourceResponse; | 1093 scoped_refptr<ResourceResponse> response = new ResourceResponse; |
| 1148 PopulateResourceResponse(request, info->filter_policy(), response); | 1094 PopulateResourceResponse(request, info->filter_policy(), response); |
| 1149 | 1095 |
| 1150 const URLRequest::UserData* d = | 1096 BlacklistRequestInfo* request_info = |
| 1151 request->GetUserData(&Blacklist::kRequestDataKey); | 1097 BlacklistRequestInfo::FromURLRequest(request); |
| 1152 if (d) { | 1098 if (request_info) { |
| 1153 const Blacklist::Match* match = static_cast<const Blacklist::Match*>(d); | 1099 const BlacklistManager* blacklist_manager = |
| 1154 if (match->attributes() & Blacklist::kBlockByType) { | 1100 request_info->GetBlacklistManager(); |
| 1101 const Blacklist* blacklist = blacklist_manager->GetCompiledBlacklist(); |
| 1102 scoped_ptr<Blacklist::Match> match(blacklist->findMatch(request->url())); |
| 1103 if (match.get() && match->attributes() & Blacklist::kBlockByType) { |
| 1155 if (match->MatchType(response->response_head.mime_type)) | 1104 if (match->MatchType(response->response_head.mime_type)) |
| 1156 return false; // TODO(idanan): Generate a replacement response. | 1105 return false; // TODO(idanan): Generate a replacement response. |
| 1157 } | 1106 } |
| 1158 } | 1107 } |
| 1159 | 1108 |
| 1160 if (request->ssl_info().cert) { | 1109 if (request->ssl_info().cert) { |
| 1161 int cert_id = | 1110 int cert_id = |
| 1162 CertStore::GetSharedInstance()->StoreCert(request->ssl_info().cert, | 1111 CertStore::GetSharedInstance()->StoreCert(request->ssl_info().cert, |
| 1163 info->child_id()); | 1112 info->child_id()); |
| 1164 response->response_head.security_info = | 1113 response->response_head.security_info = |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1822 case ViewHostMsg_UploadProgress_ACK::ID: | 1771 case ViewHostMsg_UploadProgress_ACK::ID: |
| 1823 case ViewHostMsg_SyncLoad::ID: | 1772 case ViewHostMsg_SyncLoad::ID: |
| 1824 return true; | 1773 return true; |
| 1825 | 1774 |
| 1826 default: | 1775 default: |
| 1827 break; | 1776 break; |
| 1828 } | 1777 } |
| 1829 | 1778 |
| 1830 return false; | 1779 return false; |
| 1831 } | 1780 } |
| OLD | NEW |