| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 | 330 |
| 331 LocalFrame* frame = document_loader_->GetFrame(); | 331 LocalFrame* frame = document_loader_->GetFrame(); |
| 332 DCHECK(frame); | 332 DCHECK(frame); |
| 333 return frame; | 333 return frame; |
| 334 } | 334 } |
| 335 | 335 |
| 336 LocalFrameClient* FrameFetchContext::GetLocalFrameClient() const { | 336 LocalFrameClient* FrameFetchContext::GetLocalFrameClient() const { |
| 337 return GetFrame()->Client(); | 337 return GetFrame()->Client(); |
| 338 } | 338 } |
| 339 | 339 |
| 340 ContentSettingsClient* FrameFetchContext::GetContentSettingsClient() const { | |
| 341 return GetFrame()->GetContentSettingsClient(); | |
| 342 } | |
| 343 | |
| 344 void FrameFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request, | 340 void FrameFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request, |
| 345 FetchResourceType type) { | 341 FetchResourceType type) { |
| 346 BaseFetchContext::AddAdditionalRequestHeaders(request, type); | 342 BaseFetchContext::AddAdditionalRequestHeaders(request, type); |
| 347 | 343 |
| 348 // The remaining modifications are only necessary for HTTP and HTTPS. | 344 // The remaining modifications are only necessary for HTTP and HTTPS. |
| 349 if (!request.Url().IsEmpty() && !request.Url().ProtocolIsInHTTPFamily()) | 345 if (!request.Url().IsEmpty() && !request.Url().ProtocolIsInHTTPFamily()) |
| 350 return; | 346 return; |
| 351 | 347 |
| 352 // Reload should reflect the current data saver setting. | 348 // Reload should reflect the current data saver setting. |
| 353 if (IsReloadLoadType(MasterDocumentLoader()->LoadType())) | 349 if (IsReloadLoadType(MasterDocumentLoader()->LoadType())) |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 if (!initiator_document || !initiator_document->domWindow()) | 626 if (!initiator_document || !initiator_document->domWindow()) |
| 631 return; | 627 return; |
| 632 DOMWindowPerformance::performance(*initiator_document->domWindow()) | 628 DOMWindowPerformance::performance(*initiator_document->domWindow()) |
| 633 ->AddResourceTiming(info); | 629 ->AddResourceTiming(info); |
| 634 } | 630 } |
| 635 | 631 |
| 636 bool FrameFetchContext::AllowImage(bool images_enabled, const KURL& url) const { | 632 bool FrameFetchContext::AllowImage(bool images_enabled, const KURL& url) const { |
| 637 return GetContentSettingsClient()->AllowImage(images_enabled, url); | 633 return GetContentSettingsClient()->AllowImage(images_enabled, url); |
| 638 } | 634 } |
| 639 | 635 |
| 640 ResourceRequestBlockedReason FrameFetchContext::CanRequest( | |
| 641 Resource::Type type, | |
| 642 const ResourceRequest& resource_request, | |
| 643 const KURL& url, | |
| 644 const ResourceLoaderOptions& options, | |
| 645 SecurityViolationReportingPolicy reporting_policy, | |
| 646 FetchParameters::OriginRestriction origin_restriction) const { | |
| 647 ResourceRequestBlockedReason blocked_reason = CanRequestInternal( | |
| 648 type, resource_request, url, options, reporting_policy, | |
| 649 origin_restriction, resource_request.GetRedirectStatus()); | |
| 650 if (blocked_reason != ResourceRequestBlockedReason::kNone && | |
| 651 reporting_policy == SecurityViolationReportingPolicy::kReport) { | |
| 652 probe::didBlockRequest(GetFrame(), resource_request, MasterDocumentLoader(), | |
| 653 options.initiator_info, blocked_reason); | |
| 654 } | |
| 655 return blocked_reason; | |
| 656 } | |
| 657 | |
| 658 ResourceRequestBlockedReason FrameFetchContext::CanFollowRedirect( | |
| 659 Resource::Type type, | |
| 660 const ResourceRequest& resource_request, | |
| 661 const KURL& url, | |
| 662 const ResourceLoaderOptions& options, | |
| 663 SecurityViolationReportingPolicy reporting_policy, | |
| 664 FetchParameters::OriginRestriction origin_restriction) const { | |
| 665 // CanRequestInternal checks enforced CSP, so check report-only here to ensure | |
| 666 // that violations are sent. | |
| 667 CheckCSPForRequest(resource_request, url, options, reporting_policy, | |
| 668 RedirectStatus::kFollowedRedirect, | |
| 669 ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly); | |
| 670 return CanRequest(type, resource_request, url, options, reporting_policy, | |
| 671 origin_restriction); | |
| 672 } | |
| 673 | |
| 674 ResourceRequestBlockedReason FrameFetchContext::AllowResponse( | |
| 675 Resource::Type type, | |
| 676 const ResourceRequest& resource_request, | |
| 677 const KURL& url, | |
| 678 const ResourceLoaderOptions& options) const { | |
| 679 // canRequestInternal only checks enforced policies: check report-only here | |
| 680 // to ensure violations are sent. | |
| 681 CheckCSPForRequest(resource_request, url, options, | |
| 682 SecurityViolationReportingPolicy::kReport, | |
| 683 RedirectStatus::kFollowedRedirect, | |
| 684 ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly); | |
| 685 ResourceRequestBlockedReason blocked_reason = | |
| 686 CanRequestInternal(type, resource_request, url, options, | |
| 687 SecurityViolationReportingPolicy::kReport, | |
| 688 FetchParameters::kUseDefaultOriginRestrictionForType, | |
| 689 RedirectStatus::kFollowedRedirect); | |
| 690 if (blocked_reason != ResourceRequestBlockedReason::kNone) { | |
| 691 probe::didBlockRequest(GetFrame(), resource_request, MasterDocumentLoader(), | |
| 692 options.initiator_info, blocked_reason); | |
| 693 } | |
| 694 return blocked_reason; | |
| 695 } | |
| 696 | |
| 697 ResourceRequestBlockedReason FrameFetchContext::CanRequestInternal( | |
| 698 Resource::Type type, | |
| 699 const ResourceRequest& resource_request, | |
| 700 const KURL& url, | |
| 701 const ResourceLoaderOptions& options, | |
| 702 SecurityViolationReportingPolicy reporting_policy, | |
| 703 FetchParameters::OriginRestriction origin_restriction, | |
| 704 ResourceRequest::RedirectStatus redirect_status) const { | |
| 705 bool should_block_request = false; | |
| 706 probe::shouldBlockRequest(GetFrame(), resource_request, | |
| 707 &should_block_request); | |
| 708 if (should_block_request) | |
| 709 return ResourceRequestBlockedReason::kInspector; | |
| 710 | |
| 711 SecurityOrigin* security_origin = options.security_origin.Get(); | |
| 712 if (!security_origin && execution_context_) | |
| 713 security_origin = execution_context_->GetSecurityOrigin(); | |
| 714 | |
| 715 if (origin_restriction != FetchParameters::kNoOriginRestriction && | |
| 716 security_origin && !security_origin->CanDisplay(url)) { | |
| 717 if (reporting_policy == SecurityViolationReportingPolicy::kReport) | |
| 718 FrameLoader::ReportLocalLoadFailed(GetFrame(), url.ElidedString()); | |
| 719 RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::requestResource URL was not " | |
| 720 "allowed by SecurityOrigin::canDisplay"; | |
| 721 return ResourceRequestBlockedReason::kOther; | |
| 722 } | |
| 723 | |
| 724 // Some types of resources can be loaded only from the same origin. Other | |
| 725 // types of resources, like Images, Scripts, and CSS, can be loaded from | |
| 726 // any URL. | |
| 727 switch (type) { | |
| 728 case Resource::kMainResource: | |
| 729 case Resource::kImage: | |
| 730 case Resource::kCSSStyleSheet: | |
| 731 case Resource::kScript: | |
| 732 case Resource::kFont: | |
| 733 case Resource::kRaw: | |
| 734 case Resource::kLinkPrefetch: | |
| 735 case Resource::kTextTrack: | |
| 736 case Resource::kImportResource: | |
| 737 case Resource::kMedia: | |
| 738 case Resource::kManifest: | |
| 739 case Resource::kMock: | |
| 740 // By default these types of resources can be loaded from any origin. | |
| 741 // FIXME: Are we sure about Resource::Font? | |
| 742 if (origin_restriction == FetchParameters::kRestrictToSameOrigin && | |
| 743 !security_origin->CanRequest(url)) { | |
| 744 PrintAccessDeniedMessage(url); | |
| 745 return ResourceRequestBlockedReason::kOrigin; | |
| 746 } | |
| 747 break; | |
| 748 case Resource::kXSLStyleSheet: | |
| 749 DCHECK(RuntimeEnabledFeatures::xsltEnabled()); | |
| 750 case Resource::kSVGDocument: | |
| 751 if (!security_origin->CanRequest(url)) { | |
| 752 PrintAccessDeniedMessage(url); | |
| 753 return ResourceRequestBlockedReason::kOrigin; | |
| 754 } | |
| 755 break; | |
| 756 } | |
| 757 | |
| 758 // We check the 'report-only' headers before upgrading the request (in | |
| 759 // populateResourceRequest). We check the enforced headers here to ensure we | |
| 760 // block things we ought to block. | |
| 761 if (CheckCSPForRequest( | |
| 762 resource_request, url, options, reporting_policy, redirect_status, | |
| 763 ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) == | |
| 764 ResourceRequestBlockedReason::CSP) { | |
| 765 return ResourceRequestBlockedReason::CSP; | |
| 766 } | |
| 767 | |
| 768 if (type == Resource::kScript || type == Resource::kImportResource) { | |
| 769 DCHECK(GetFrame()); | |
| 770 if (!GetContentSettingsClient()->AllowScriptFromSource( | |
| 771 !GetFrame()->GetSettings() || | |
| 772 GetFrame()->GetSettings()->GetScriptEnabled(), | |
| 773 url)) { | |
| 774 GetContentSettingsClient()->DidNotAllowScript(); | |
| 775 // TODO(estark): Use a different ResourceRequestBlockedReason here, since | |
| 776 // this check has nothing to do with CSP. https://crbug.com/600795 | |
| 777 return ResourceRequestBlockedReason::CSP; | |
| 778 } | |
| 779 } | |
| 780 | |
| 781 // SVG Images have unique security rules that prevent all subresource requests | |
| 782 // except for data urls. | |
| 783 if (type != Resource::kMainResource && | |
| 784 GetFrame()->GetChromeClient().IsSVGImageChromeClient() && | |
| 785 !url.ProtocolIsData()) | |
| 786 return ResourceRequestBlockedReason::kOrigin; | |
| 787 | |
| 788 // Measure the number of legacy URL schemes ('ftp://') and the number of | |
| 789 // embedded-credential ('http://user:password@...') resources embedded as | |
| 790 // subresources. | |
| 791 if (resource_request.GetFrameType() != WebURLRequest::kFrameTypeTopLevel) { | |
| 792 DCHECK(GetFrame()->GetDocument()); | |
| 793 if (SchemeRegistry::ShouldTreatURLSchemeAsLegacy(url.Protocol()) && | |
| 794 !SchemeRegistry::ShouldTreatURLSchemeAsLegacy( | |
| 795 GetFrame()->GetDocument()->GetSecurityOrigin()->Protocol())) { | |
| 796 Deprecation::CountDeprecation( | |
| 797 GetFrame()->GetDocument(), | |
| 798 UseCounter::kLegacyProtocolEmbeddedAsSubresource); | |
| 799 | |
| 800 // TODO(mkwst): Enabled by default in M59. Drop the runtime-enabled check | |
| 801 // in M60: https://www.chromestatus.com/feature/5709390967472128 | |
| 802 if (RuntimeEnabledFeatures::blockLegacySubresourcesEnabled()) | |
| 803 return ResourceRequestBlockedReason::kOrigin; | |
| 804 } | |
| 805 | |
| 806 if ((!url.User().IsEmpty() || !url.Pass().IsEmpty()) && | |
| 807 resource_request.GetRequestContext() != | |
| 808 WebURLRequest::kRequestContextXMLHttpRequest) { | |
| 809 Deprecation::CountDeprecation( | |
| 810 GetFrame()->GetDocument(), | |
| 811 UseCounter::kRequestedSubresourceWithEmbeddedCredentials); | |
| 812 // TODO(mkwst): Remove the runtime-enabled check in M59: | |
| 813 // https://www.chromestatus.com/feature/5669008342777856 | |
| 814 if (RuntimeEnabledFeatures::blockCredentialedSubresourcesEnabled()) | |
| 815 return ResourceRequestBlockedReason::kOrigin; | |
| 816 } | |
| 817 } | |
| 818 | |
| 819 // Check for mixed content. We do this second-to-last so that when folks block | |
| 820 // mixed content with a CSP policy, they don't get a warning. They'll still | |
| 821 // get a warning in the console about CSP blocking the load. | |
| 822 if (MixedContentChecker::ShouldBlockFetch(GetFrame(), resource_request, url, | |
| 823 reporting_policy)) | |
| 824 return ResourceRequestBlockedReason::kMixedContent; | |
| 825 | |
| 826 if (url.WhitespaceRemoved()) { | |
| 827 Deprecation::CountDeprecation( | |
| 828 GetFrame()->GetDocument(), | |
| 829 UseCounter::kCanRequestURLHTTPContainingNewline); | |
| 830 if (url.ProtocolIsInHTTPFamily()) { | |
| 831 if (RuntimeEnabledFeatures::restrictCanRequestURLCharacterSetEnabled()) | |
| 832 return ResourceRequestBlockedReason::kOther; | |
| 833 } else { | |
| 834 UseCounter::Count(GetFrame()->GetDocument(), | |
| 835 UseCounter::kCanRequestURLNonHTTPContainingNewline); | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 // Let the client have the final say into whether or not the load should | |
| 840 // proceed. | |
| 841 DocumentLoader* document_loader = MasterDocumentLoader(); | |
| 842 if (document_loader && document_loader->GetSubresourceFilter() && | |
| 843 type != Resource::kMainResource && type != Resource::kImportResource) { | |
| 844 if (!document_loader->GetSubresourceFilter()->AllowLoad( | |
| 845 url, resource_request.GetRequestContext(), reporting_policy)) { | |
| 846 return ResourceRequestBlockedReason::kSubresourceFilter; | |
| 847 } | |
| 848 } | |
| 849 | |
| 850 return ResourceRequestBlockedReason::kNone; | |
| 851 } | |
| 852 | |
| 853 ResourceRequestBlockedReason FrameFetchContext::CheckCSPForRequest( | |
| 854 const ResourceRequest& resource_request, | |
| 855 const KURL& url, | |
| 856 const ResourceLoaderOptions& options, | |
| 857 SecurityViolationReportingPolicy reporting_policy, | |
| 858 ResourceRequest::RedirectStatus redirect_status, | |
| 859 ContentSecurityPolicy::CheckHeaderType check_header_type) const { | |
| 860 if (GetFrame()->GetScriptController().ShouldBypassMainWorldCSP() || | |
| 861 options.content_security_policy_option == | |
| 862 kDoNotCheckContentSecurityPolicy) { | |
| 863 return ResourceRequestBlockedReason::kNone; | |
| 864 } | |
| 865 | |
| 866 if (execution_context_) { | |
| 867 DCHECK(execution_context_->GetContentSecurityPolicy()); | |
| 868 if (!execution_context_->GetContentSecurityPolicy()->AllowRequest( | |
| 869 resource_request.GetRequestContext(), url, | |
| 870 options.content_security_policy_nonce, options.integrity_metadata, | |
| 871 options.parser_disposition, redirect_status, reporting_policy, | |
| 872 check_header_type)) | |
| 873 return ResourceRequestBlockedReason::CSP; | |
| 874 } | |
| 875 return ResourceRequestBlockedReason::kNone; | |
| 876 } | |
| 877 | |
| 878 bool FrameFetchContext::IsControlledByServiceWorker() const { | 636 bool FrameFetchContext::IsControlledByServiceWorker() const { |
| 879 DCHECK(MasterDocumentLoader()); | 637 DCHECK(MasterDocumentLoader()); |
| 880 | 638 |
| 881 // Service workers are bypassed by suborigins (see | 639 // Service workers are bypassed by suborigins (see |
| 882 // https://w3c.github.io/webappsec-suborigins/). Since service worker | 640 // https://w3c.github.io/webappsec-suborigins/). Since service worker |
| 883 // controllers are assigned based on physical origin, without knowledge of | 641 // controllers are assigned based on physical origin, without knowledge of |
| 884 // whether the context is in a suborigin, it is necessary to explicitly bypass | 642 // whether the context is in a suborigin, it is necessary to explicitly bypass |
| 885 // service workers on a per-request basis. Additionally, it is necessary to | 643 // service workers on a per-request basis. Additionally, it is necessary to |
| 886 // explicitly return |false| here so that it is clear that the SW will be | 644 // explicitly return |false| here so that it is clear that the SW will be |
| 887 // bypassed. In particular, this is important for | 645 // bypassed. In particular, this is important for |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1075 !GetFrame()->IsMainFrame()) | 833 !GetFrame()->IsMainFrame()) |
| 1076 return kResourceLoadPriorityVeryLow; | 834 return kResourceLoadPriorityVeryLow; |
| 1077 | 835 |
| 1078 return priority; | 836 return priority; |
| 1079 } | 837 } |
| 1080 | 838 |
| 1081 RefPtr<WebTaskRunner> FrameFetchContext::LoadingTaskRunner() const { | 839 RefPtr<WebTaskRunner> FrameFetchContext::LoadingTaskRunner() const { |
| 1082 return GetFrame()->FrameScheduler()->LoadingTaskRunner(); | 840 return GetFrame()->FrameScheduler()->LoadingTaskRunner(); |
| 1083 } | 841 } |
| 1084 | 842 |
| 843 ContentSettingsClient* FrameFetchContext::GetContentSettingsClient() const { |
| 844 return GetFrame()->GetContentSettingsClient(); |
| 845 } |
| 846 |
| 847 Settings* FrameFetchContext::GetSettings() const { |
| 848 DCHECK(GetFrame()); |
| 849 return GetFrame()->GetSettings(); |
| 850 } |
| 851 |
| 852 SubresourceFilter* FrameFetchContext::GetSubresourceFilter() const { |
| 853 DocumentLoader* document_loader = MasterDocumentLoader(); |
| 854 return document_loader ? document_loader->GetSubresourceFilter() : nullptr; |
| 855 } |
| 856 |
| 857 SecurityContext* FrameFetchContext::GetMainResourceSecurityContext() const { |
| 858 DCHECK(GetFrame()->GetDocument()); |
| 859 return GetFrame()->GetDocument(); |
| 860 } |
| 861 |
| 862 bool FrameFetchContext::ShouldBlockRequestByInspector( |
| 863 const ResourceRequest& resource_request) const { |
| 864 bool should_block_request = false; |
| 865 probe::shouldBlockRequest(GetFrame(), resource_request, |
| 866 &should_block_request); |
| 867 return should_block_request; |
| 868 } |
| 869 |
| 870 void FrameFetchContext::DispatchDidBlockRequest( |
| 871 const ResourceRequest& resource_request, |
| 872 const FetchInitiatorInfo& fetch_initiator_info, |
| 873 ResourceRequestBlockedReason blocked_reason) const { |
| 874 probe::didBlockRequest(GetFrame(), resource_request, MasterDocumentLoader(), |
| 875 fetch_initiator_info, blocked_reason); |
| 876 } |
| 877 |
| 878 void FrameFetchContext::ReportLocalLoadFailed(const KURL& url) const { |
| 879 FrameLoader::ReportLocalLoadFailed(GetFrame(), url.ElidedString()); |
| 880 } |
| 881 |
| 882 bool FrameFetchContext::ShouldBypassMainWorldCSP() const { |
| 883 return GetFrame()->GetScriptController().ShouldBypassMainWorldCSP(); |
| 884 } |
| 885 |
| 886 bool FrameFetchContext::IsSVGImageChromeClient() const { |
| 887 return GetFrame()->GetChromeClient().IsSVGImageChromeClient(); |
| 888 } |
| 889 |
| 890 void FrameFetchContext::CountUsage(UseCounter::Feature feature) const { |
| 891 UseCounter::Count(GetFrame()->GetDocument(), feature); |
| 892 } |
| 893 |
| 894 void FrameFetchContext::CountDeprecation(UseCounter::Feature feature) const { |
| 895 Deprecation::CountDeprecation(GetFrame()->GetDocument(), feature); |
| 896 } |
| 897 |
| 898 bool FrameFetchContext::ShouldBlockFetchByMixedContentCheck( |
| 899 const ResourceRequest& resource_request, |
| 900 const KURL& url, |
| 901 SecurityViolationReportingPolicy reporting_policy) const { |
| 902 return MixedContentChecker::ShouldBlockFetch(GetFrame(), resource_request, |
| 903 url, reporting_policy); |
| 904 } |
| 905 |
| 1085 DEFINE_TRACE(FrameFetchContext) { | 906 DEFINE_TRACE(FrameFetchContext) { |
| 1086 visitor->Trace(document_loader_); | 907 visitor->Trace(document_loader_); |
| 1087 BaseFetchContext::Trace(visitor); | 908 BaseFetchContext::Trace(visitor); |
| 1088 } | 909 } |
| 1089 | 910 |
| 1090 } // namespace blink | 911 } // namespace blink |
| OLD | NEW |