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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
499 LoaderIOThreadNotifier::~LoaderIOThreadNotifier() {} | 499 LoaderIOThreadNotifier::~LoaderIOThreadNotifier() {} |
500 | 500 |
501 void LoaderIOThreadNotifier::RenderFrameDeleted( | 501 void LoaderIOThreadNotifier::RenderFrameDeleted( |
502 RenderFrameHost* render_frame_host) { | 502 RenderFrameHost* render_frame_host) { |
503 NotifyForRouteFromUI( | 503 NotifyForRouteFromUI( |
504 static_cast<RenderFrameHostImpl*>(render_frame_host) | 504 static_cast<RenderFrameHostImpl*>(render_frame_host) |
505 ->GetGlobalFrameRoutingId(), | 505 ->GetGlobalFrameRoutingId(), |
506 base::Bind(&ResourceDispatcherHostImpl::OnRenderFrameDeleted)); | 506 base::Bind(&ResourceDispatcherHostImpl::OnRenderFrameDeleted)); |
507 } | 507 } |
508 | 508 |
509 // The ctors for the OriginAccessInfo structure have been defined here to fix | |
510 // compile errors with clang. Reason being presence of members with complex | |
511 // ctors like STL set. | |
jam
2016/08/01 20:06:01
nit: no need for this comment (i.e. we don't do it
ananta
2016/08/02 00:40:49
Done.
| |
512 ResourceDispatcherHostImpl::OriginAccessInfo::OriginAccessInfo() { | |
513 } | |
514 | |
515 ResourceDispatcherHostImpl::OriginAccessInfo::~OriginAccessInfo() { | |
516 } | |
517 | |
518 ResourceDispatcherHostImpl::OriginAccessInfo::OriginAccessInfo( | |
519 const OriginAccessInfo& other) { | |
520 } | |
521 | |
509 // static | 522 // static |
510 ResourceDispatcherHost* ResourceDispatcherHost::Get() { | 523 ResourceDispatcherHost* ResourceDispatcherHost::Get() { |
511 return g_resource_dispatcher_host; | 524 return g_resource_dispatcher_host; |
512 } | 525 } |
513 | 526 |
514 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() | 527 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() |
515 : save_file_manager_(new SaveFileManager()), | 528 : save_file_manager_(new SaveFileManager()), |
516 request_id_(-1), | 529 request_id_(-1), |
517 is_shutdown_(false), | 530 is_shutdown_(false), |
518 num_in_flight_requests_(0), | 531 num_in_flight_requests_(0), |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
552 if (!IsBrowserSideNavigationEnabled() && | 565 if (!IsBrowserSideNavigationEnabled() && |
553 base::FeatureList::IsEnabled(features::kStaleWhileRevalidate)) { | 566 base::FeatureList::IsEnabled(features::kStaleWhileRevalidate)) { |
554 async_revalidation_manager_.reset(new AsyncRevalidationManager); | 567 async_revalidation_manager_.reset(new AsyncRevalidationManager); |
555 } | 568 } |
556 } | 569 } |
557 | 570 |
558 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { | 571 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { |
559 DCHECK(outstanding_requests_stats_map_.empty()); | 572 DCHECK(outstanding_requests_stats_map_.empty()); |
560 DCHECK(g_resource_dispatcher_host); | 573 DCHECK(g_resource_dispatcher_host); |
561 g_resource_dispatcher_host = NULL; | 574 g_resource_dispatcher_host = NULL; |
575 | |
576 // Delete the origin access info maps. | |
jam
2016/08/01 20:06:01
(wouldn't be needed if unique_ptr was used)
ananta
2016/08/02 00:40:49
Done.
| |
577 for (auto index : context_origin_access_info_map_) | |
578 delete index.second; | |
562 } | 579 } |
563 | 580 |
564 // static | 581 // static |
565 ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { | 582 ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { |
566 return g_resource_dispatcher_host; | 583 return g_resource_dispatcher_host; |
567 } | 584 } |
568 | 585 |
569 // static | 586 // static |
570 void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRouteFromUI( | 587 void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRouteFromUI( |
571 const GlobalFrameRoutingId& global_routing_id) { | 588 const GlobalFrameRoutingId& global_routing_id) { |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
757 void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( | 774 void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( |
758 net::URLRequest* request) { | 775 net::URLRequest* request) { |
759 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | 776 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); |
760 if (info) { | 777 if (info) { |
761 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); | 778 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); |
762 if (loader) | 779 if (loader) |
763 loader->ClearLoginDelegate(); | 780 loader->ClearLoginDelegate(); |
764 } | 781 } |
765 } | 782 } |
766 | 783 |
784 void ResourceDispatcherHostImpl::AddSchemeForAccessCheck( | |
785 const std::string& scheme) { | |
786 origins_for_access_check_.insert(scheme); | |
787 } | |
788 | |
789 void ResourceDispatcherHostImpl::AddOriginAccessInformation( | |
790 const ResourceContext* context, | |
791 const std::string& origin) { | |
792 GURL url(origin); | |
793 // The following conditions need to apply before we can add access | |
794 // information for an origin. | |
795 // 1. The URL has to be valid. | |
796 // 2. It has to have a valid host. | |
797 // 3. The scheme has to be registered in the list of schemes being access | |
798 // checked. | |
799 if (!url.is_valid() || !url.has_host() || | |
800 origins_for_access_check_.find(url.scheme()) == | |
801 origins_for_access_check_.end()) { | |
802 DCHECK(false); | |
jam
2016/08/01 20:06:01
nit: NOTREACHED() is preferred to DCHECK(false)
ananta
2016/08/02 00:40:49
Done.
| |
803 return; | |
804 } | |
805 | |
806 OriginAccessInfoMap* origin_access_info_map = | |
807 GetOriginAccessMapForResourceContext(context); | |
808 | |
809 OriginAccessInfo access_info; | |
810 (*origin_access_info_map)[url.host()] = access_info; | |
811 } | |
812 | |
813 void ResourceDispatcherHostImpl::RemoveOriginAccessInformation( | |
814 const ResourceContext* context, | |
815 const std::string& origin) { | |
816 GURL url(origin); | |
817 // The scheme has to be registered in the list of schemes being access | |
818 // checked. | |
819 if (origins_for_access_check_.find(url.scheme()) == | |
820 origins_for_access_check_.end()) { | |
821 DCHECK(false); | |
822 return; | |
823 } | |
824 | |
825 OriginAccessInfoMap* origin_access_info_map = | |
826 GetOriginAccessMapForResourceContext(context); | |
827 | |
828 OriginAccessInfoMap::iterator index = origin_access_info_map->find( | |
829 url.host()); | |
830 if (index != origin_access_info_map->end()) | |
831 origin_access_info_map->erase(index); | |
832 } | |
833 | |
834 void ResourceDispatcherHostImpl::AddOwnerForOrigin( | |
835 const ResourceContext* context, | |
836 const std::string& origin, | |
837 int owner_process_id) { | |
838 GURL url(origin); | |
839 // The scheme has to be registered in the list of schemes being access | |
840 // checked. | |
841 if (origins_for_access_check_.find(url.scheme()) == | |
842 origins_for_access_check_.end()) { | |
843 DCHECK(false); | |
844 return; | |
845 } | |
846 | |
847 OriginAccessInfoMap* origin_access_info_map = | |
848 GetOriginAccessMapForResourceContext(context); | |
849 | |
850 OriginAccessInfoMap::iterator index = origin_access_info_map->find( | |
851 url.host()); | |
852 // If the host is not found in the map, then don't add the owner. | |
853 if (index == origin_access_info_map->end()) | |
854 return; | |
855 | |
856 OriginAccessInfo& access_info = index->second; | |
857 // The owner should not be there in the list. | |
858 DCHECK(access_info.origin_owner_processes.find(owner_process_id) == | |
859 access_info.origin_owner_processes.end()); | |
860 access_info.origin_owner_processes.insert(owner_process_id); | |
861 } | |
862 | |
863 void ResourceDispatcherHostImpl::RemoveOwnerForOrigin( | |
864 const ResourceContext* context, | |
865 const std::string& origin, | |
866 int owner_process_id) { | |
867 GURL url(origin); | |
868 // The scheme has to be registered in the list of schemes being access | |
869 // checked. | |
870 if (origins_for_access_check_.find(url.scheme()) == | |
871 origins_for_access_check_.end()) { | |
872 DCHECK(false); | |
873 return; | |
874 } | |
875 | |
876 OriginAccessInfoMap* origin_access_info_map = | |
877 GetOriginAccessMapForResourceContext(context); | |
878 | |
879 OriginAccessInfoMap::iterator index = origin_access_info_map->find( | |
880 url.host()); | |
881 // If the host is not found in the map, then don't remove the owner. | |
882 if (index == origin_access_info_map->end()) | |
883 return; | |
884 | |
885 OriginAccessInfo& access_info = index->second; | |
886 | |
887 std::set<int>::iterator process_index = | |
888 access_info.origin_owner_processes.find(owner_process_id); | |
889 // The owner has to be there in the list. | |
890 DCHECK(access_info.origin_owner_processes.find(owner_process_id) != | |
891 access_info.origin_owner_processes.end()); | |
892 access_info.origin_owner_processes.erase(process_index); | |
893 } | |
894 | |
895 void ResourceDispatcherHostImpl::AddGuestForOrigin( | |
896 const ResourceContext* context, | |
897 const std::string& origin, | |
898 int guest_process_id) { | |
899 GURL url(origin); | |
900 // The scheme has to be registered in the list of schemes being access | |
901 // checked. | |
902 if (origins_for_access_check_.find(url.scheme()) == | |
903 origins_for_access_check_.end()) { | |
904 DCHECK(false); | |
905 return; | |
906 } | |
907 | |
908 OriginAccessInfoMap* origin_access_info_map = | |
909 GetOriginAccessMapForResourceContext(context); | |
910 | |
911 OriginAccessInfoMap::iterator index = origin_access_info_map->find( | |
912 url.host()); | |
913 // If the host is not found in the map, then don't add the guest. | |
914 if (index == origin_access_info_map->end()) | |
915 return; | |
916 | |
917 OriginAccessInfo& access_info = index->second; | |
918 // The guest should not be there in the list. | |
919 DCHECK(access_info.origin_guest_processes.find(guest_process_id) == | |
920 access_info.origin_guest_processes.end()); | |
921 access_info.origin_guest_processes.insert(guest_process_id); | |
922 } | |
923 | |
924 void ResourceDispatcherHostImpl::RemoveGuestForOrigin( | |
925 const ResourceContext* context, | |
926 const std::string& origin, | |
927 int guest_process_id) { | |
928 GURL url(origin); | |
929 // The scheme has to be registered in the list of schemes being access | |
930 // checked. | |
931 if (origins_for_access_check_.find(url.scheme()) == | |
932 origins_for_access_check_.end()) { | |
933 DCHECK(false); | |
934 return; | |
935 } | |
936 | |
937 OriginAccessInfoMap* origin_access_info_map = | |
938 GetOriginAccessMapForResourceContext(context); | |
939 | |
940 OriginAccessInfoMap::iterator index = origin_access_info_map->find( | |
941 url.host()); | |
942 // If the host is not found in the map, then don't remove the guest. | |
943 if (index == origin_access_info_map->end()) | |
944 return; | |
945 | |
946 OriginAccessInfo& access_info = index->second; | |
947 | |
948 std::set<int>::iterator process_index = | |
949 access_info.origin_guest_processes.find(guest_process_id); | |
950 // The guest has to be there in the list. | |
951 DCHECK(access_info.origin_guest_processes.find(guest_process_id) != | |
952 access_info.origin_guest_processes.end()); | |
953 access_info.origin_guest_processes.erase(process_index); | |
954 } | |
955 | |
767 void ResourceDispatcherHostImpl::Shutdown() { | 956 void ResourceDispatcherHostImpl::Shutdown() { |
768 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 957 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
769 BrowserThread::PostTask(BrowserThread::IO, | 958 BrowserThread::PostTask(BrowserThread::IO, |
770 FROM_HERE, | 959 FROM_HERE, |
771 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, | 960 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, |
772 base::Unretained(this))); | 961 base::Unretained(this))); |
773 } | 962 } |
774 | 963 |
775 std::unique_ptr<ResourceHandler> | 964 std::unique_ptr<ResourceHandler> |
776 ResourceDispatcherHostImpl::CreateResourceHandlerForDownload( | 965 ResourceDispatcherHostImpl::CreateResourceHandlerForDownload( |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1367 filter_->GetContexts(request_data.resource_type, &resource_context, | 1556 filter_->GetContexts(request_data.resource_type, &resource_context, |
1368 &request_context); | 1557 &request_context); |
1369 | 1558 |
1370 // Parse the headers before calling ShouldServiceRequest, so that they are | 1559 // Parse the headers before calling ShouldServiceRequest, so that they are |
1371 // available to be validated. | 1560 // available to be validated. |
1372 net::HttpRequestHeaders headers; | 1561 net::HttpRequestHeaders headers; |
1373 headers.AddHeadersFromString(request_data.headers); | 1562 headers.AddHeadersFromString(request_data.headers); |
1374 | 1563 |
1375 if (is_shutdown_ || | 1564 if (is_shutdown_ || |
1376 !ShouldServiceRequest(process_type, child_id, request_data, headers, | 1565 !ShouldServiceRequest(process_type, child_id, request_data, headers, |
1377 filter_, resource_context)) { | 1566 filter_, resource_context, this)) { |
1378 AbortRequestBeforeItStarts(filter_, sync_result, request_id); | 1567 AbortRequestBeforeItStarts(filter_, sync_result, request_id); |
1379 return; | 1568 return; |
1380 } | 1569 } |
1381 | 1570 |
1382 // Allow the observer to block/handle the request. | 1571 // Allow the observer to block/handle the request. |
1383 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, | 1572 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, |
1384 request_data.url, | 1573 request_data.url, |
1385 request_data.resource_type, | 1574 request_data.resource_type, |
1386 resource_context)) { | 1575 resource_context)) { |
1387 AbortRequestBeforeItStarts(filter_, sync_result, request_id); | 1576 AbortRequestBeforeItStarts(filter_, sync_result, request_id); |
(...skipping 1207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2595 DCHECK(deserialized); | 2784 DCHECK(deserialized); |
2596 ssl.cert_id = GetCertStore()->StoreCert(ssl_info.cert.get(), child_id); | 2785 ssl.cert_id = GetCertStore()->StoreCert(ssl_info.cert.get(), child_id); |
2597 response->head.security_info = SerializeSecurityInfo(ssl); | 2786 response->head.security_info = SerializeSecurityInfo(ssl); |
2598 } | 2787 } |
2599 | 2788 |
2600 CertStore* ResourceDispatcherHostImpl::GetCertStore() { | 2789 CertStore* ResourceDispatcherHostImpl::GetCertStore() { |
2601 return cert_store_for_testing_ ? cert_store_for_testing_ | 2790 return cert_store_for_testing_ ? cert_store_for_testing_ |
2602 : CertStore::GetInstance(); | 2791 : CertStore::GetInstance(); |
2603 } | 2792 } |
2604 | 2793 |
2794 ResourceDispatcherHostImpl::OriginAccessInfoMap* | |
2795 ResourceDispatcherHostImpl::GetOriginAccessMapForResourceContext( | |
2796 const ResourceContext* context) { | |
2797 OriginAccessInfoMap* origin_access_map = | |
2798 context_origin_access_info_map_[context]; | |
2799 if (!origin_access_map) { | |
2800 origin_access_map = new OriginAccessInfoMap; | |
2801 context_origin_access_info_map_[context] = origin_access_map; | |
2802 } | |
2803 return origin_access_map; | |
2804 } | |
2805 | |
2806 bool ResourceDispatcherHostImpl::IsIllegalOrigin(ResourceContext* context, | |
2807 const GURL& origin, | |
2808 int child_process_id) { | |
2809 if (origins_for_access_check_.find(origin.scheme()) == | |
2810 origins_for_access_check_.end()) { | |
2811 return false; | |
2812 } | |
2813 OriginAccessInfoMap* origin_access_info_map = | |
2814 GetOriginAccessMapForResourceContext( | |
2815 const_cast<const ResourceContext*>(context)); | |
2816 DCHECK(origin_access_info_map); | |
2817 | |
2818 OriginAccessInfoMap::iterator index = | |
2819 origin_access_info_map->find(origin.host()); | |
2820 if (index == origin_access_info_map->end()) | |
2821 return false; | |
2822 | |
2823 OriginAccessInfo& access_info = index->second; | |
2824 // Owner processes are granted access by default. | |
2825 if (access_info.origin_owner_processes.find(child_process_id) != | |
2826 access_info.origin_owner_processes.end()) { | |
2827 return false; | |
2828 } | |
2829 // Guest processes are allowed access. | |
2830 if (access_info.origin_guest_processes.find(child_process_id) != | |
2831 access_info.origin_guest_processes.end()) { | |
2832 return false; | |
2833 } | |
2834 // The origin being accessed is not allowed for the |child_process_id|. | |
2835 return true; | |
2836 } | |
2837 | |
2605 } // namespace content | 2838 } // namespace content |
OLD | NEW |