OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading |
6 | 6 |
7 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
8 | 8 |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 | 10 |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
288 | 288 |
289 // Consults the RendererSecurity policy to determine whether the | 289 // Consults the RendererSecurity policy to determine whether the |
290 // ResourceDispatcherHostImpl should service this request. A request might be | 290 // ResourceDispatcherHostImpl should service this request. A request might be |
291 // disallowed if the renderer is not authorized to retrieve the request URL or | 291 // disallowed if the renderer is not authorized to retrieve the request URL or |
292 // if the renderer is attempting to upload an unauthorized file. | 292 // if the renderer is attempting to upload an unauthorized file. |
293 bool ShouldServiceRequest(int process_type, | 293 bool ShouldServiceRequest(int process_type, |
294 int child_id, | 294 int child_id, |
295 const ResourceRequest& request_data, | 295 const ResourceRequest& request_data, |
296 const net::HttpRequestHeaders& headers, | 296 const net::HttpRequestHeaders& headers, |
297 ResourceMessageFilter* filter, | 297 ResourceMessageFilter* filter, |
298 ResourceContext* resource_context) { | 298 ResourceContext* resource_context, |
299 ResourceDispatcherHostImpl* host) { | |
299 ChildProcessSecurityPolicyImpl* policy = | 300 ChildProcessSecurityPolicyImpl* policy = |
300 ChildProcessSecurityPolicyImpl::GetInstance(); | 301 ChildProcessSecurityPolicyImpl::GetInstance(); |
301 | 302 |
302 // Check if the renderer is permitted to request the requested URL. | 303 // Check if the renderer is permitted to request the requested URL. |
303 if (!policy->CanRequestURL(child_id, request_data.url)) { | 304 if (!policy->CanRequestURL(child_id, request_data.url)) { |
304 VLOG(1) << "Denied unauthorized request for " | 305 VLOG(1) << "Denied unauthorized request for " |
305 << request_data.url.possibly_invalid_spec(); | 306 << request_data.url.possibly_invalid_spec(); |
306 return false; | 307 return false; |
307 } | 308 } |
308 | 309 |
309 // Check if the renderer is using an illegal Origin header. If so, kill it. | 310 // Check if the renderer is using an illegal Origin header. If so, kill it. |
310 std::string origin_string; | 311 std::string origin_string; |
311 bool has_origin = headers.GetHeader("Origin", &origin_string) && | 312 bool has_origin = headers.GetHeader("Origin", &origin_string) && |
312 origin_string != "null"; | 313 origin_string != "null"; |
313 if (has_origin) { | 314 if (has_origin) { |
314 GURL origin(origin_string); | 315 GURL origin(origin_string); |
315 if (!policy->CanCommitURL(child_id, origin) || | 316 if (!policy->CanCommitURL(child_id, origin) || |
316 GetContentClient()->browser()->IsIllegalOrigin(resource_context, | 317 host->IsIllegalOrigin(resource_context, origin, child_id)) { |
317 child_id, origin)) { | |
318 VLOG(1) << "Killed renderer for illegal origin: " << origin_string; | 318 VLOG(1) << "Killed renderer for illegal origin: " << origin_string; |
319 bad_message::ReceivedBadMessage(filter, bad_message::RDH_ILLEGAL_ORIGIN); | 319 bad_message::ReceivedBadMessage(filter, bad_message::RDH_ILLEGAL_ORIGIN); |
320 return false; | 320 return false; |
321 } | 321 } |
322 } | 322 } |
323 | 323 |
324 // Check if the renderer is permitted to upload the requested files. | 324 // Check if the renderer is permitted to upload the requested files. |
325 if (request_data.request_body.get()) { | 325 if (request_data.request_body.get()) { |
326 const std::vector<ResourceRequestBodyImpl::Element>* uploads = | 326 const std::vector<ResourceRequestBodyImpl::Element>* uploads = |
327 request_data.request_body->elements(); | 327 request_data.request_body->elements(); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 if (pending_frame_host) | 486 if (pending_frame_host) |
487 routing_ids->insert(pending_frame_host->GetGlobalFrameRoutingId()); | 487 routing_ids->insert(pending_frame_host->GetGlobalFrameRoutingId()); |
488 } | 488 } |
489 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 489 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
490 base::Bind(&NotifyForRouteSetOnIO, frame_callback, | 490 base::Bind(&NotifyForRouteSetOnIO, frame_callback, |
491 base::Passed(std::move(routing_ids)))); | 491 base::Passed(std::move(routing_ids)))); |
492 } | 492 } |
493 | 493 |
494 } // namespace | 494 } // namespace |
495 | 495 |
496 ResourceDispatcherHostImpl::OriginAccessInfo::OriginAccessInfo() { | |
497 } | |
498 | |
499 ResourceDispatcherHostImpl::OriginAccessInfo::~OriginAccessInfo() { | |
500 } | |
501 | |
502 ResourceDispatcherHostImpl::OriginAccessInfo::OriginAccessInfo( | |
503 const OriginAccessInfo& other) { | |
504 } | |
505 | |
496 // static | 506 // static |
497 ResourceDispatcherHost* ResourceDispatcherHost::Get() { | 507 ResourceDispatcherHost* ResourceDispatcherHost::Get() { |
498 return g_resource_dispatcher_host; | 508 return g_resource_dispatcher_host; |
499 } | 509 } |
500 | 510 |
501 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() | 511 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() |
502 : save_file_manager_(new SaveFileManager()), | 512 : save_file_manager_(new SaveFileManager()), |
503 request_id_(-1), | 513 request_id_(-1), |
504 is_shutdown_(false), | 514 is_shutdown_(false), |
505 num_in_flight_requests_(0), | 515 num_in_flight_requests_(0), |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( | 754 void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( |
745 net::URLRequest* request) { | 755 net::URLRequest* request) { |
746 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | 756 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); |
747 if (info) { | 757 if (info) { |
748 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); | 758 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); |
749 if (loader) | 759 if (loader) |
750 loader->ClearLoginDelegate(); | 760 loader->ClearLoginDelegate(); |
751 } | 761 } |
752 } | 762 } |
753 | 763 |
764 void ResourceDispatcherHostImpl::AddSchemeForAccessCheck( | |
765 const std::string& scheme) { | |
766 origins_for_access_check_.insert(scheme); | |
767 } | |
768 | |
769 void ResourceDispatcherHostImpl::AddProcessForOrigin( | |
770 const ResourceContext* context, | |
771 const std::string& origin, | |
772 int process_id) { | |
773 GURL url(origin); | |
jam
2016/08/02 17:01:46
nit: in these three new methods, add a DCHECK_CURR
ananta
2016/08/02 22:28:28
Added the DCHECK for the following methods:
1. Reg
| |
774 // The following conditions need to apply before we can add the process to | |
775 // the list of allowed processes for an origin. | |
776 // 1. The URL has to be valid. | |
777 // 2. It has to have a valid host. | |
778 // 3. The scheme has to be registered in the list of schemes being access | |
779 // checked. | |
780 if (!url.is_valid() || !url.has_host() || | |
781 origins_for_access_check_.find(url.scheme()) == | |
782 origins_for_access_check_.end()) { | |
783 NOTREACHED() << "Invalid URL or unregistered scheme."; | |
784 return; | |
785 } | |
786 | |
787 OriginAccessInfoMap* origin_access_info_map = | |
788 GetOriginAccessMapForResourceContext(context); | |
789 DCHECK(origin_access_info_map); | |
790 | |
791 OriginAccessInfoMap::iterator index = origin_access_info_map->find( | |
792 url.host()); | |
793 // If the host is not found in the map, then don't add the owner. | |
794 if (index == origin_access_info_map->end()) | |
795 return; | |
796 | |
797 OriginAccessInfo& access_info = index->second; | |
798 // The process should not be there in the list. | |
799 DCHECK(access_info.allowed_processes.find(process_id) == | |
800 access_info.allowed_processes.end()); | |
801 access_info.allowed_processes.insert(process_id); | |
802 } | |
803 | |
804 void ResourceDispatcherHostImpl::RemoveProcessForOrigin( | |
805 const ResourceContext* context, | |
806 const std::string& origin, | |
807 int process_id) { | |
808 GURL url(origin); | |
809 // The scheme has to be registered in the list of schemes being access | |
810 // checked. | |
811 if (origins_for_access_check_.find(url.scheme()) == | |
812 origins_for_access_check_.end()) { | |
813 DCHECK(false); | |
814 return; | |
815 } | |
816 | |
817 OriginAccessInfoMap* origin_access_info_map = | |
818 GetOriginAccessMapForResourceContext(context); | |
819 DCHECK(origin_access_info_map); | |
820 | |
821 OriginAccessInfoMap::iterator index = origin_access_info_map->find( | |
822 url.host()); | |
823 // If the host is not found in the map, then don't remove the owner. | |
824 if (index == origin_access_info_map->end()) | |
825 return; | |
826 | |
827 OriginAccessInfo& access_info = index->second; | |
828 | |
829 std::set<int>::iterator process_index = | |
830 access_info.allowed_processes.find(process_id); | |
831 // The process has to be there in the list. | |
832 DCHECK(process_index != access_info.allowed_processes.end()); | |
833 access_info.allowed_processes.erase(process_index); | |
834 if (access_info.allowed_processes.empty()) | |
835 origin_access_info_map->erase(index); | |
836 } | |
837 | |
754 void ResourceDispatcherHostImpl::Shutdown() { | 838 void ResourceDispatcherHostImpl::Shutdown() { |
755 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 839 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
756 BrowserThread::PostTask(BrowserThread::IO, | 840 BrowserThread::PostTask(BrowserThread::IO, |
757 FROM_HERE, | 841 FROM_HERE, |
758 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, | 842 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, |
759 base::Unretained(this))); | 843 base::Unretained(this))); |
760 } | 844 } |
761 | 845 |
762 std::unique_ptr<ResourceHandler> | 846 std::unique_ptr<ResourceHandler> |
763 ResourceDispatcherHostImpl::CreateResourceHandlerForDownload( | 847 ResourceDispatcherHostImpl::CreateResourceHandlerForDownload( |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1354 filter_->GetContexts(request_data.resource_type, &resource_context, | 1438 filter_->GetContexts(request_data.resource_type, &resource_context, |
1355 &request_context); | 1439 &request_context); |
1356 | 1440 |
1357 // Parse the headers before calling ShouldServiceRequest, so that they are | 1441 // Parse the headers before calling ShouldServiceRequest, so that they are |
1358 // available to be validated. | 1442 // available to be validated. |
1359 net::HttpRequestHeaders headers; | 1443 net::HttpRequestHeaders headers; |
1360 headers.AddHeadersFromString(request_data.headers); | 1444 headers.AddHeadersFromString(request_data.headers); |
1361 | 1445 |
1362 if (is_shutdown_ || | 1446 if (is_shutdown_ || |
1363 !ShouldServiceRequest(process_type, child_id, request_data, headers, | 1447 !ShouldServiceRequest(process_type, child_id, request_data, headers, |
1364 filter_, resource_context)) { | 1448 filter_, resource_context, this)) { |
1365 AbortRequestBeforeItStarts(filter_, sync_result, request_id); | 1449 AbortRequestBeforeItStarts(filter_, sync_result, request_id); |
1366 return; | 1450 return; |
1367 } | 1451 } |
1368 | 1452 |
1369 // Allow the observer to block/handle the request. | 1453 // Allow the observer to block/handle the request. |
1370 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, | 1454 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, |
1371 request_data.url, | 1455 request_data.url, |
1372 request_data.resource_type, | 1456 request_data.resource_type, |
1373 resource_context)) { | 1457 resource_context)) { |
1374 AbortRequestBeforeItStarts(filter_, sync_result, request_id); | 1458 AbortRequestBeforeItStarts(filter_, sync_result, request_id); |
(...skipping 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2600 DCHECK(deserialized); | 2684 DCHECK(deserialized); |
2601 ssl.cert_id = GetCertStore()->StoreCert(ssl_info.cert.get(), child_id); | 2685 ssl.cert_id = GetCertStore()->StoreCert(ssl_info.cert.get(), child_id); |
2602 response->head.security_info = SerializeSecurityInfo(ssl); | 2686 response->head.security_info = SerializeSecurityInfo(ssl); |
2603 } | 2687 } |
2604 | 2688 |
2605 CertStore* ResourceDispatcherHostImpl::GetCertStore() { | 2689 CertStore* ResourceDispatcherHostImpl::GetCertStore() { |
2606 return cert_store_for_testing_ ? cert_store_for_testing_ | 2690 return cert_store_for_testing_ ? cert_store_for_testing_ |
2607 : CertStore::GetInstance(); | 2691 : CertStore::GetInstance(); |
2608 } | 2692 } |
2609 | 2693 |
2694 ResourceDispatcherHostImpl::OriginAccessInfoMap* | |
2695 ResourceDispatcherHostImpl::GetOriginAccessMapForResourceContext( | |
2696 const ResourceContext* context) { | |
2697 ResourceContextOriginMap::iterator context_index = | |
2698 context_origin_access_info_map_.find(context); | |
2699 if (context_index != context_origin_access_info_map_.end()) | |
2700 return context_index->second.get(); | |
2701 | |
2702 context_origin_access_info_map_[context].reset(new OriginAccessInfoMap); | |
2703 return context_origin_access_info_map_[context].get(); | |
2704 } | |
2705 | |
2706 bool ResourceDispatcherHostImpl::IsIllegalOrigin(ResourceContext* context, | |
2707 const GURL& origin, | |
2708 int child_process_id) { | |
2709 if (origins_for_access_check_.find(origin.scheme()) == | |
2710 origins_for_access_check_.end()) { | |
2711 return false; | |
2712 } | |
2713 | |
2714 OriginAccessInfoMap* origin_access_info_map = | |
2715 GetOriginAccessMapForResourceContext( | |
2716 const_cast<const ResourceContext*>(context)); | |
2717 DCHECK(origin_access_info_map); | |
2718 | |
2719 OriginAccessInfoMap::iterator index = | |
2720 origin_access_info_map->find(origin.host()); | |
2721 if (index == origin_access_info_map->end()) | |
2722 return false; | |
2723 | |
2724 OriginAccessInfo& access_info = index->second; | |
2725 // Processes in the list for this origin are allowed. | |
2726 if (access_info.allowed_processes.find(child_process_id) != | |
2727 access_info.allowed_processes.end()) { | |
2728 return false; | |
2729 } | |
2730 // The origin being accessed is not allowed for the |child_process_id|. | |
2731 return true; | |
2732 } | |
2733 | |
2610 } // namespace content | 2734 } // namespace content |
OLD | NEW |