summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc319
1 files changed, 303 insertions, 16 deletions
diff --git a/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc b/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
index f0be0f5ecee..96beedf1085 100644
--- a/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
+++ b/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -4,7 +4,11 @@
#include "third_party/blink/renderer/core/loader/base_fetch_context.h"
+#include "net/http/structured_headers.h"
#include "services/network/public/cpp/request_mode.h"
+#include "third_party/blink/public/common/client_hints/client_hints.h"
+#include "third_party/blink/public/common/device_memory/approximated_device_memory.h"
+#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
@@ -13,8 +17,7 @@
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/core/loader/previews_resource_loading_hints.h"
-#include "third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.h"
+#include "third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.h"
#include "third_party/blink/renderer/core/loader/subresource_filter.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -24,9 +27,26 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
+#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
+namespace {
+
+// Simple function to add quotes to make headers strings.
+const AtomicString SerializeHeaderString(std::string str) {
+ std::string output;
+ if (!str.empty()) {
+ output = net::structured_headers::SerializeItem(
+ net::structured_headers::Item(str))
+ .value_or(std::string());
+ }
+
+ return AtomicString(output.c_str());
+}
+
+} // namespace
+
namespace blink {
base::Optional<ResourceRequestBlockedReason> BaseFetchContext::CanRequest(
@@ -47,17 +67,41 @@ base::Optional<ResourceRequestBlockedReason> BaseFetchContext::CanRequest(
return blocked_reason;
}
+base::Optional<ResourceRequestBlockedReason>
+BaseFetchContext::CanRequestBasedOnSubresourceFilterOnly(
+ ResourceType type,
+ const ResourceRequest& resource_request,
+ const KURL& url,
+ const ResourceLoaderOptions& options,
+ ReportingDisposition reporting_disposition,
+ const base::Optional<ResourceRequest::RedirectInfo>& redirect_info) const {
+ auto* subresource_filter = GetSubresourceFilter();
+ if (subresource_filter && type != ResourceType::kImportResource &&
+ !subresource_filter->AllowLoad(url, resource_request.GetRequestContext(),
+ reporting_disposition)) {
+ if (reporting_disposition == ReportingDisposition::kReport) {
+ DispatchDidBlockRequest(resource_request, options.initiator_info,
+ ResourceRequestBlockedReason::kSubresourceFilter,
+ type);
+ }
+ return ResourceRequestBlockedReason::kSubresourceFilter;
+ }
+
+ return base::nullopt;
+}
+
bool BaseFetchContext::CalculateIfAdSubresource(
- const ResourceRequest& request,
+ const ResourceRequestHead& request,
+ const base::Optional<KURL>& alias_url,
ResourceType type,
const FetchInitiatorInfo& initiator_info) {
- // A base class should override this is they have more signals than just the
- // SubresourceFilter.
+ // A derived class should override this if they have more signals than just
+ // the SubresourceFilter.
SubresourceFilter* filter = GetSubresourceFilter();
+ const KURL& url = alias_url ? alias_url.value() : request.Url();
return request.IsAdResource() ||
- (filter &&
- filter->IsAdResource(request.Url(), request.GetRequestContext()));
+ (filter && filter->IsAdResource(url, request.GetRequestContext()));
}
bool BaseFetchContext::SendConversionRequestInsteadOfRedirecting(
@@ -67,6 +111,229 @@ bool BaseFetchContext::SendConversionRequestInsteadOfRedirecting(
return false;
}
+void BaseFetchContext::AddClientHintsIfNecessary(
+ const ClientHintsPreferences& hints_preferences,
+ const url::Origin& resource_origin,
+ bool is_1p_origin,
+ base::Optional<UserAgentMetadata> ua,
+ const FeaturePolicy* policy,
+ const base::Optional<ClientHintImageInfo>& image_info,
+ const base::Optional<WTF::AtomicString>& lang,
+ ResourceRequest& request) {
+ // If the feature is enabled, then client hints are allowed only on secure
+ // URLs.
+ if (!ClientHintsPreferences::IsClientHintsAllowed(request.Url()))
+ return;
+
+ // Sec-CH-UA is special: we always send the header to all origins that are
+ // eligible for client hints (e.g. secure transport, JavaScript enabled).
+ //
+ // https://github.com/WICG/ua-client-hints
+ //
+ // One exception, however, is that a custom UA is sometimes set without
+ // specifying accomponying client hints, in which case we disable sending
+ // them.
+ if (ClientHintsPreferences::UserAgentClientHintEnabled() && ua) {
+ // ShouldSendClientHint is called to make sure UA is controlled by
+ // FeaturePolicy.
+ if (ShouldSendClientHint(ClientHintsMode::kStandard, policy,
+ resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUA,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUA)],
+ ua->SerializeBrandVersionList().c_str());
+ }
+
+ // We also send Sec-CH-UA-Mobile to all hints. It is a one-bit header
+ // identifying if the browser has opted for a "mobile" experience
+ // Formatted using the "sh-boolean" format from:
+ // https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html#boolean
+ // ShouldSendClientHint is called to make sure it's controlled by
+ // FeaturePolicy.
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUAMobile,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUAMobile)],
+ ua->mobile ? "?1" : "?0");
+ }
+ }
+
+ // If the frame is detached, then don't send any hints other than UA.
+ if (!policy)
+ return;
+
+ if (!RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled() &&
+ !base::FeatureList::IsEnabled(features::kAllowClientHintsToThirdParty) &&
+ !is_1p_origin) {
+ // No client hints for 3p origins.
+ return;
+ }
+
+ // The next 4 hints should be enabled if we're allowing legacy hints to third
+ // parties, or if FeaturePolicy delegation says they are allowed.
+ if (ShouldSendClientHint(
+ ClientHintsMode::kLegacy, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kDeviceMemory,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ "Device-Memory",
+ AtomicString(String::Number(
+ ApproximatedDeviceMemory::GetApproximatedDeviceMemory())));
+ }
+
+ // These hints only make sense if the image info is available
+ if (image_info) {
+ if (ShouldSendClientHint(ClientHintsMode::kLegacy, policy, resource_origin,
+ is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kDpr,
+ hints_preferences)) {
+ request.SetHttpHeaderField("DPR",
+ AtomicString(String::Number(image_info->dpr)));
+ }
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kLegacy, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kViewportWidth,
+ hints_preferences) &&
+ image_info->viewport_width) {
+ request.SetHttpHeaderField(
+ "Viewport-Width",
+ AtomicString(String::Number(image_info->viewport_width.value())));
+ }
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kLegacy, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kResourceWidth,
+ hints_preferences)) {
+ if (image_info->resource_width.is_set) {
+ float physical_width =
+ image_info->resource_width.width * image_info->dpr;
+ request.SetHttpHeaderField(
+ "Width", AtomicString(String::Number(ceil(physical_width))));
+ }
+ }
+ }
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kRtt, hints_preferences)) {
+ base::Optional<base::TimeDelta> http_rtt =
+ GetNetworkStateNotifier().GetWebHoldbackHttpRtt();
+ if (!http_rtt) {
+ http_rtt = GetNetworkStateNotifier().HttpRtt();
+ }
+
+ uint32_t rtt =
+ GetNetworkStateNotifier().RoundRtt(request.Url().Host(), http_rtt);
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kRtt)],
+ AtomicString(String::Number(rtt)));
+ }
+
+ if (ShouldSendClientHint(ClientHintsMode::kStandard, policy, resource_origin,
+ is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kDownlink,
+ hints_preferences)) {
+ base::Optional<double> throughput_mbps =
+ GetNetworkStateNotifier().GetWebHoldbackDownlinkThroughputMbps();
+ if (!throughput_mbps) {
+ throughput_mbps = GetNetworkStateNotifier().DownlinkThroughputMbps();
+ }
+
+ double mbps = GetNetworkStateNotifier().RoundMbps(request.Url().Host(),
+ throughput_mbps);
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kDownlink)],
+ AtomicString(String::Number(mbps)));
+ }
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kEct, hints_preferences)) {
+ base::Optional<WebEffectiveConnectionType> holdback_ect =
+ GetNetworkStateNotifier().GetWebHoldbackEffectiveType();
+ if (!holdback_ect)
+ holdback_ect = GetNetworkStateNotifier().EffectiveType();
+
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kEct)],
+ AtomicString(NetworkStateNotifier::EffectiveConnectionTypeToString(
+ holdback_ect.value())));
+ }
+
+ if (ShouldSendClientHint(ClientHintsMode::kStandard, policy, resource_origin,
+ is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kLang,
+ hints_preferences) &&
+ lang) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kLang)],
+ lang.value());
+ }
+
+ // Only send User Agent hints if the info is available
+ if (ClientHintsPreferences::UserAgentClientHintEnabled() && ua) {
+ if (ShouldSendClientHint(ClientHintsMode::kStandard, policy,
+ resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUAArch,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUAArch)],
+ SerializeHeaderString(ua->architecture));
+ }
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUAPlatform,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUAPlatform)],
+ SerializeHeaderString(ua->platform));
+ }
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUAPlatformVersion,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUAPlatformVersion)],
+ SerializeHeaderString(ua->platform_version));
+ }
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUAModel,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUAModel)],
+ SerializeHeaderString(ua->model));
+ }
+
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUAFullVersion,
+ hints_preferences)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUAFullVersion)],
+ SerializeHeaderString(ua->full_version));
+ }
+ }
+}
+
void BaseFetchContext::PrintAccessDeniedMessage(const KURL& url) const {
if (url.IsNull())
return;
@@ -119,7 +386,7 @@ BaseFetchContext::CheckCSPForRequestInternal(
return base::nullopt;
}
- const ContentSecurityPolicy* csp =
+ ContentSecurityPolicy* csp =
GetContentSecurityPolicyForWorld(options.world_for_csp.get());
if (csp &&
!csp->AllowRequest(request_context, request_destination, url,
@@ -254,16 +521,9 @@ BaseFetchContext::CanRequestInternal(
return ResourceRequestBlockedReason::kOther;
}
- // Loading of a subresource may be blocked by previews resource loading hints.
- if (GetPreviewsResourceLoadingHints() &&
- !GetPreviewsResourceLoadingHints()->AllowLoad(
- type, url, resource_request.Priority())) {
- return ResourceRequestBlockedReason::kOther;
- }
-
if (SendConversionRequestInsteadOfRedirecting(url, redirect_info,
reporting_disposition)) {
- return ResourceRequestBlockedReason::kOther;
+ return ResourceRequestBlockedReason::kConversionRequest;
}
// Let the client have the final say into whether or not the load should
@@ -278,6 +538,33 @@ BaseFetchContext::CanRequestInternal(
return base::nullopt;
}
+bool BaseFetchContext::ShouldSendClientHint(
+ ClientHintsMode mode,
+ const FeaturePolicy* policy,
+ const url::Origin& resource_origin,
+ bool is_1p_origin,
+ network::mojom::blink::WebClientHintsType type,
+ const ClientHintsPreferences& hints_preferences) const {
+ bool origin_ok;
+
+ if (mode == ClientHintsMode::kLegacy &&
+ base::FeatureList::IsEnabled(features::kAllowClientHintsToThirdParty)) {
+ origin_ok = true;
+ } else if (RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled()) {
+ origin_ok =
+ (policy && policy->IsFeatureEnabledForOrigin(
+ kClientHintsFeaturePolicyMapping[static_cast<int>(type)],
+ resource_origin));
+ } else {
+ origin_ok = is_1p_origin;
+ }
+
+ if (!origin_ok)
+ return false;
+
+ return IsClientHintSentByDefault(type) || hints_preferences.ShouldSend(type);
+}
+
void BaseFetchContext::AddBackForwardCacheExperimentHTTPHeaderIfNeeded(
ExecutionContext* context,
ResourceRequest& request) {