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