summaryrefslogtreecommitdiff
path: root/chromium/services/network/public
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/services/network/public')
-rw-r--r--chromium/services/network/public/cpp/BUILD.gn66
-rw-r--r--chromium/services/network/public/cpp/address_list_mojom_traits.cc6
-rw-r--r--chromium/services/network/public/cpp/address_list_mojom_traits.h5
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/BUILD.gn7
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/DIR_METADATA3
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.cc150
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.h32
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc17
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc9
-rw-r--r--chromium/services/network/public/cpp/client_hints.cc14
-rw-r--r--chromium/services/network/public/cpp/constants.cc3
-rw-r--r--chromium/services/network/public/cpp/constants.h4
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc477
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy.h26
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc591
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_context.cc41
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_context.h18
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc67
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source.cc174
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source.h18
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source_list.cc60
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source_list.h13
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc207
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc391
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc53
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits.h33
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc217
-rw-r--r--chromium/services/network/public/cpp/cors/cors.cc9
-rw-r--r--chromium/services/network/public/cpp/cors/cors_legacy.cc40
-rw-r--r--chromium/services/network/public/cpp/cors/cors_legacy.h39
-rw-r--r--chromium/services/network/public/cpp/cors/cors_unittest.cc1
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_cache.cc127
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_cache.h79
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_cache_unittest.cc211
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_result.cc212
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_result.h104
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_result_unittest.cc332
-rw-r--r--chromium/services/network/public/cpp/cross_origin_embedder_policy_parser.cc4
-rw-r--r--chromium/services/network/public/cpp/cross_origin_embedder_policy_parser_unittest.cc5
-rw-r--r--chromium/services/network/public/cpp/cross_origin_read_blocking.cc82
-rw-r--r--chromium/services/network/public/cpp/cross_origin_read_blocking.h16
-rw-r--r--chromium/services/network/public/cpp/cross_origin_read_blocking_unittest.cc13
-rw-r--r--chromium/services/network/public/cpp/cross_origin_resource_policy.cc7
-rw-r--r--chromium/services/network/public/cpp/cross_origin_resource_policy.h8
-rw-r--r--chromium/services/network/public/cpp/cross_origin_resource_policy_unittest.cc17
-rw-r--r--chromium/services/network/public/cpp/data_element.cc170
-rw-r--r--chromium/services/network/public/cpp/data_element.h257
-rw-r--r--chromium/services/network/public/cpp/data_pipe_to_source_stream_unittest.cc5
-rw-r--r--chromium/services/network/public/cpp/digitally_signed_mojom_traits_unittest.cc8
-rw-r--r--chromium/services/network/public/cpp/features.cc46
-rw-r--r--chromium/services/network/public/cpp/features.h15
-rw-r--r--chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc8
-rw-r--r--chromium/services/network/public/cpp/initiator_lock_compatibility.h3
-rw-r--r--chromium/services/network/public/cpp/ip_address_mojom_traits_unittest.cc6
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util.cc45
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util.h27
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util_unittest.cc94
-rw-r--r--chromium/services/network/public/cpp/is_potentially_trustworthy.cc89
-rw-r--r--chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc142
-rw-r--r--chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.h340
-rw-r--r--chromium/services/network/public/cpp/isolation_info_mojom_traits.cc18
-rw-r--r--chromium/services/network/public/cpp/isolation_info_mojom_traits.h6
-rw-r--r--chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc33
-rw-r--r--chromium/services/network/public/cpp/isolation_opt_in_hints.cc40
-rw-r--r--chromium/services/network/public/cpp/isolation_opt_in_hints.h41
-rw-r--r--chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc2
-rw-r--r--chromium/services/network/public/cpp/load_timing_info_mojom_traits.h5
-rw-r--r--chromium/services/network/public/cpp/net_ipc_param_traits.cc60
-rw-r--r--chromium/services/network/public/cpp/net_ipc_param_traits.h21
-rw-r--r--chromium/services/network/public/cpp/network_ipc_param_traits.cc155
-rw-r--r--chromium/services/network/public/cpp/network_ipc_param_traits.h43
-rw-r--r--chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc8
-rw-r--r--chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h8
-rw-r--r--chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc4
-rw-r--r--chromium/services/network/public/cpp/network_param_mojom_traits.cc15
-rw-r--r--chromium/services/network/public/cpp/network_param_mojom_traits.h41
-rw-r--r--chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc19
-rw-r--r--chromium/services/network/public/cpp/not_implemented_url_loader_factory.h22
-rw-r--r--chromium/services/network/public/cpp/opaque_response_blocking.cc220
-rw-r--r--chromium/services/network/public/cpp/opaque_response_blocking.h58
-rw-r--r--chromium/services/network/public/cpp/opaque_response_blocking_unittest.cc261
-rw-r--r--chromium/services/network/public/cpp/origin_agent_cluster_parser.cc (renamed from chromium/services/network/public/cpp/origin_isolation_parser.cc)4
-rw-r--r--chromium/services/network/public/cpp/origin_agent_cluster_parser.h (renamed from chromium/services/network/public/cpp/origin_isolation_parser.h)12
-rw-r--r--chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc31
-rw-r--r--chromium/services/network/public/cpp/origin_isolation_parser_unittest.cc31
-rw-r--r--chromium/services/network/public/cpp/origin_policy.cc9
-rw-r--r--chromium/services/network/public/cpp/origin_policy.h9
-rw-r--r--chromium/services/network/public/cpp/parsed_headers.cc17
-rw-r--r--chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc2
-rw-r--r--chromium/services/network/public/cpp/request_destination.cc6
-rw-r--r--chromium/services/network/public/cpp/resource_request.cc88
-rw-r--r--chromium/services/network/public/cpp/resource_request.h40
-rw-r--r--chromium/services/network/public/cpp/resource_request_body.cc38
-rw-r--r--chromium/services/network/public/cpp/resource_request_body.h7
-rw-r--r--chromium/services/network/public/cpp/schemeful_site_mojom_traits.cc11
-rw-r--r--chromium/services/network/public/cpp/schemeful_site_mojom_traits_unittest.cc2
-rw-r--r--chromium/services/network/public/cpp/self_deleting_url_loader_factory.cc52
-rw-r--r--chromium/services/network/public/cpp/self_deleting_url_loader_factory.h60
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader.cc10
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader_unittest.cc81
-rw-r--r--chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc13
-rw-r--r--chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h13
-rw-r--r--chromium/services/network/public/cpp/site_for_cookies_mojom_traits_unittest.cc2
-rw-r--r--chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc5
-rw-r--r--chromium/services/network/public/cpp/trust_token_http_headers.h2
-rw-r--r--chromium/services/network/public/cpp/url_loader_completion_status.h2
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits.cc137
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits.h159
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc99
-rw-r--r--chromium/services/network/public/cpp/x_frame_options.dict11
-rw-r--r--chromium/services/network/public/cpp/x_frame_options_parser.cc46
-rw-r--r--chromium/services/network/public/cpp/x_frame_options_parser.h22
-rw-r--r--chromium/services/network/public/cpp/x_frame_options_parser_fuzzer.cc22
-rw-r--r--chromium/services/network/public/cpp/x_frame_options_parser_unittest.cc81
-rw-r--r--chromium/services/network/public/mojom/BUILD.gn96
-rw-r--r--chromium/services/network/public/mojom/address_list.mojom5
-rw-r--r--chromium/services/network/public/mojom/auth_and_certificate_observer.mojom120
-rw-r--r--chromium/services/network/public/mojom/client_security_state.mojom4
-rw-r--r--chromium/services/network/public/mojom/content_security_policy.mojom58
-rw-r--r--chromium/services/network/public/mojom/cookie_access_observer.mojom7
-rw-r--r--chromium/services/network/public/mojom/cookie_manager.mojom32
-rw-r--r--chromium/services/network/public/mojom/fetch_api.mojom53
-rw-r--r--chromium/services/network/public/mojom/isolation_info.mojom2
-rw-r--r--chromium/services/network/public/mojom/load_timing_info.mojom1
-rw-r--r--chromium/services/network/public/mojom/network_context.mojom218
-rw-r--r--chromium/services/network/public/mojom/network_isolation_key.mojom9
-rw-r--r--chromium/services/network/public/mojom/network_param.mojom20
-rw-r--r--chromium/services/network/public/mojom/network_service.mojom51
-rw-r--r--chromium/services/network/public/mojom/network_service_test.mojom11
-rw-r--r--chromium/services/network/public/mojom/parsed_headers.mojom8
-rw-r--r--chromium/services/network/public/mojom/quic_transport.mojom5
-rw-r--r--chromium/services/network/public/mojom/site_for_cookies.mojom5
-rw-r--r--chromium/services/network/public/mojom/trust_tokens.mojom32
-rw-r--r--chromium/services/network/public/mojom/url_loader.mojom101
-rw-r--r--chromium/services/network/public/mojom/url_loader_factory.mojom7
-rw-r--r--chromium/services/network/public/mojom/url_response_head.mojom16
-rw-r--r--chromium/services/network/public/mojom/web_bundle_handle.mojom28
-rw-r--r--chromium/services/network/public/mojom/websocket.mojom7
-rw-r--r--chromium/services/network/public/mojom/x_frame_options.mojom16
-rw-r--r--chromium/services/network/public/proto/BUILD.gn7
-rw-r--r--chromium/services/network/public/proto/sct_audit_report.proto38
-rw-r--r--chromium/services/network/public/proto/tls_deprecation_config.proto19
142 files changed, 4523 insertions, 3920 deletions
diff --git a/chromium/services/network/public/cpp/BUILD.gn b/chromium/services/network/public/cpp/BUILD.gn
index 1ba78613e28..1e3bd0ffecc 100644
--- a/chromium/services/network/public/cpp/BUILD.gn
+++ b/chromium/services/network/public/cpp/BUILD.gn
@@ -43,10 +43,6 @@ component("cpp") {
"cors/origin_access_entry.h",
"cors/origin_access_list.cc",
"cors/origin_access_list.h",
- "cors/preflight_cache.cc",
- "cors/preflight_cache.h",
- "cors/preflight_result.cc",
- "cors/preflight_result.h",
"cross_origin_embedder_policy_parser.cc",
"cross_origin_embedder_policy_parser.h",
"cross_origin_opener_policy_parser.cc",
@@ -83,8 +79,10 @@ component("cpp") {
"network_switches.h",
"not_implemented_url_loader_factory.cc",
"not_implemented_url_loader_factory.h",
- "origin_isolation_parser.cc",
- "origin_isolation_parser.h",
+ "opaque_response_blocking.cc",
+ "opaque_response_blocking.h",
+ "origin_agent_cluster_parser.cc",
+ "origin_agent_cluster_parser.h",
"parsed_headers.cc",
"parsed_headers.h",
"request_destination.cc",
@@ -93,6 +91,8 @@ component("cpp") {
"request_mode.h",
"resolve_host_client_base.cc",
"resolve_host_client_base.h",
+ "self_deleting_url_loader_factory.cc",
+ "self_deleting_url_loader_factory.h",
"session_cookie_delete_predicate.h",
"shared_url_loader_factory.cc",
"shared_url_loader_factory.h",
@@ -114,6 +114,8 @@ component("cpp") {
"web_sandbox_flags.h",
"wrapper_shared_url_loader_factory.cc",
"wrapper_shared_url_loader_factory.h",
+ "x_frame_options_parser.cc",
+ "x_frame_options_parser.h",
]
if (!is_ios) {
@@ -179,12 +181,31 @@ component("cookies_mojom_support") {
]
deps = [
":crash_keys",
+ ":schemeful_site_mojom_support",
"//net",
"//services/network/public/mojom:cookies_mojom_shared",
]
defines = [ "IS_NETWORK_CPP_BASE_IMPL" ]
}
+component("network_param_mojom_support") {
+ sources = [
+ "net_ipc_param_traits.cc",
+ "net_ipc_param_traits.h",
+ "network_param_mojom_traits.cc",
+ "network_param_mojom_traits.h",
+ ]
+ deps = [
+ "//ipc",
+ "//mojo/public/cpp/base:shared_typemap_traits",
+ "//net",
+ "//services/network/public/mojom:mojom_network_param_shared",
+ "//url/ipc:url_ipc",
+ "//url/mojom:url_mojom_origin",
+ ]
+ defines = [ "IS_NETWORK_CPP_BASE_IMPL" ]
+}
+
# This component is separate from cpp_base as it is a dependency of
# //services/network/public/mojom:url_loader_base.
component("cross_origin_embedder_policy") {
@@ -237,12 +258,8 @@ component("cpp_base") {
"http_request_headers_mojom_traits.h",
"isolation_info_mojom_traits.cc",
"isolation_info_mojom_traits.h",
- "isolation_opt_in_hints.cc",
- "isolation_opt_in_hints.h",
"mutable_network_traffic_annotation_tag_mojom_traits.h",
"mutable_partial_network_traffic_annotation_tag_mojom_traits.h",
- "net_ipc_param_traits.cc",
- "net_ipc_param_traits.h",
"network_interface_mojom_traits.cc",
"network_interface_mojom_traits.h",
"network_ipc_param_traits.cc",
@@ -280,6 +297,7 @@ component("cpp_base") {
":crash_keys",
":cross_origin_embedder_policy",
":ip_address_mojom_support",
+ ":network_param_mojom_support",
":schemeful_site_mojom_support",
"//services/network/public/mojom:url_loader_base",
"//third_party/webrtc_overrides:webrtc_component",
@@ -303,6 +321,21 @@ mojom("test_interfaces") {
public_deps = [ "//services/network/public/mojom" ]
}
+source_set("test_support") {
+ testonly = true
+
+ sources = [ "is_potentially_trustworthy_unittest.h" ]
+
+ public_deps = [
+ ":cpp",
+ "//base",
+ "//base/test:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//url:url_test_support",
+ ]
+}
+
source_set("tests") {
testonly = true
@@ -316,8 +349,6 @@ source_set("tests") {
"cors/cors_unittest.cc",
"cors/origin_access_entry_unittest.cc",
"cors/origin_access_list_unittest.cc",
- "cors/preflight_cache_unittest.cc",
- "cors/preflight_result_unittest.cc",
"cross_origin_embedder_policy_parser_unittest.cc",
"cross_origin_opener_policy_parser_unittest.cc",
"cross_origin_read_blocking_unittest.cc",
@@ -340,8 +371,9 @@ source_set("tests") {
"network_isolation_key_mojom_traits_unittest.cc",
"network_mojom_traits_unittest.cc",
"network_quality_tracker_unittest.cc",
+ "opaque_response_blocking_unittest.cc",
"optional_trust_token_params_unittest.cc",
- "origin_isolation_parser_unittest.cc",
+ "origin_agent_cluster_parser_unittest.cc",
"proxy_config_mojom_traits_unittest.cc",
"schemeful_site_mojom_traits_unittest.cc",
"simple_url_loader_unittest.cc",
@@ -350,6 +382,7 @@ source_set("tests") {
"supports_loading_mode/supports_loading_mode_parser_unittest.cc",
"url_request_mojom_traits_unittest.cc",
"web_sandbox_flags_unittests.cc",
+ "x_frame_options_parser_unittest.cc",
]
if (!is_ios) {
@@ -359,6 +392,7 @@ source_set("tests") {
deps = [
":cpp",
":test_interfaces",
+ ":test_support",
"//base",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/test_support:test_utils",
@@ -373,6 +407,12 @@ source_set("tests") {
public_deps = [ ":buildflags" ]
}
+fuzzer_test("xfo_fuzzer") {
+ sources = [ "x_frame_options_parser_fuzzer.cc" ]
+ dict = "x_frame_options.dict"
+ deps = [ ":cpp" ]
+}
+
fuzzer_test("cors_fuzzer") {
sources = [ "cors/cors_fuzzer.cc" ]
deps = [ ":cpp" ]
diff --git a/chromium/services/network/public/cpp/address_list_mojom_traits.cc b/chromium/services/network/public/cpp/address_list_mojom_traits.cc
index 0dac1c7c001..795bbb9a856 100644
--- a/chromium/services/network/public/cpp/address_list_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/address_list_mojom_traits.cc
@@ -16,10 +16,10 @@ bool StructTraits<network::mojom::AddressListDataView, net::AddressList>::Read(
if (!data.ReadAddresses(&out->endpoints()))
return false;
- std::string canonical_name;
- if (!data.ReadCanonicalName(&canonical_name))
+ std::vector<std::string> dns_aliases;
+ if (!data.ReadDnsAliases(&dns_aliases))
return false;
- out->set_canonical_name(canonical_name);
+ out->SetDnsAliases(std::move(dns_aliases));
return true;
}
diff --git a/chromium/services/network/public/cpp/address_list_mojom_traits.h b/chromium/services/network/public/cpp/address_list_mojom_traits.h
index 6c47b7c7aa4..7186789268a 100644
--- a/chromium/services/network/public/cpp/address_list_mojom_traits.h
+++ b/chromium/services/network/public/cpp/address_list_mojom_traits.h
@@ -22,8 +22,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
return obj.endpoints();
}
- static const std::string& canonical_name(const net::AddressList& obj) {
- return obj.canonical_name();
+ static const std::vector<std::string>& dns_aliases(
+ const net::AddressList& obj) {
+ return obj.dns_aliases();
}
static bool Read(network::mojom::AddressListDataView data,
diff --git a/chromium/services/network/public/cpp/cert_verifier/BUILD.gn b/chromium/services/network/public/cpp/cert_verifier/BUILD.gn
index cf8e80d2d6f..a0e55c95f7c 100644
--- a/chromium/services/network/public/cpp/cert_verifier/BUILD.gn
+++ b/chromium/services/network/public/cpp/cert_verifier/BUILD.gn
@@ -22,12 +22,9 @@ source_set("mojo_cert_verifier") {
}
source_set("cert_verifier_creation") {
- sources = [
- "cert_verifier_creation.cc",
- "cert_verifier_creation.h",
- ]
+ sources = []
- if (is_ash) {
+ if (is_chromeos_ash) {
sources += [
"system_trust_store_provider_chromeos.cc",
"system_trust_store_provider_chromeos.h",
diff --git a/chromium/services/network/public/cpp/cert_verifier/DIR_METADATA b/chromium/services/network/public/cpp/cert_verifier/DIR_METADATA
index c97d1840b0a..14a5f5e3989 100644
--- a/chromium/services/network/public/cpp/cert_verifier/DIR_METADATA
+++ b/chromium/services/network/public/cpp/cert_verifier/DIR_METADATA
@@ -8,4 +8,5 @@
monorail {
component: "Internals>Network>Certificate"
-} \ No newline at end of file
+}
+team_email: "trusty-transport@chromium.org"
diff --git a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.cc b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.cc
deleted file mode 100644
index c1974d1533d..00000000000
--- a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/public/cpp/cert_verifier/cert_verifier_creation.h"
-
-#include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
-#include "net/base/features.h"
-#include "net/cert_net/cert_net_fetcher_url_request.h"
-#include "net/net_buildflags.h"
-
-#if BUILDFLAG(IS_ASH)
-#include "crypto/nss_util_internal.h"
-#include "net/cert/cert_verify_proc.h"
-#include "net/cert/cert_verify_proc_builtin.h"
-#include "net/cert/internal/system_trust_store.h"
-#include "net/cert/multi_threaded_cert_verifier.h"
-#include "services/network/public/cpp/cert_verifier/system_trust_store_provider_chromeos.h"
-#endif
-
-#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED) || \
- BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
-#include "net/cert/cert_verify_proc.h"
-#include "net/cert/cert_verify_proc_builtin.h"
-#include "net/cert/multi_threaded_cert_verifier.h"
-#endif
-
-#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
-#include "services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo.h"
-#endif
-
-namespace network {
-
-namespace {
-
-#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
-bool UsingBuiltinCertVerifier(
- mojom::CertVerifierCreationParams::CertVerifierImpl mode) {
- switch (mode) {
- case mojom::CertVerifierCreationParams::CertVerifierImpl::kDefault:
- return base::FeatureList::IsEnabled(
- net::features::kCertVerifierBuiltinFeature);
- case mojom::CertVerifierCreationParams::CertVerifierImpl::kBuiltin:
- return true;
- case mojom::CertVerifierCreationParams::CertVerifierImpl::kSystem:
- return false;
- }
-}
-#endif
-
-#if BUILDFLAG(IS_ASH)
-scoped_refptr<net::CertVerifyProc> CreateCertVerifyProcForUser(
- scoped_refptr<net::CertNetFetcher> net_fetcher,
- crypto::ScopedPK11Slot user_public_slot) {
- return net::CreateCertVerifyProcBuiltin(
- std::move(net_fetcher),
- std::make_unique<SystemTrustStoreProviderChromeOS>(
- std::move(user_public_slot)));
-}
-
-scoped_refptr<net::CertVerifyProc> CreateCertVerifyProcWithoutUserSlots(
- scoped_refptr<net::CertNetFetcher> net_fetcher) {
- return net::CreateCertVerifyProcBuiltin(
- std::move(net_fetcher),
- std::make_unique<SystemTrustStoreProviderChromeOS>());
-}
-#endif // BUILDFLAG(IS_ASH)
-
-} // namespace
-
-bool IsUsingCertNetFetcher() {
-#if defined(OS_ANDROID) || defined(OS_FUCHSIA) || defined(OS_CHROMEOS) || \
- defined(OS_LINUX) || \
- BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED) || \
- BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
- return true;
-#else
- return false;
-#endif
-}
-
-std::unique_ptr<net::CertVerifier> CreateCertVerifier(
- mojom::CertVerifierCreationParams* creation_params,
- scoped_refptr<net::CertNetFetcher> cert_net_fetcher) {
- DCHECK(cert_net_fetcher || !IsUsingCertNetFetcher());
-
- std::unique_ptr<net::CertVerifier> cert_verifier;
-
- bool use_builtin_cert_verifier;
-#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
- use_builtin_cert_verifier =
- creation_params
- ? UsingBuiltinCertVerifier(creation_params->use_builtin_cert_verifier)
- : UsingBuiltinCertVerifier(
- mojom::CertVerifierCreationParams::CertVerifierImpl::kDefault);
-#else
- use_builtin_cert_verifier = false;
-#endif
-
-#if BUILDFLAG(IS_ASH)
- scoped_refptr<net::CertVerifyProc> verify_proc;
- if (!creation_params || creation_params->username_hash.empty()) {
- verify_proc =
- CreateCertVerifyProcWithoutUserSlots(std::move(cert_net_fetcher));
- } else {
- // Make sure NSS is initialized for the user.
- crypto::InitializeNSSForChromeOSUser(creation_params->username_hash,
- creation_params->nss_path.value());
-
- crypto::ScopedPK11Slot public_slot =
- crypto::GetPublicSlotForChromeOSUser(creation_params->username_hash);
- verify_proc = CreateCertVerifyProcForUser(std::move(cert_net_fetcher),
- std::move(public_slot));
- }
- cert_verifier =
- std::make_unique<net::MultiThreadedCertVerifier>(std::move(verify_proc));
-#endif
-#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
- if (!cert_verifier && creation_params &&
- creation_params->trial_comparison_cert_verifier_params) {
- cert_verifier = std::make_unique<TrialComparisonCertVerifierMojo>(
- creation_params->trial_comparison_cert_verifier_params->initial_allowed,
- std::move(creation_params->trial_comparison_cert_verifier_params
- ->config_client_receiver),
- std::move(creation_params->trial_comparison_cert_verifier_params
- ->report_client),
- net::CertVerifyProc::CreateSystemVerifyProc(cert_net_fetcher),
- net::CertVerifyProc::CreateBuiltinVerifyProc(cert_net_fetcher));
- }
-#endif
-#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
- if (!cert_verifier) {
- cert_verifier = std::make_unique<net::MultiThreadedCertVerifier>(
- use_builtin_cert_verifier
- ? net::CertVerifyProc::CreateBuiltinVerifyProc(
- std::move(cert_net_fetcher))
- : net::CertVerifyProc::CreateSystemVerifyProc(
- std::move(cert_net_fetcher)));
- }
-#endif
-
- if (!cert_verifier) {
- cert_verifier = net::CertVerifier::CreateDefaultWithoutCaching(
- std::move(cert_net_fetcher));
- }
-
- return cert_verifier;
-}
-} // namespace network
diff --git a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.h b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.h
deleted file mode 100644
index ea6a8120661..00000000000
--- a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_creation.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_NETWORK_PUBLIC_CPP_CERT_VERIFIER_CERT_VERIFIER_CREATION_H_
-#define SERVICES_NETWORK_PUBLIC_CPP_CERT_VERIFIER_CERT_VERIFIER_CREATION_H_
-
-#include <memory>
-
-#include "base/component_export.h"
-#include "base/memory/scoped_refptr.h"
-#include "net/cert/cert_net_fetcher.h"
-#include "net/cert/cert_verifier.h"
-#include "services/network/public/mojom/network_context.mojom.h"
-
-namespace network {
-
-// Certain platforms and build configurations require a net::CertNetFetcher in
-// order to instantiate a net::CertVerifier. Callers of CreateCertVerifier() can
-// call IsUsingCertNetFetcher() to decide whether or not to pass a
-// net::CertNetFetcher.
-bool IsUsingCertNetFetcher();
-
-// Creates a concrete net::CertVerifier based on the platform and the particular
-// build configuration. |creation_params| is optional.
-std::unique_ptr<net::CertVerifier> CreateCertVerifier(
- mojom::CertVerifierCreationParams* creation_params,
- scoped_refptr<net::CertNetFetcher> cert_net_fetcher);
-
-} // namespace network
-
-#endif // SERVICES_NETWORK_PUBLIC_CPP_CERT_VERIFIER_CERT_VERIFIER_CREATION_H_
diff --git a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
index 3388e84eb7a..790d06e3023 100644
--- a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
@@ -34,7 +34,7 @@ TEST(CertVerifierMojomTraitsTest, RequestParams) {
net::CertVerifier::RequestParams out_params;
ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::RequestParams>(
- &params, &out_params));
+ params, out_params));
ASSERT_EQ(params, out_params);
}
@@ -114,7 +114,7 @@ TEST(CertVerifierMojomTraitsTest, ConfigBasic) {
net::CertVerifier::Config out_config;
ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CertVerifierConfig>(
- &config, &out_config));
+ config, out_config));
ASSERT_TRUE(ConfigsEqual(config, out_config));
}
@@ -128,19 +128,16 @@ TEST(CertVerifierMojomTraitsTest, ConfigTrue) {
net::CertVerifier::Config out_config;
ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CertVerifierConfig>(
- &config, &out_config));
+ config, out_config));
ASSERT_TRUE(ConfigsEqual(config, out_config));
}
TEST(CertVerifierMojomTraitsTest, ConfigCRLAndAdditionalCerts) {
std::string crl_set;
- {
- base::ScopedAllowBlockingForTesting allow_blocking;
- base::ReadFileToString(
- net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
- &crl_set);
- }
+ base::ReadFileToString(
+ net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
+ &crl_set);
const base::FilePath certs_dir = net::GetTestCertsDirectory();
@@ -157,7 +154,7 @@ TEST(CertVerifierMojomTraitsTest, ConfigCRLAndAdditionalCerts) {
net::CertVerifier::Config out_config;
ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CertVerifierConfig>(
- &config, &out_config));
+ config, out_config));
ASSERT_TRUE(ConfigsEqual(config, out_config));
}
diff --git a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
index 767d136b405..b562727948d 100644
--- a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
@@ -18,10 +18,12 @@ class CertVerifierRequestImpl : public mojom::CertVerifierRequest,
public:
CertVerifierRequestImpl(
mojo::PendingReceiver<mojom::CertVerifierRequest> receiver,
+ scoped_refptr<net::X509Certificate> cert,
net::CertVerifyResult* verify_result,
net::CompletionOnceCallback callback,
const net::NetLogWithSource& net_log)
: receiver_(this, std::move(receiver)),
+ cert_(cert),
cert_verify_result_(verify_result),
completion_callback_(std::move(callback)),
net_log_(net_log) {
@@ -50,12 +52,15 @@ class CertVerifierRequestImpl : public mojom::CertVerifierRequest,
// The CertVerifierRequest disconnected.
DCHECK(completion_callback_);
*cert_verify_result_ = net::CertVerifyResult();
+ cert_verify_result_->verified_cert = cert_;
cert_verify_result_->cert_status = net::CERT_STATUS_INVALID;
std::move(completion_callback_).Run(net::ERR_ABORTED);
}
private:
mojo::Receiver<mojom::CertVerifierRequest> receiver_;
+ // Certificate being verified.
+ scoped_refptr<net::X509Certificate> cert_;
// Out parameter for the result.
net::CertVerifyResult* cert_verify_result_;
// Callback to call once the result is available.
@@ -119,8 +124,8 @@ int MojoCertVerifier::Verify(
cert_verifier_request.InitWithNewPipeAndPassReceiver();
mojo_cert_verifier_->Verify(params, std::move(cert_verifier_request));
*out_req = std::make_unique<CertVerifierRequestImpl>(
- std::move(cert_verifier_receiver), verify_result, std::move(callback),
- net_log);
+ std::move(cert_verifier_receiver), params.certificate(), verify_result,
+ std::move(callback), net_log);
return net::ERR_IO_PENDING;
}
diff --git a/chromium/services/network/public/cpp/client_hints.cc b/chromium/services/network/public/cpp/client_hints.cc
index db8bb0d2315..6beb9b69a88 100644
--- a/chromium/services/network/public/cpp/client_hints.cc
+++ b/chromium/services/network/public/cpp/client_hints.cc
@@ -26,13 +26,13 @@ const char* const kClientHintsNameMapping[] = {"device-memory",
"downlink",
"ect",
"lang",
- "ua",
- "ua-arch",
- "ua-platform",
- "ua-model",
- "ua-mobile",
- "ua-full-version",
- "ua-platform-version"};
+ "sec-ch-ua",
+ "sec-ch-ua-arch",
+ "sec-ch-ua-platform",
+ "sec-ch-ua-model",
+ "sec-ch-ua-mobile",
+ "sec-ch-ua-full-version",
+ "sec-ch-ua-platform-version"};
const size_t kClientHintsMappingsCount = base::size(kClientHintsNameMapping);
diff --git a/chromium/services/network/public/cpp/constants.cc b/chromium/services/network/public/cpp/constants.cc
index c766f565c6e..d9090e19bed 100644
--- a/chromium/services/network/public/cpp/constants.cc
+++ b/chromium/services/network/public/cpp/constants.cc
@@ -6,9 +6,6 @@
namespace network {
-const char kFrameAcceptHeaderValue[] =
- "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
- "image/apng,*/*;q=0.8";
const char kDefaultAcceptHeaderValue[] = "*/*";
} // namespace network
diff --git a/chromium/services/network/public/cpp/constants.h b/chromium/services/network/public/cpp/constants.h
index 55772c98fa9..0008d465666 100644
--- a/chromium/services/network/public/cpp/constants.h
+++ b/chromium/services/network/public/cpp/constants.h
@@ -14,10 +14,6 @@ namespace network {
// The default buffer size of DataPipe which is used to send the content body.
static constexpr size_t kDataPipeDefaultAllocationSize = 512 * 1024;
-// Accept header used for frame requests.
-COMPONENT_EXPORT(NETWORK_CPP)
-extern const char kFrameAcceptHeaderValue[];
-
// The default Accept header value to use if none were specified.
COMPONENT_EXPORT(NETWORK_CPP)
extern const char kDefaultAcceptHeaderValue[];
diff --git a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc
index d69c1fc5eda..7450e790226 100644
--- a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc
@@ -6,8 +6,10 @@
#include <sstream>
#include <string>
+#include "base/base64url.h"
#include "base/containers/flat_set.h"
#include "base/ranges/algorithm.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -18,7 +20,6 @@
#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "services/network/public/cpp/content_security_policy/csp_source.h"
#include "services/network/public/cpp/content_security_policy/csp_source_list.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "url/gurl.h"
@@ -39,73 +40,9 @@ bool IsDirectiveNameCharacter(char c) {
}
bool IsDirectiveValueCharacter(char c) {
+ // Whitespace + VCHAR, but not ',' and ';'
return base::IsAsciiWhitespace(c) ||
- base::IsAsciiPrintable(c); // Whitespace + VCHAR
-}
-
-static CSPDirectiveName CSPFallback(CSPDirectiveName directive,
- CSPDirectiveName original_directive) {
- switch (directive) {
- case CSPDirectiveName::ConnectSrc:
- case CSPDirectiveName::FontSrc:
- case CSPDirectiveName::ImgSrc:
- case CSPDirectiveName::ManifestSrc:
- case CSPDirectiveName::MediaSrc:
- case CSPDirectiveName::PrefetchSrc:
- case CSPDirectiveName::ObjectSrc:
- case CSPDirectiveName::ScriptSrc:
- case CSPDirectiveName::StyleSrc:
- return CSPDirectiveName::DefaultSrc;
-
- case CSPDirectiveName::ScriptSrcAttr:
- case CSPDirectiveName::ScriptSrcElem:
- return CSPDirectiveName::ScriptSrc;
-
- case CSPDirectiveName::StyleSrcAttr:
- case CSPDirectiveName::StyleSrcElem:
- return CSPDirectiveName::StyleSrc;
-
- case CSPDirectiveName::FrameSrc:
- case CSPDirectiveName::WorkerSrc:
- return CSPDirectiveName::ChildSrc;
-
- // Because the fallback chain of child-src can be different if we are
- // checking a worker or a frame request, we need to know the original type
- // of the request to decide. These are the fallback chains for worker-src
- // and frame-src specifically.
-
- // worker-src > child-src > script-src > default-src
- // frame-src > child-src > default-src
-
- // Since there are some situations and tests that will operate on the
- // `child-src` directive directly (like for example the EE subsumption
- // algorithm), we consider the child-src > default-src fallback path as the
- // "default" and the worker-src fallback path as an exception.
- case CSPDirectiveName::ChildSrc:
- if (original_directive == CSPDirectiveName::WorkerSrc)
- return CSPDirectiveName::ScriptSrc;
-
- return CSPDirectiveName::DefaultSrc;
-
- case CSPDirectiveName::BaseURI:
- case CSPDirectiveName::BlockAllMixedContent:
- case CSPDirectiveName::DefaultSrc:
- case CSPDirectiveName::FormAction:
- case CSPDirectiveName::FrameAncestors:
- case CSPDirectiveName::NavigateTo:
- case CSPDirectiveName::PluginTypes:
- case CSPDirectiveName::ReportTo:
- case CSPDirectiveName::ReportURI:
- case CSPDirectiveName::RequireTrustedTypesFor:
- case CSPDirectiveName::Sandbox:
- case CSPDirectiveName::TreatAsPublicAddress:
- case CSPDirectiveName::TrustedTypes:
- case CSPDirectiveName::UpgradeInsecureRequests:
- return CSPDirectiveName::Unknown;
- case CSPDirectiveName::Unknown:
- NOTREACHED();
- return CSPDirectiveName::Unknown;
- }
+ (base::IsAsciiPrintable(c) && c != ',' && c != ';');
}
std::string ElideURLForReportViolation(const GURL& url) {
@@ -135,7 +72,6 @@ bool SupportedInReportOnly(CSPDirectiveName directive) {
case CSPDirectiveName::MediaSrc:
case CSPDirectiveName::NavigateTo:
case CSPDirectiveName::ObjectSrc:
- case CSPDirectiveName::PluginTypes:
case CSPDirectiveName::PrefetchSrc:
case CSPDirectiveName::ReportTo:
case CSPDirectiveName::ReportURI:
@@ -181,7 +117,6 @@ const char* ErrorMessage(CSPDirectiveName directive) {
case CSPDirectiveName::ManifestSrc:
case CSPDirectiveName::MediaSrc:
case CSPDirectiveName::ObjectSrc:
- case CSPDirectiveName::PluginTypes:
case CSPDirectiveName::PrefetchSrc:
case CSPDirectiveName::ReportTo:
case CSPDirectiveName::ReportURI:
@@ -215,7 +150,7 @@ void ReportViolation(CSPContext* context,
// ensure that these are not transmitted between different cross-origin
// renderers.
GURL blocked_url = (directive_name == CSPDirectiveName::FrameAncestors)
- ? GURL(ToString(context->self_source()))
+ ? GURL(ToString(*policy->self_origin))
: url;
auto safe_source_location =
source_location ? source_location->Clone() : mojom::SourceLocation::New();
@@ -303,8 +238,10 @@ DirectivesMap ParseHeaderValue(base::StringPiece header) {
// 5. Let directive value be the result of splitting token on ASCII
// whitespace.
base::StringPiece value;
- if (pos != std::string::npos)
- value = directive.substr(pos + 1);
+ if (pos != std::string::npos) {
+ value = base::TrimString(directive.substr(pos + 1),
+ base::kWhitespaceASCII, base::TRIM_ALL);
+ }
// 6. Let directive be a new directive whose name is directive name,
// and value is directive value.
@@ -562,7 +499,18 @@ bool ParseHash(base::StringPiece expression, mojom::CSPHashSource* hash) {
return false;
hash->algorithm = item.type;
- hash->value = subexpression.as_string();
+
+ // We lazily accept both base64url and base64-encoded data.
+ std::string normalized_value;
+ base::ReplaceChars(subexpression, "+", "-", &normalized_value);
+ base::ReplaceChars(normalized_value, "/", "_", &normalized_value);
+
+ std::string out;
+ if (!base::Base64UrlDecode(normalized_value,
+ base::Base64UrlDecodePolicy::IGNORE_PADDING,
+ &out))
+ return false;
+ hash->value = std::vector<uint8_t>(out.begin(), out.end());
return true;
}
}
@@ -694,35 +642,79 @@ mojom::CSPSourceListPtr ParseSourceList(
return directive;
}
-// Checks whether |expression| is a plugin type matching the regex:
-// [^\s/]+\/[^\s/]+
-// We assume |expression| does not contain any whitespaces.
-bool IsPluginType(base::StringPiece expression) {
- auto* it = expression.begin();
- auto* end = expression.end();
+// Parse the 'required-trusted-types-for' directive.
+// https://w3c.github.io/webappsec-trusted-types/dist/spec/#require-trusted-types-for-csp-directive
+network::mojom::CSPRequireTrustedTypesFor ParseRequireTrustedTypesFor(
+ base::StringPiece value,
+ std::vector<std::string>& parsing_errors) {
+ network::mojom::CSPRequireTrustedTypesFor out =
+ network::mojom::CSPRequireTrustedTypesFor::None;
+ for (const auto expression : base::SplitStringPiece(
+ value, base::kWhitespaceASCII, base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
+ if (expression == "'script'") {
+ out = network::mojom::CSPRequireTrustedTypesFor::Script;
+ } else {
+ const char* hint = nullptr;
+ if (expression == "script" || expression == "scripts" ||
+ expression == "'scripts'") {
+ hint = " Did you mean 'script'?";
+ }
- int count_1 = EatChar(&it, end, [](char c) { return c != '/'; });
- if (it == end || *it != '/')
- return false;
- ++it;
- int count_2 = EatChar(&it, end, [](char c) { return c != '/'; });
+ parsing_errors.emplace_back(base::StringPrintf(
+ "Invalid expression in 'require-trusted-types-for' "
+ "Content Security Policy directive: %s.%s\n",
+ expression.as_string().c_str(), hint));
+ }
+ }
+ if (out == network::mojom::CSPRequireTrustedTypesFor::None)
+ parsing_errors.emplace_back(base::StringPrintf(
+ "'require-trusted-types-for' Content Security Policy "
+ "directive is empty; The directive has no effect.\n"));
+ return out;
+}
- return count_1 >= 1 && count_2 >= 1 && it == end;
+// This implements tt-policy-name from
+// https://w3c.github.io/webappsec-trusted-types/dist/spec/#trusted-types-csp-directive/
+bool IsValidTrustedTypesPolicyName(base::StringPiece value) {
+ return base::ranges::all_of(value, [](char c) {
+ return base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) ||
+ base::Contains("-#=_/@.%", c);
+ });
}
-std::vector<std::string> ParsePluginTypes(
+// Parse the 'trusted-types' directive.
+// https://w3c.github.io/webappsec-trusted-types/dist/spec/#trusted-types-csp-directive
+network::mojom::CSPTrustedTypesPtr ParseTrustedTypes(
base::StringPiece value,
std::vector<std::string>& parsing_errors) {
- std::vector<std::string> out;
- for (const auto expression : base::SplitStringPiece(
- value, base::kWhitespaceASCII, base::TRIM_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY)) {
- if (IsPluginType(expression))
- out.emplace_back(expression.as_string());
+ auto out = network::mojom::CSPTrustedTypes::New();
+ std::vector<base::StringPiece> pieces =
+ base::SplitStringPiece(value, base::kWhitespaceASCII,
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ if (pieces.size() == 1 && pieces[0] == "'none'")
+ return out;
+
+ for (const auto expression : pieces) {
+ if (expression == "*")
+ out->allow_any = true;
+ else if (expression == "'allow-duplicates'")
+ out->allow_duplicates = true;
+ else if (expression == "'none'") {
+ parsing_errors.emplace_back(
+ "The value of the Content Security Policy directive "
+ "'trusted_types' contains an invalid policy: 'none'. "
+ "It will be ignored. "
+ "Note that 'none' has no effect unless it is the only "
+ "expression in the directive value.");
+ } else if (IsValidTrustedTypesPolicyName(expression))
+ out->list.emplace_back(expression);
else {
parsing_errors.emplace_back(base::StringPrintf(
- "Invalid plugin type in 'plugin-types' Content Security Policy "
- "directive: '%s'.",
+ "The value of the Content Security Policy directive "
+ "'trusted_types' contains an invalid policy: '%s'. "
+ "It will be ignored.",
expression.as_string().c_str()));
}
}
@@ -766,6 +758,47 @@ void ParseReportDirective(const GURL& request_url,
}
}
+void WarnIfDirectiveValueNotEmpty(
+ const std::pair<base::StringPiece, base::StringPiece>& directive,
+ std::vector<std::string>& parsing_errors) {
+ if (!directive.second.empty()) {
+ parsing_errors.emplace_back(base::StringPrintf(
+ "The Content Security Policy directive '%s' should be empty, but was "
+ "delivered with a value of '%s'. The directive has been applied, and "
+ "the value ignored.",
+ directive.first.as_string().c_str(),
+ directive.second.as_string().c_str()));
+ }
+}
+
+mojom::CSPSourcePtr ComputeSelfOrigin(const GURL& url) {
+ if (url.scheme() == url::kFileScheme) {
+ // Forget the host for file schemes. Host can anyway only be `localhost` or
+ // empty and this is platform dependent.
+ //
+ // TODO(antoniosartori): Consider returning mojom::CSPSource::New() for
+ // file: urls, so that 'self' for file: would match nothing.
+ return mojom::CSPSource::New(url::kFileScheme, "", url::PORT_UNSPECIFIED,
+ "", false, false);
+ }
+ return mojom::CSPSource::New(url.scheme(), url.host(), url.EffectiveIntPort(),
+ "", false, false);
+}
+
+std::string UnrecognizedDirectiveErrorMessage(
+ const std::string& directive_name) {
+ if (base::EqualsCaseInsensitiveASCII(directive_name, "plugin-types")) {
+ return "The Content-Security-Policy directive 'plugin-types' has been "
+ "removed from the "
+ "specification. If you want to block plugins, consider specifying "
+ "\"object-src 'none'\" instead.";
+ }
+
+ return base::StringPrintf(
+ "Unrecognized Content-Security-Policy directive '%s'.",
+ directive_name.c_str());
+}
+
void AddContentSecurityPolicyFromHeader(base::StringPiece header,
mojom::ContentSecurityPolicyType type,
const GURL& base_url,
@@ -773,6 +806,7 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header,
DirectivesMap directives = ParseHeaderValue(header);
out->header = mojom::ContentSecurityPolicyHeader::New(
header.as_string(), type, mojom::ContentSecurityPolicySource::kHTTP);
+ out->self_origin = ComputeSelfOrigin(base_url);
for (auto directive : directives) {
if (!base::ranges::all_of(directive.first, IsDirectiveNameCharacter)) {
@@ -784,28 +818,39 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header,
continue;
}
- if (!base::ranges::all_of(directive.second, IsDirectiveValueCharacter)) {
- out->parsing_errors.emplace_back(base::StringPrintf(
- "The value for the Content-Security-Policy directive '%s' contains "
- "one or more invalid characters. Non-whitespace characters outside "
- "ASCII 0x21-0x7E must be percent-encoded, as described in RFC 3986, "
- "section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1.",
- directive.first.as_string().c_str()));
- continue;
- }
-
CSPDirectiveName directive_name =
ToCSPDirectiveName(directive.first.as_string());
+ if (directive_name == CSPDirectiveName::Unknown) {
+ out->parsing_errors.emplace_back(
+ UnrecognizedDirectiveErrorMessage(directive.first.as_string()));
+ continue;
+ }
+
// A directive with this name has already been parsed. Skip further
// directives per
// https://www.w3.org/TR/CSP3/#parse-serialized-policy.
- if (out->directives.count(directive_name)) {
+ if (out->raw_directives.count(directive_name)) {
out->parsing_errors.emplace_back(base::StringPrintf(
"Ignoring duplicate Content-Security-Policy directive '%s'.",
directive.first.as_string().c_str()));
continue;
}
+ out->raw_directives[directive_name] = directive.second.as_string();
+
+ if (!base::ranges::all_of(directive.second, IsDirectiveValueCharacter)) {
+ out->parsing_errors.emplace_back(base::StringPrintf(
+ "The value for the Content-Security-Policy directive '%s' contains "
+ "one or more invalid characters. In a source expression, "
+ "non-whitespace characters outside ASCII "
+ "0x21-0x7E must be Punycode-encoded, as described in RFC 3492 "
+ "(https://tools.ietf.org/html/rfc3492), if part of the hostname and "
+ "percent-encoded, as described in RFC 3986, section 2.1 "
+ "(http://tools.ietf.org/html/rfc3986#section-2.1), if part of the "
+ "path.",
+ directive.first.as_string().c_str()));
+ continue;
+ }
if (type == mojom::ContentSecurityPolicyType::kReport &&
!SupportedInReportOnly(directive_name)) {
@@ -842,51 +887,38 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header,
directive_name, directive.second, out->parsing_errors);
break;
case CSPDirectiveName::Sandbox:
- // Note: |ParseSandboxPolicy(...).error_message| is ignored here.
- // Blink's CSP parser is already in charge of displaying it.
+ // Note: Outside of CSP embedded enforcement,
+ // |ParseSandboxPolicy(...).error_message| isn't displayed to the user.
+ // Blink's CSP parser is already in charge of it.
{
auto sandbox = ParseWebSandboxPolicy(directive.second,
mojom::WebSandboxFlags::kNone);
out->sandbox = sandbox.flags;
- out->parsing_errors.emplace_back(std::move(sandbox.error_message));
+ if (!sandbox.error_message.empty())
+ out->parsing_errors.emplace_back(std::move(sandbox.error_message));
}
break;
case CSPDirectiveName::UpgradeInsecureRequests:
out->upgrade_insecure_requests = true;
- if (!directive.second.empty()) {
- out->parsing_errors.emplace_back(base::StringPrintf(
- "The Content Security Policy directive "
- "'upgrade-insecure-requests' should be empty, but was delivered "
- "with a value of '%s'. The directive has been applied, and the "
- "value ignored.",
- directive.second.as_string().c_str()));
- }
+ WarnIfDirectiveValueNotEmpty(directive, out->parsing_errors);
break;
case CSPDirectiveName::TreatAsPublicAddress:
out->treat_as_public_address = true;
- if (!directive.second.empty()) {
- out->parsing_errors.emplace_back(base::StringPrintf(
- "The Content Security Policy directive 'treat-as-public-address' "
- "should be empty, but was delivered with a value of '%s'. The "
- "directive has been applied, and the value ignored.",
- directive.second.as_string().c_str()));
- }
+ WarnIfDirectiveValueNotEmpty(directive, out->parsing_errors);
break;
- case CSPDirectiveName::PluginTypes:
- // If the plugin-types directive is present, then always initialize
- // `out->plugin_types` to be non-null, since only the plugin types
- // explicitly listed will be allowed..
- out->plugin_types =
- ParsePluginTypes(directive.second, out->parsing_errors);
+ case CSPDirectiveName::RequireTrustedTypesFor:
+ out->require_trusted_types_for =
+ ParseRequireTrustedTypesFor(directive.second, out->parsing_errors);
break;
- // We check the following three directives so that we do not trigger a
- // warning because of an unrecognized directive. However, we skip
- // parsing them for now since we do not need these directives here (they
- // are parsed and enforced in the blink CSP parser).
- case CSPDirectiveName::BlockAllMixedContent:
- case CSPDirectiveName::RequireTrustedTypesFor:
case CSPDirectiveName::TrustedTypes:
+ out->trusted_types =
+ ParseTrustedTypes(directive.second, out->parsing_errors);
+ break;
+
+ case CSPDirectiveName::BlockAllMixedContent:
+ out->block_all_mixed_content = true;
+ WarnIfDirectiveValueNotEmpty(directive, out->parsing_errors);
break;
case CSPDirectiveName::ReportTo:
@@ -902,9 +934,6 @@ void AddContentSecurityPolicyFromHeader(base::StringPiece header,
&(out->report_endpoints));
break;
case CSPDirectiveName::Unknown:
- out->parsing_errors.emplace_back(base::StringPrintf(
- "Unrecognized Content-Security-Policy directive '%s'.",
- directive.first.as_string().c_str()));
break;
}
}
@@ -915,7 +944,8 @@ std::pair<CSPDirectiveName, const mojom::CSPSourceList*> GetSourceList(
const mojom::ContentSecurityPolicy& policy) {
for (CSPDirectiveName effective_directive = directive;
effective_directive != CSPDirectiveName::Unknown;
- effective_directive = CSPFallback(effective_directive, directive)) {
+ effective_directive =
+ CSPFallbackDirective(effective_directive, directive)) {
auto value = policy.directives.find(effective_directive);
if (value != policy.directives.end())
return std::make_pair(effective_directive, value->second.get());
@@ -923,57 +953,71 @@ std::pair<CSPDirectiveName, const mojom::CSPSourceList*> GetSourceList(
return std::make_pair(CSPDirectiveName::Unknown, nullptr);
}
-// Check that all plugin-types allowed by the intersection of the policies in
-// |policies_b| are also allowed by |policy_a|.
-bool PluginTypesSubsumes(
- const mojom::ContentSecurityPolicy& policy_a,
- const std::vector<mojom::ContentSecurityPolicyPtr>& policies_b) {
- // Note that `policy->plugin_types == base::nullopt` means all plugin-types
- // are allowed, while if `policy->plugin_types` is the empty vector than no
- // plugin-types are allowed.
-
- if (!policy_a.plugin_types.has_value())
- // |types_a| allows everything.
- return true;
+} // namespace
- if (policies_b.empty())
- return false;
+CSPDirectiveName CSPFallbackDirective(CSPDirectiveName directive,
+ CSPDirectiveName original_directive) {
+ switch (directive) {
+ case CSPDirectiveName::ConnectSrc:
+ case CSPDirectiveName::FontSrc:
+ case CSPDirectiveName::ImgSrc:
+ case CSPDirectiveName::ManifestSrc:
+ case CSPDirectiveName::MediaSrc:
+ case CSPDirectiveName::PrefetchSrc:
+ case CSPDirectiveName::ObjectSrc:
+ case CSPDirectiveName::ScriptSrc:
+ case CSPDirectiveName::StyleSrc:
+ return CSPDirectiveName::DefaultSrc;
- // Compute the intersection of the allowed plugin-types from |policies_b|.
- // First, find the first non-null plugin-types entry in |policies_b|.
- base::Optional<base::flat_set<std::string>> types_b;
- auto it = policies_b.begin();
- for (; it != policies_b.end(); ++it) {
- if ((*it)->plugin_types.has_value()) {
- types_b = base::flat_set<std::string>((*it)->plugin_types.value());
- break;
- }
- }
+ case CSPDirectiveName::ScriptSrcAttr:
+ case CSPDirectiveName::ScriptSrcElem:
+ return CSPDirectiveName::ScriptSrc;
- // If |types_b| is base::nullopt, then no policy in |policies_b| specified
- // any plugin-types, so |policies_b| allows everything.
- if (!types_b.has_value())
- return false;
+ case CSPDirectiveName::StyleSrcAttr:
+ case CSPDirectiveName::StyleSrcElem:
+ return CSPDirectiveName::StyleSrc;
- // Now complete the intersection by considering the remaining policies of
- // |policies_b|.
- for (; it != policies_b.end(); ++it) {
- if ((*it)->plugin_types.has_value()) {
- base::flat_set<std::string> set((*it)->plugin_types.value());
- base::EraseIf(types_b.value(),
- [&set](const auto& type) { return !set.contains(type); });
- }
- }
+ case CSPDirectiveName::FrameSrc:
+ case CSPDirectiveName::WorkerSrc:
+ return CSPDirectiveName::ChildSrc;
- // Check that every plugin-type in |types_b| is allowed by |types_a|.
- return base::ranges::all_of(types_b.value(), [&](const std::string& type_b) {
- return base::ranges::any_of(
- policy_a.plugin_types.value(),
- [&](const std::string& type_a) { return type_a == type_b; });
- });
-}
+ // Because the fallback chain of child-src can be different if we are
+ // checking a worker or a frame request, we need to know the original type
+ // of the request to decide. These are the fallback chains for worker-src
+ // and frame-src specifically.
-} // namespace
+ // worker-src > child-src > script-src > default-src
+ // frame-src > child-src > default-src
+
+ // Since there are some situations and tests that will operate on the
+ // `child-src` directive directly (like for example the EE subsumption
+ // algorithm), we consider the child-src > default-src fallback path as the
+ // "default" and the worker-src fallback path as an exception.
+ case CSPDirectiveName::ChildSrc:
+ if (original_directive == CSPDirectiveName::WorkerSrc)
+ return CSPDirectiveName::ScriptSrc;
+
+ return CSPDirectiveName::DefaultSrc;
+
+ case CSPDirectiveName::BaseURI:
+ case CSPDirectiveName::BlockAllMixedContent:
+ case CSPDirectiveName::DefaultSrc:
+ case CSPDirectiveName::FormAction:
+ case CSPDirectiveName::FrameAncestors:
+ case CSPDirectiveName::NavigateTo:
+ case CSPDirectiveName::ReportTo:
+ case CSPDirectiveName::ReportURI:
+ case CSPDirectiveName::RequireTrustedTypesFor:
+ case CSPDirectiveName::Sandbox:
+ case CSPDirectiveName::TreatAsPublicAddress:
+ case CSPDirectiveName::TrustedTypes:
+ case CSPDirectiveName::UpgradeInsecureRequests:
+ return CSPDirectiveName::Unknown;
+ case CSPDirectiveName::Unknown:
+ NOTREACHED();
+ return CSPDirectiveName::Unknown;
+ }
+}
void AddContentSecurityPolicyFromHeaders(
const net::HttpResponseHeaders& headers,
@@ -1015,9 +1059,6 @@ void AddContentSecurityPolicyFromHeaders(
mojom::AllowCSPFromHeaderValuePtr ParseAllowCSPFromHeader(
const net::HttpResponseHeaders& headers) {
- if (!base::FeatureList::IsEnabled(features::kOutOfBlinkCSPEE))
- return nullptr;
-
std::string allow_csp_from;
if (!headers.GetNormalizedHeader("Allow-CSP-From", &allow_csp_from))
return nullptr;
@@ -1045,6 +1086,8 @@ bool CheckContentSecurityPolicy(const mojom::ContentSecurityPolicyPtr& policy,
CSPContext* context,
const mojom::SourceLocationPtr& source_location,
bool is_form_submission) {
+ DCHECK(policy->self_origin);
+
if (ShouldBypassContentSecurityPolicy(context, directive_name, url))
return true;
@@ -1058,13 +1101,13 @@ bool CheckContentSecurityPolicy(const mojom::ContentSecurityPolicyPtr& policy,
for (CSPDirectiveName effective_directive_name = directive_name;
effective_directive_name != CSPDirectiveName::Unknown;
effective_directive_name =
- CSPFallback(effective_directive_name, directive_name)) {
+ CSPFallbackDirective(effective_directive_name, directive_name)) {
const auto& directive = policy->directives.find(effective_directive_name);
if (directive == policy->directives.end())
continue;
const auto& source_list = directive->second;
- bool allowed = CheckCSPSourceList(source_list, url, context,
+ bool allowed = CheckCSPSourceList(*source_list, url, *(policy->self_origin),
has_followed_redirect, is_response_check);
if (!allowed) {
@@ -1118,28 +1161,23 @@ void UpgradeInsecureRequest(GURL* url) {
bool IsValidRequiredCSPAttr(
const std::vector<mojom::ContentSecurityPolicyPtr>& policy,
const mojom::ContentSecurityPolicy* context,
- const url::Origin& origin,
std::string& error_message) {
DCHECK(policy.size() == 1);
if (!policy[0])
return false;
- if (!policy[0]->parsing_errors.empty()) {
- error_message =
- "Parsing the csp attribute into a Content-Security-Policy returned one "
- "or more parsing errors: " +
- base::JoinString(policy[0]->parsing_errors, " ");
- return false;
- }
-
- if (!policy[0]->report_endpoints.empty()) {
+ if (!policy[0]->report_endpoints.empty() ||
+ // We really don't want any report directives, even with invalid/missing
+ // endpoints.
+ policy[0]->raw_directives.contains(mojom::CSPDirectiveName::ReportURI) ||
+ policy[0]->raw_directives.contains(mojom::CSPDirectiveName::ReportTo)) {
error_message =
"The csp attribute cannot contain the directives 'report-to' or "
"'report-uri'.";
return false;
}
- if (context && !Subsumes(*context, policy, origin)) {
+ if (context && !Subsumes(*context, policy)) {
error_message =
"The csp attribute Content-Security-Policy is not subsumed by the "
"frame's parent csp attribute Content-Security-Policy.";
@@ -1150,19 +1188,19 @@ bool IsValidRequiredCSPAttr(
}
bool Subsumes(const mojom::ContentSecurityPolicy& policy_a,
- const std::vector<mojom::ContentSecurityPolicyPtr>& policies_b,
- const url::Origin& origin_b) {
+ const std::vector<mojom::ContentSecurityPolicyPtr>& policies_b) {
if (policy_a.header->type == mojom::ContentSecurityPolicyType::kReport)
return true;
- if (!PluginTypesSubsumes(policy_a, policies_b))
- return false;
if (policy_a.directives.empty())
return true;
if (policies_b.empty())
return false;
+ // All policies in |policies_b| must have the same self_origin.
+ mojom::CSPSource* origin_b = policies_b[0]->self_origin.get();
+
// A list of directives that we consider for subsumption.
// See more about source lists here:
// https://w3c.github.io/webappsec-csp/#framework-directive-source-list
@@ -1230,8 +1268,6 @@ CSPDirectiveName ToCSPDirectiveName(const std::string& name) {
return CSPDirectiveName::MediaSrc;
if (name == "object-src")
return CSPDirectiveName::ObjectSrc;
- if (name == "plugin-types")
- return CSPDirectiveName::PluginTypes;
if (name == "prefetch-src")
return CSPDirectiveName::PrefetchSrc;
if (name == "report-uri")
@@ -1296,8 +1332,6 @@ std::string ToString(CSPDirectiveName name) {
return "media-src";
case CSPDirectiveName::ObjectSrc:
return "object-src";
- case CSPDirectiveName::PluginTypes:
- return "plugin-types";
case CSPDirectiveName::PrefetchSrc:
return "prefetch-src";
case CSPDirectiveName::ReportURI:
@@ -1337,4 +1371,31 @@ std::string ToString(CSPDirectiveName name) {
return "";
}
+bool AllowsBlanketEnforcementOfRequiredCSP(
+ const url::Origin& request_origin,
+ const GURL& response_url,
+ const network::mojom::AllowCSPFromHeaderValue* allow_csp_from) {
+ if (response_url.SchemeIs(url::kAboutScheme) ||
+ response_url.SchemeIs(url::kDataScheme) || response_url.SchemeIsFile() ||
+ response_url.SchemeIsFileSystem() || response_url.SchemeIsBlob()) {
+ return true;
+ }
+
+ if (request_origin.IsSameOriginWith(url::Origin::Create(response_url)))
+ return true;
+
+ if (!allow_csp_from)
+ return false;
+
+ if (allow_csp_from->is_allow_star())
+ return true;
+
+ if (allow_csp_from->is_origin() &&
+ request_origin.IsSameOriginWith(allow_csp_from->get_origin())) {
+ return true;
+ }
+
+ return false;
+}
+
} // namespace network
diff --git a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.h b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.h
index 3f2eaa6ad10..e420a0277d8 100644
--- a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.h
+++ b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.h
@@ -22,6 +22,14 @@ class HttpResponseHeaders;
namespace network {
class CSPContext;
+// Return the next Content Security Policy directive after |directive| in
+// |original_directive|'s fallback list:
+// https://w3c.github.io/webappsec-csp/#directive-fallback-list.
+COMPONENT_EXPORT(NETWORK_CPP)
+mojom::CSPDirectiveName CSPFallbackDirective(
+ mojom::CSPDirectiveName directive,
+ mojom::CSPDirectiveName original_directive);
+
// Parses the Content-Security-Policy headers specified in |headers| and appends
// the results into |out|.
//
@@ -83,16 +91,13 @@ COMPONENT_EXPORT(NETWORK_CPP)
bool IsValidRequiredCSPAttr(
const std::vector<mojom::ContentSecurityPolicyPtr>& policy,
const mojom::ContentSecurityPolicy* context,
- const url::Origin& url,
std::string& error_message);
-// Checks whether |policy_a| subsumes the policy list
-// |policies_b| with origin |origin_b| according to the algorithm
-// https://w3c.github.io/webappsec-cspee/#subsume-policy-list.
+// Checks whether |policy_a| subsumes the policy list |policies_b| according to
+// the algorithm https://w3c.github.io/webappsec-cspee/#subsume-policy-list.
COMPONENT_EXPORT(NETWORK_CPP)
bool Subsumes(const mojom::ContentSecurityPolicy& policy_a,
- const std::vector<mojom::ContentSecurityPolicyPtr>& policies_b,
- const url::Origin& origin_b);
+ const std::vector<mojom::ContentSecurityPolicyPtr>& policies_b);
COMPONENT_EXPORT(NETWORK_CPP)
mojom::CSPDirectiveName ToCSPDirectiveName(const std::string& name);
@@ -100,6 +105,15 @@ mojom::CSPDirectiveName ToCSPDirectiveName(const std::string& name);
COMPONENT_EXPORT(NETWORK_CPP)
std::string ToString(mojom::CSPDirectiveName name);
+// Return true if the response allows the embedder to enforce arbitrary policy
+// on its behalf.
+// Specification: https://w3c.github.io/webappsec-cspee/#origin-allowed
+COMPONENT_EXPORT(NETWORK_CPP)
+bool AllowsBlanketEnforcementOfRequiredCSP(
+ const url::Origin& request_origin,
+ const GURL& response_url,
+ const network::mojom::AllowCSPFromHeaderValue* allow_csp_from);
+
} // namespace network
#endif // SERVICES_NETWORK_PUBLIC_CPP_CONTENT_SECURITY_POLICY_CONTENT_SECURITY_POLICY_H_
diff --git a/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
index 1913361f19b..36878ad5118 100644
--- a/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
@@ -4,7 +4,8 @@
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "base/stl_util.h"
+#include "base/containers/contains.h"
+#include "base/strings/stringprintf.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
@@ -62,6 +63,9 @@ static void TestFrameAncestorsCSPParser(const std::string& header,
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors->sources.size(),
expected_result->parsed_sources.size());
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ header);
for (size_t i = 0; i < expected_result->parsed_sources.size(); i++) {
EXPECT_EQ(frame_ancestors->sources[i]->scheme,
expected_result->parsed_sources[i].scheme);
@@ -110,6 +114,8 @@ class CSPContextTest : public CSPContext {
mojom::ContentSecurityPolicyPtr EmptyCSP() {
auto policy = mojom::ContentSecurityPolicy::New();
policy->header = mojom::ContentSecurityPolicyHeader::New();
+ policy->self_origin = network::mojom::CSPSource::New(
+ "", "", url::PORT_UNSPECIFIED, "", false, false);
return policy;
}
@@ -267,7 +273,11 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
EXPECT_EQ(2U, policies[0]->directives.size());
+ EXPECT_EQ(2U, policies[0]->raw_directives.size());
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "example.com");
auto& frame_ancestors =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -279,6 +289,8 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
EXPECT_EQ(frame_ancestors->allow_self, false);
+ EXPECT_EQ(policies[0]->raw_directives[mojom::CSPDirectiveName::ScriptSrc],
+ "example2.com");
auto& script_src =
policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc];
EXPECT_EQ(script_src->sources.size(), 1U);
@@ -308,7 +320,11 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
EXPECT_EQ(1U, policies[0]->directives.size());
+ EXPECT_EQ(1U, policies[0]->raw_directives.size());
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "example.org");
auto& frame_ancestors =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -337,6 +353,7 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
EXPECT_TRUE(policies[0]->directives.empty());
+ EXPECT_TRUE(policies[0]->raw_directives.empty());
EXPECT_EQ(1U, policies[0]->parsing_errors.size());
EXPECT_EQ(
@@ -359,9 +376,13 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
EXPECT_EQ(1U, policies[0]->parsing_errors.size());
EXPECT_EQ(
"The value for the Content-Security-Policy directive 'frame-ancestors' "
- "contains one or more invalid characters. Non-whitespace characters "
- "outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC "
- "3986, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1.",
+ "contains one or more invalid characters. In a source expression, "
+ "non-whitespace characters outside ASCII 0x21-0x7E must be "
+ "Punycode-encoded, as described in RFC 3492 "
+ "(https://tools.ietf.org/html/rfc3492), if part of the hostname and "
+ "percent-encoded, as described in RFC 3986, section 2.1 "
+ "(http://tools.ietf.org/html/rfc3986#section-2.1), if part of the "
+ "path.",
policies[0]->parsing_errors[0]);
}
@@ -374,7 +395,11 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
EXPECT_EQ(1U, policies[0]->directives.size());
+ EXPECT_EQ(1U, policies[0]->raw_directives.size());
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "object-src");
auto& frame_ancestors =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -405,7 +430,11 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
EXPECT_EQ(1U, policies[0]->directives.size());
+ EXPECT_EQ(1U, policies[0]->raw_directives.size());
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "http://example.org/index.html?a=b");
auto& frame_ancestors =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -437,7 +466,11 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
EXPECT_EQ(1U, policies[0]->directives.size());
+ EXPECT_EQ(1U, policies[0]->raw_directives.size());
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "http://example.org/index.html#a");
auto& frame_ancestors =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -473,6 +506,14 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
&policies);
EXPECT_EQ(2U, policies.size());
+
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "example.com");
+ EXPECT_EQ(
+ policies[1]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "example.org");
+
auto& frame_ancestors0 =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
auto& frame_ancestors1 =
@@ -509,6 +550,10 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
&policies);
EXPECT_EQ(2U, policies.size());
+ EXPECT_EQ(
+ policies[1]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "example.org");
+
auto& frame_ancestors1 =
policies[1]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors1->sources.size(), 1U);
@@ -535,6 +580,14 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
&policies);
EXPECT_EQ(2U, policies.size());
+
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "example.com");
+ EXPECT_EQ(
+ policies[1]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "example.org");
+
auto& frame_ancestors0 =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
auto& frame_ancestors1 =
@@ -571,6 +624,10 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::FrameAncestors],
+ "example.com");
+
auto& report_endpoints = policies[0]->report_endpoints;
EXPECT_EQ(report_endpoints.size(), 1U);
EXPECT_EQ(report_endpoints[0], "http://example.com/report");
@@ -591,48 +648,140 @@ TEST(ContentSecurityPolicy, ParseDirectives) {
}
TEST(ContentSecurityPolicy, ParsePluginTypes) {
+ std::vector<mojom::ContentSecurityPolicyPtr> policies =
+ ParseCSP("plugin-types application/pdf text/plain");
+ EXPECT_EQ(policies[0]->directives.size(), 0u);
+ EXPECT_EQ(policies[0]->parsing_errors[0],
+ "The Content-Security-Policy directive 'plugin-types' has been "
+ "removed from the "
+ "specification. If you want to block plugins, consider specifying "
+ "\"object-src 'none'\" instead.");
+}
+
+TEST(ContentSecurityPolicy, ParseRequireTrustedTypesFor) {
+ struct {
+ const char* input;
+ const unsigned long errors;
+ network::mojom::CSPRequireTrustedTypesFor expected;
+ } cases[]{
+ {
+ "",
+ 1u,
+ network::mojom::CSPRequireTrustedTypesFor::None,
+ },
+ {
+ "'script'",
+ 0u,
+ network::mojom::CSPRequireTrustedTypesFor::Script,
+ },
+ {
+ "'wasm' 'script'",
+ 1u,
+ network::mojom::CSPRequireTrustedTypesFor::Script,
+ },
+ {
+ "'script' 'wasm' 'script'",
+ 1u,
+ network::mojom::CSPRequireTrustedTypesFor::Script,
+ },
+ {
+ "'wasm'",
+ 2u,
+ network::mojom::CSPRequireTrustedTypesFor::None,
+ },
+ };
+
+ for (const auto& testCase : cases) {
+ std::vector<mojom::ContentSecurityPolicyPtr> policies = ParseCSP(
+ base::StringPrintf("require-trusted-types-for %s", testCase.input));
+ EXPECT_EQ(
+ policies[0]
+ ->raw_directives[mojom::CSPDirectiveName::RequireTrustedTypesFor],
+ testCase.input);
+ EXPECT_EQ(policies[0]->directives.size(), 0u);
+ EXPECT_EQ(policies[0]->parsing_errors.size(), testCase.errors);
+ EXPECT_EQ(policies[0]->require_trusted_types_for, testCase.expected);
+ }
+}
+
+TEST(ContentSecurityPolicy, ParseTrustedTypes) {
{
std::vector<mojom::ContentSecurityPolicyPtr> policies =
- ParseCSP("plugin-types application/pdf text/plain invalid a/a/a");
- EXPECT_EQ(policies[0]->directives.size(), 0u);
- EXPECT_TRUE(policies[0]->plugin_types.has_value());
- EXPECT_EQ(policies[0]->plugin_types.value().size(), 2u);
- EXPECT_EQ(policies[0]->plugin_types.value()[0], "application/pdf");
- EXPECT_EQ(policies[0]->plugin_types.value()[1], "text/plain");
- EXPECT_EQ(policies[0]->parsing_errors.size(), 2u);
- EXPECT_EQ(policies[0]->parsing_errors[0],
- "Invalid plugin type in 'plugin-types' Content Security Policy "
- "directive: 'invalid'.");
- EXPECT_EQ(policies[0]->parsing_errors[1],
- "Invalid plugin type in 'plugin-types' Content Security Policy "
- "directive: 'a/a/a'.");
+ ParseCSP("script-src 'none'");
+ EXPECT_EQ(policies[0]->directives.size(), 1u);
+ EXPECT_FALSE(policies[0]->trusted_types);
}
{
std::vector<mojom::ContentSecurityPolicyPtr> policies =
- ParseCSP("plugin-types ; default-src 'self'");
- EXPECT_TRUE(policies[0]->plugin_types.has_value());
- EXPECT_EQ(policies[0]->plugin_types.value().size(), 0u);
+ ParseCSP("trusted-types 'none'");
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::TrustedTypes],
+ "'none'");
+ EXPECT_EQ(policies[0]->directives.size(), 0u);
+ EXPECT_TRUE(policies[0]->trusted_types);
+ EXPECT_EQ(policies[0]->trusted_types->list.size(), 0u);
+ EXPECT_FALSE(policies[0]->trusted_types->allow_any);
+ EXPECT_FALSE(policies[0]->trusted_types->allow_duplicates);
+ EXPECT_EQ(policies[0]->trusted_types->list.size(), 0u);
EXPECT_EQ(policies[0]->parsing_errors.size(), 0u);
}
{
std::vector<mojom::ContentSecurityPolicyPtr> policies =
- ParseCSP("plugin-types 'self' ; default-src 'self'");
- EXPECT_TRUE(policies[0]->plugin_types.has_value());
- EXPECT_EQ(policies[0]->plugin_types.value().size(), 0u);
- EXPECT_EQ(policies[0]->parsing_errors.size(), 1u);
- EXPECT_EQ(policies[0]->parsing_errors[0],
- "Invalid plugin type in 'plugin-types' Content Security Policy "
- "directive: ''self''.");
+ ParseCSP("trusted-types policy 'none' other_policy@ invalid~policy");
+ EXPECT_EQ(
+ policies[0]->raw_directives[mojom::CSPDirectiveName::TrustedTypes],
+ "policy 'none' other_policy@ invalid~policy");
+ EXPECT_EQ(policies[0]->directives.size(), 0u);
+ EXPECT_TRUE(policies[0]->trusted_types);
+ EXPECT_EQ(policies[0]->trusted_types->list.size(), 2u);
+ EXPECT_EQ(policies[0]->trusted_types->list[0], "policy");
+ EXPECT_EQ(policies[0]->trusted_types->list[1], "other_policy@");
+ EXPECT_FALSE(policies[0]->trusted_types->allow_any);
+ EXPECT_FALSE(policies[0]->trusted_types->allow_duplicates);
+ EXPECT_EQ(policies[0]->parsing_errors.size(), 2u);
+ EXPECT_EQ(
+ policies[0]->parsing_errors[0],
+ "The value of the Content Security Policy directive 'trusted_types' "
+ "contains an invalid policy: 'none'. It will be ignored. "
+ "Note that 'none' has no effect unless it is the only "
+ "expression in the directive value.");
+ EXPECT_EQ(
+ policies[0]->parsing_errors[1],
+ "The value of the Content Security Policy directive 'trusted_types' "
+ "contains an invalid policy: 'invalid~policy'. It will be ignored.");
+ }
+}
+
+TEST(ContentSecurityPolicy, ParseBlockAllMixedContent) {
+ {
+ std::vector<mojom::ContentSecurityPolicyPtr> policies =
+ ParseCSP("script-src 'none'");
+ EXPECT_EQ(policies[0]->directives.size(), 1u);
+ EXPECT_FALSE(policies[0]->block_all_mixed_content);
}
{
std::vector<mojom::ContentSecurityPolicyPtr> policies =
- ParseCSP("default-src 'self'");
- EXPECT_FALSE(policies[0]->plugin_types.has_value());
+ ParseCSP("block-all-mixed-content");
+ EXPECT_EQ(policies[0]->directives.size(), 0u);
+ EXPECT_TRUE(policies[0]->block_all_mixed_content);
EXPECT_EQ(policies[0]->parsing_errors.size(), 0u);
}
+
+ {
+ std::vector<mojom::ContentSecurityPolicyPtr> policies =
+ ParseCSP("block-all-mixed-content true");
+ EXPECT_EQ(policies[0]->directives.size(), 0u);
+ EXPECT_TRUE(policies[0]->block_all_mixed_content);
+ EXPECT_EQ(policies[0]->parsing_errors.size(), 1u);
+ EXPECT_EQ(policies[0]->parsing_errors[0],
+ "The Content Security Policy directive "
+ "'block-all-mixed-content' should be empty, but was delivered "
+ "with a value of 'true'. The directive has been applied, and the "
+ "value ignored.");
+ }
}
TEST(ContentSecurityPolicy, ParseReportEndpoint) {
@@ -703,6 +852,40 @@ TEST(ContentSecurityPolicy, ParseReportEndpoint) {
}
}
+TEST(ContentSecurityPolicy, ParseStoresSelfOrigin) {
+ struct {
+ const char* url;
+ network::mojom::CSPSourcePtr self_origin;
+ } testCases[]{
+ {
+ "https://example.com",
+ network::mojom::CSPSource::New("https", "example.com", 443, "", false,
+ false),
+ },
+ {
+ "http://example.com/main/index.html",
+ network::mojom::CSPSource::New("http", "example.com", 80, "", false,
+ false),
+ },
+ {
+ "file://localhost/var/www/index.html",
+ network::mojom::CSPSource::New("file", "", url::PORT_UNSPECIFIED, "",
+ false, false),
+ },
+ };
+
+ for (const auto& testCase : testCases) {
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy", "default-src 'none'");
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL(testCase.url),
+ &policies);
+
+ EXPECT_TRUE(testCase.self_origin.Equals(policies[0]->self_origin));
+ }
+}
+
// Check URL are upgraded iif "upgrade-insecure-requests" directive is defined.
TEST(ContentSecurityPolicy, ShouldUpgradeInsecureRequest) {
std::vector<mojom::ContentSecurityPolicyPtr> policies;
@@ -958,7 +1141,6 @@ TEST(ContentSecurityPolicy, NavigateToChecks) {
csp->allow_response_redirects = true;
return csp;
};
- context.SetSelf(source_a());
struct TestCase {
mojom::CSPSourceListPtr navigate_to_list;
@@ -997,6 +1179,7 @@ TEST(ContentSecurityPolicy, NavigateToChecks) {
for (auto& test : cases) {
auto policy = EmptyCSP();
+ policy->self_origin = source_a().Clone();
policy->directives[CSPDirectiveName::NavigateTo] =
std::move(test.navigate_to_list);
@@ -1024,6 +1207,8 @@ TEST(ContentSecurityPolicy, ParseSandbox) {
std::vector<mojom::ContentSecurityPolicyPtr> policies;
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
+ EXPECT_EQ(policies[0]->raw_directives[mojom::CSPDirectiveName::Sandbox],
+ "allow-downloads allow-scripts");
EXPECT_EQ(policies[0]->sandbox,
~mojom::WebSandboxFlags::kDownloads &
~mojom::WebSandboxFlags::kScripts &
@@ -1033,13 +1218,13 @@ TEST(ContentSecurityPolicy, ParseSandbox) {
TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
struct TestCase {
std::string directive_value;
- base::Callback<mojom::CSPSourceListPtr()> expected;
+ base::OnceCallback<mojom::CSPSourceListPtr()> expected;
std::string expected_error;
} cases[] = {
{
"'nonce-a' 'nonce-a=' 'nonce-a==' 'nonce-a===' 'nonce-==' 'nonce-' "
"'nonce 'nonce-cde' 'nonce-cde=' 'nonce-cde==' 'nonce-cde==='",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->nonces.push_back("a");
csp->nonces.push_back("a=");
@@ -1052,37 +1237,28 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
"",
},
{
- "'sha256-abc' 'sha256-ABC' 'sha256 'sha256-' 'sha384-abc' "
- "'sha512-abc' 'sha-abc' 'sha256-*' 'sha-256-cde' 'sha-384-cde' "
- "'sha-512-cde'",
- base::Bind([] {
+ "'sha256-YWJj' 'nonce-cde' 'sha256-QUJD'",
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
- csp->hashes.push_back(mojom::CSPHashSource::New(
- mojom::CSPHashAlgorithm::SHA256, "abc"));
- csp->hashes.push_back(mojom::CSPHashSource::New(
- mojom::CSPHashAlgorithm::SHA256, "ABC"));
- csp->hashes.push_back(mojom::CSPHashSource::New(
- mojom::CSPHashAlgorithm::SHA384, "abc"));
- csp->hashes.push_back(mojom::CSPHashSource::New(
- mojom::CSPHashAlgorithm::SHA512, "abc"));
- csp->hashes.push_back(mojom::CSPHashSource::New(
- mojom::CSPHashAlgorithm::SHA256, "cde"));
- csp->hashes.push_back(mojom::CSPHashSource::New(
- mojom::CSPHashAlgorithm::SHA384, "cde"));
- csp->hashes.push_back(mojom::CSPHashSource::New(
- mojom::CSPHashAlgorithm::SHA512, "cde"));
+ csp->hashes.push_back(
+ mojom::CSPHashSource::New(mojom::CSPHashAlgorithm::SHA256,
+ std::vector<uint8_t>{'a', 'b', 'c'}));
+ csp->hashes.push_back(
+ mojom::CSPHashSource::New(mojom::CSPHashAlgorithm::SHA256,
+ std::vector<uint8_t>{'A', 'B', 'C'}));
+ csp->nonces.push_back("cde");
return csp;
}),
"",
},
{
"'none' ",
- base::Bind([] { return mojom::CSPSourceList::New(); }),
+ base::BindOnce([] { return mojom::CSPSourceList::New(); }),
"",
},
{
"'none' 'self'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_self = true;
return csp;
@@ -1094,7 +1270,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'self' 'none'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_self = true;
return csp;
@@ -1106,7 +1282,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'self'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_self = true;
return csp;
@@ -1114,7 +1290,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'wrong' *",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_star = true;
return csp;
@@ -1124,7 +1300,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'wrong' 'unsafe-inline'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_inline = true;
return csp;
@@ -1134,7 +1310,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'wrong' 'unsafe-eval'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_eval = true;
return csp;
@@ -1144,7 +1320,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'wrong' 'wasm-eval'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_wasm_eval = true;
return csp;
@@ -1154,7 +1330,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'wrong' 'strict-dynamic'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_dynamic = true;
return csp;
@@ -1164,7 +1340,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'wrong' 'unsafe-hashes'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->allow_unsafe_hashes = true;
return csp;
@@ -1174,7 +1350,7 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
},
{
"'wrong' 'report-sample'",
- base::Bind([] {
+ base::BindOnce([] {
auto csp = mojom::CSPSourceList::New();
csp->report_sample = true;
return csp;
@@ -1193,27 +1369,86 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
std::vector<mojom::ContentSecurityPolicyPtr> policies;
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
- EXPECT_TRUE(test.expected.Run().Equals(
- policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc]));
+ EXPECT_TRUE(
+ std::move(test.expected)
+ .Run()
+ .Equals(
+ policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc]));
+
+ EXPECT_EQ(policies[0]->raw_directives[mojom::CSPDirectiveName::ScriptSrc],
+ base::TrimString(test.directive_value, " ", base::TRIM_ALL)
+ .as_string());
if (!test.expected_error.empty())
EXPECT_EQ(test.expected_error, policies[0]->parsing_errors[0]);
}
}
+TEST(ContentSecurityPolicy, ParseHash) {
+ using Algo = mojom::CSPHashAlgorithm;
+ struct TestCase {
+ std::string hash;
+ Algo expected_algorithm;
+ std::vector<uint8_t> expected_hash;
+ } cases[] = {
+ // For this test, we have the following base64 encoding:
+ // abc => YWJj ABC => QUJD cd => Y2Q= abcd => YWJjZA==
+ // We also test base64 without padding.
+ {"'sha256-YWJj'", Algo::SHA256, {'a', 'b', 'c'}},
+ {"'sha256-QUJD'", Algo::SHA256, {'A', 'B', 'C'}},
+ {"'sha256", Algo::None, {}},
+ {"'sha256-'", Algo::None, {}},
+ {"'sha384-YWJj'", Algo::SHA384, {'a', 'b', 'c'}},
+ {"'sha512-YWJjZA'", Algo::SHA512, {'a', 'b', 'c', 'd'}},
+ {"'sha-YWJj'", Algo::None, {}},
+ {"'sha256-*'", Algo::None, {}},
+ {"'sha-256-Y2Q'", Algo::SHA256, {'c', 'd'}},
+ {"'sha-384-Y2Q='", Algo::SHA384, {'c', 'd'}},
+ {"'sha-512-Y2Q='", Algo::SHA512, {'c', 'd'}},
+ // "ABCDE" is not valid base64 and should be ignored.
+ {"'sha256-ABCDE'", Algo::None, {}},
+ {"'sha256--__'", Algo::SHA256, {0xfb, 0xff}},
+ {"'sha256-++/'", Algo::SHA256, {0xfb, 0xef}},
+ // Other invalid hashes should be ignored.
+ {"'sha256-YWJj", Algo::None, {}},
+ {"'sha111-YWJj'", Algo::None, {}},
+ {"'sha256-ABC('", Algo::None, {}},
+ };
+
+ for (auto& test : cases) {
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy", "script-src " + test.hash);
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+ &policies);
+ const std::vector<mojom::CSPHashSourcePtr>& hashes =
+ policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc]->hashes;
+ if (test.expected_algorithm != Algo::None) {
+ EXPECT_EQ(1u, hashes.size()) << test.hash << " should parse to one hash";
+ EXPECT_EQ(test.expected_algorithm, hashes[0]->algorithm)
+ << test.hash << " should have algorithm " << test.expected_algorithm;
+ EXPECT_EQ(test.expected_hash, hashes[0]->value)
+ << test.hash << " has not been base64decoded correctly";
+ } else {
+ EXPECT_TRUE(hashes.empty()) << test.hash << " should be an invalid hash";
+ }
+ }
+}
+
TEST(ContentSecurityPolicy, IsValidRequiredCSPAttr) {
struct TestCase {
const char* csp;
bool expected;
std::string expected_error;
- } cases[] = {{"script-src 'none'", true, ""},
- {"script-src 'none'; invalid-directive", false,
- "Parsing the csp attribute into a Content-Security-Policy "
- "returned one or more parsing errors: Unrecognized "
- "Content-Security-Policy directive 'invalid-directive'."},
- {"script-src 'none'; report-uri https://www.example.com", false,
- "The csp attribute cannot contain the directives 'report-to' "
- "or 'report-uri'."}};
+ } cases[] = {
+ {" script-src 'none' https://www.google.com ;; ; invalid-directive "
+ "invalid-value ;",
+ true, ""},
+ {"script-src 'none'; report-uri https://www.example.com", false,
+ "The csp attribute cannot contain the directives 'report-to' "
+ "or 'report-uri'."},
+ };
for (auto& test : cases) {
SCOPED_TRACE(test.csp);
@@ -1223,11 +1458,14 @@ TEST(ContentSecurityPolicy, IsValidRequiredCSPAttr) {
required_csp_headers->SetHeader("Content-Security-Policy", test.csp);
AddContentSecurityPolicyFromHeaders(*required_csp_headers,
GURL("https://example.com/"), &csp);
+
+ // Overwrite the header_value artificially. At the moment, our header parser
+ // takes already care of some parts (like removing commas). But we want to
+ // be sure that header values with commas or other invalid header values are
+ // blocked by our validation mechanism anyway.
+ csp[0]->header->header_value = test.csp;
std::string out;
- EXPECT_EQ(
- test.expected,
- IsValidRequiredCSPAttr(
- csp, nullptr, url::Origin::Create(GURL("https://a.com")), out));
+ EXPECT_EQ(test.expected, IsValidRequiredCSPAttr(csp, nullptr, out));
EXPECT_EQ(test.expected_error, out);
}
}
@@ -1277,9 +1515,7 @@ TEST(ContentSecurityPolicy, Subsumes) {
std::vector<mojom::ContentSecurityPolicyPtr> returned_csp;
AddContentSecurityPolicyFromHeaders(
*returned_csp_headers, GURL("https://example.com/"), &returned_csp);
- EXPECT_EQ(test.expected,
- Subsumes(*required_csp[0], returned_csp,
- url::Origin::Create(GURL("https://a.com"))))
+ EXPECT_EQ(test.expected, Subsumes(*required_csp[0], returned_csp))
<< test.name;
}
}
@@ -1343,16 +1579,13 @@ TEST(ContentSecurityPolicy, SubsumesBasedOnCSPSourcesOnly) {
for (const auto& test : cases) {
std::vector<mojom::ContentSecurityPolicyPtr> policies_b =
ParseCSP(test.policies);
- EXPECT_EQ(Subsumes(*policy_a[0], policies_b,
- url::Origin::Create(GURL("https://a.com"))),
- test.expected)
+ EXPECT_EQ(Subsumes(*policy_a[0], policies_b), test.expected)
<< csp_a << " should " << (test.expected ? "" : "not ") << "subsume "
<< test.policies;
if (!policies_b.empty()) {
// Check if first policy of `listB` subsumes `A`.
- EXPECT_EQ(Subsumes(*policies_b[0], policy_a,
- url::Origin::Create(GURL("https://a.com"))),
+ EXPECT_EQ(Subsumes(*policies_b[0], policy_a),
test.expected_first_policy_opposite)
<< csp_a << " should "
<< (test.expected_first_policy_opposite ? "" : "not ") << "subsume "
@@ -1441,81 +1674,7 @@ TEST(ContentSecurityPolicy, SubsumesIfNoneIsPresent) {
ParseCSP(test.policy_a);
std::vector<mojom::ContentSecurityPolicyPtr> policies_b =
ParseCSP(test.policies_b);
- EXPECT_EQ(Subsumes(*policy_a[0], policies_b,
- url::Origin::Create(GURL("https://a.com"))),
- test.expected)
- << test.policy_a << " should " << (test.expected ? "" : "not ")
- << "subsume " << test.policies_b;
- }
-}
-
-TEST(ContentSecurityPolicy, SubsumesPluginTypes) {
- struct TestCase {
- const char* policy_a;
- const char* policies_b;
- bool expected;
- } cases[] = {
- // `policyA` subsumes `policiesB`.
- {"script-src 'unsafe-inline'",
- "script-src , script-src http://example.com, plugin-types text/plain",
- true},
- {"script-src http://example.com",
- "script-src http://example.com; plugin-types ", true},
- {"script-src http://example.com",
- "script-src http://example.com; plugin-types text/plain", true},
- {"script-src http://example.com; plugin-types text/plain",
- "script-src http://example.com; plugin-types text/plain", true},
- {"script-src http://example.com; plugin-types text/plain",
- "script-src http://example.com; plugin-types ", true},
- {"script-src http://example.com; plugin-types text/plain",
- "script-src http://example.com; plugin-types , plugin-types ", true},
- {"plugin-types application/pdf text/plain",
- "plugin-types application/pdf text/plain, plugin-types "
- "application/x-blink-test-plugin",
- true},
- {"plugin-types application/pdf text/plain",
- "plugin-types application/pdf text/plain,"
- "plugin-types application/pdf text/plain "
- "application/x-blink-test-plugin",
- true},
- {"plugin-types application/x-shockwave-flash application/pdf text/plain",
- "plugin-types application/x-shockwave-flash application/pdf text/plain, "
- "plugin-types application/x-shockwave-flash",
- true},
- {"plugin-types application/x-shockwave-flash",
- "plugin-types application/x-shockwave-flash application/pdf text/plain, "
- "plugin-types application/x-shockwave-flash",
- true},
- // `policyA` does not subsume `policiesB`.
- {"script-src http://example.com; plugin-types text/plain", "", false},
- {"script-src http://example.com; plugin-types text/plain",
- "script-src http://example.com", false},
- {"plugin-types random-value",
- "script-src 'unsafe-inline', plugin-types text/plain", false},
- {"plugin-types random-value",
- "script-src http://example.com, script-src http://example.com", false},
- {"plugin-types random-value",
- "plugin-types text/plain, plugin-types text/plain", false},
- {"script-src http://example.com; plugin-types text/plain",
- "plugin-types , plugin-types ", false},
- {"plugin-types application/pdf text/plain",
- "plugin-types application/x-blink-test-plugin,"
- "plugin-types application/x-blink-test-plugin",
- false},
- {"plugin-types application/pdf text/plain",
- "plugin-types application/pdf application/x-blink-test-plugin, "
- "plugin-types application/x-blink-test-plugin",
- false},
- };
-
- for (const auto& test : cases) {
- std::vector<mojom::ContentSecurityPolicyPtr> policy_a =
- ParseCSP(test.policy_a);
- std::vector<mojom::ContentSecurityPolicyPtr> policies_b =
- ParseCSP(test.policies_b);
- EXPECT_EQ(Subsumes(*policy_a[0], policies_b,
- url::Origin::Create(GURL("https://a.com"))),
- test.expected)
+ EXPECT_EQ(Subsumes(*policy_a[0], policies_b), test.expected)
<< test.policy_a << " should " << (test.expected ? "" : "not ")
<< "subsume " << test.policies_b;
}
@@ -1556,4 +1715,120 @@ TEST(ContentSecurityPolicy, InvalidPolicyInReportTreatAsPublicAddress) {
policy->parsing_errors[0]);
}
+TEST(ContentSecurityPolicy, AllowsBlanketEnforcementOfRequiredCSP) {
+ struct TestCase {
+ const char* name;
+ const char* request_origin;
+ const char* response_origin;
+ const char* allow_csp_from;
+ bool expected_result;
+ } cases[] = {
+ {
+ "About scheme allows",
+ "http://example.com",
+ "about://me",
+ nullptr,
+ true,
+ },
+ {
+ "File scheme allows",
+ "http://example.com",
+ "file://me",
+ nullptr,
+ true,
+ },
+ {
+ "Data scheme allows",
+ "http://example.com",
+ "data://me",
+ nullptr,
+ true,
+ },
+ {
+ "Filesystem scheme allows",
+ "http://example.com",
+ "filesystem://me",
+ nullptr,
+ true,
+ },
+ {
+ "Blob scheme allows",
+ "http://example.com",
+ "blob://me",
+ nullptr,
+ true,
+ },
+ {
+ "Same origin allows",
+ "http://example.com",
+ "http://example.com",
+ nullptr,
+ true,
+ },
+ {
+ "Same origin allows independently of header",
+ "http://example.com",
+ "http://example.com",
+ "http://not-example.com",
+ true,
+ },
+ {
+ "Different origin does not allow",
+ "http://example.com",
+ "http://not.example.com",
+ nullptr,
+ false,
+ },
+ {
+ "Different origin with right header allows",
+ "http://example.com",
+ "http://not-example.com",
+ "http://example.com",
+ true,
+ },
+ {
+ "Different origin with right header 2 allows",
+ "http://example.com",
+ "http://not-example.com",
+ "http://example.com/",
+ true,
+ },
+ {
+ "Different origin with wrong header does not allow",
+ "http://example.com",
+ "http://not-example.com",
+ "http://not-example.com",
+ false,
+ },
+ {
+ "Wildcard header allows",
+ "http://example.com",
+ "http://not-example.com",
+ "*",
+ true,
+ },
+ {
+ "Malformed header does not allow",
+ "http://example.com",
+ "http://not-example.com",
+ "*; http://example.com",
+ false,
+ },
+ };
+
+ for (const auto& test : cases) {
+ SCOPED_TRACE(test.name);
+ auto headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
+ if (test.allow_csp_from)
+ headers->AddHeader("allow-csp-from", test.allow_csp_from);
+ auto allow_csp_from = network::ParseAllowCSPFromHeader(*headers);
+
+ bool actual = AllowsBlanketEnforcementOfRequiredCSP(
+ url::Origin::Create(GURL(test.request_origin)),
+ GURL(test.response_origin), allow_csp_from.get());
+ EXPECT_EQ(test.expected_result, actual);
+ }
+}
+
} // namespace network
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_context.cc b/chromium/services/network/public/cpp/content_security_policy/csp_context.cc
index ee5a5d548c5..a1ee0020048 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_context.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_context.cc
@@ -3,9 +3,10 @@
// found in the LICENSE file.
#include "services/network/public/cpp/content_security_policy/csp_context.h"
-#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "url/origin.h"
+#include "base/containers/contains.h"
+#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
+#include "url/url_util.h"
namespace network {
@@ -53,34 +54,16 @@ bool CSPContext::IsAllowedByCsp(mojom::CSPDirectiveName directive_name,
return allow;
}
-void CSPContext::SetSelf(const url::Origin& origin) {
- self_source_.reset();
-
- // When the origin is unique, no URL should match with 'self'. That's why
- // |self_source_| stays undefined here.
- if (origin.opaque())
- return;
-
- if (origin.scheme() == url::kFileScheme) {
- self_source_ = mojom::CSPSource::New(
- url::kFileScheme, "", url::PORT_UNSPECIFIED, "", false, false);
- return;
- }
-
- self_source_ = mojom::CSPSource::New(
- origin.scheme(), origin.host(),
- origin.port() == 0 ? url::PORT_UNSPECIFIED : origin.port(), "", false,
- false);
-
- DCHECK_NE("", self_source_->scheme);
-}
-
-void CSPContext::SetSelf(mojom::CSPSourcePtr self_source) {
- self_source_ = std::move(self_source);
-}
-
bool CSPContext::SchemeShouldBypassCSP(const base::StringPiece& scheme) {
- return false;
+ // Blink uses its SchemeRegistry to check if a scheme should be bypassed.
+ // It can't be used on the browser process. It is used for two things:
+ // 1) Bypassing the "chrome-extension" scheme when chrome is built with the
+ // extensions support.
+ // 2) Bypassing arbitrary scheme for testing purpose only in blink and in V8.
+ // TODO(arthursonzogni): url::GetBypassingCSPScheme() is used instead of the
+ // blink::SchemeRegistry. It contains 1) but not 2).
+ const auto& bypassing_schemes = url::GetCSPBypassingSchemes();
+ return base::Contains(bypassing_schemes, scheme);
}
void CSPContext::SanitizeDataForUseInCspViolation(
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_context.h b/chromium/services/network/public/cpp/content_security_policy/csp_context.h
index 968b39daeb3..4f9fd68ac03 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_context.h
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_context.h
@@ -9,10 +9,6 @@
class GURL;
-namespace url {
-class Origin;
-}
-
namespace network {
// A CSPContext represents the Document where the Content-Security-Policy are
@@ -75,6 +71,8 @@ class COMPONENT_EXPORT(NETWORK_CPP) CSPContext {
// HTTPS) according to the CSP.
bool ShouldModifyRequestUrlForCsp(bool is_subresource_or_form_submssion);
+ // This is declared virtual only so that it can be overridden for unit
+ // testing.
virtual bool SchemeShouldBypassCSP(const base::StringPiece& scheme);
// TODO(arthursonzogni): This is an interface. Stop storing object in it.
@@ -87,20 +85,8 @@ class COMPONENT_EXPORT(NETWORK_CPP) CSPContext {
return policies_;
}
- void SetSelf(const url::Origin& origin);
- void SetSelf(mojom::CSPSourcePtr self_source);
-
- // When a CSPSourceList contains 'self', the url is allowed when it match the
- // CSPSource returned by this function.
- // Sometimes there is no 'self' source. It means that the current origin is
- // unique and no urls will match 'self' whatever they are.
- // Note: When there is a 'self' source, its scheme is guaranteed to be
- // non-empty.
- const mojom::CSPSourcePtr& self_source() { return self_source_; }
-
private:
// TODO(arthursonzogni): This is an interface. Stop storing object in it.
- mojom::CSPSourcePtr self_source_; // Nullable.
std::vector<mojom::ContentSecurityPolicyPtr> policies_;
};
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
index 39168c0b5a3..151bec3d684 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
@@ -66,19 +66,22 @@ mojom::ContentSecurityPolicyPtr EmptyCSP() {
}
// Build a new policy made of only one directive and no report endpoints.
-mojom::ContentSecurityPolicyPtr BuildPolicy(CSPDirectiveName directive_name,
+mojom::ContentSecurityPolicyPtr BuildPolicy(mojom::CSPSourcePtr self_source,
+ CSPDirectiveName directive_name,
mojom::CSPSourcePtr source) {
auto source_list = mojom::CSPSourceList::New();
source_list->sources.push_back(std::move(source));
auto policy = EmptyCSP();
policy->directives[directive_name] = std::move(source_list);
+ policy->self_origin = std::move(self_source);
return policy;
}
// Build a new policy made of only one directive and no report endpoints.
-mojom::ContentSecurityPolicyPtr BuildPolicy(CSPDirectiveName directive_name,
+mojom::ContentSecurityPolicyPtr BuildPolicy(mojom::CSPSourcePtr self_source,
+ CSPDirectiveName directive_name,
mojom::CSPSourcePtr source_1,
mojom::CSPSourcePtr source_2) {
auto source_list = mojom::CSPSourceList::New();
@@ -87,6 +90,7 @@ mojom::ContentSecurityPolicyPtr BuildPolicy(CSPDirectiveName directive_name,
auto policy = EmptyCSP();
policy->directives[directive_name] = std::move(source_list);
+ policy->self_origin = std::move(self_source);
return policy;
}
@@ -104,8 +108,11 @@ network::mojom::SourceLocationPtr SourceLocation() {
TEST(CSPContextTest, SchemeShouldBypassCSP) {
CSPContextTest context;
- context.AddContentSecurityPolicy(BuildPolicy(
- CSPDirectiveName::DefaultSrc, BuildCSPSource("", "example.com")));
+ auto self_source = network::mojom::CSPSource::New("http", "example.com", 80,
+ "", false, false);
+ context.AddContentSecurityPolicy(
+ BuildPolicy(self_source.Clone(), CSPDirectiveName::DefaultSrc,
+ BuildCSPSource("", "example.com")));
EXPECT_FALSE(context.IsAllowedByCsp(
CSPDirectiveName::FrameSrc, GURL("data:text/html,<html></html>"), false,
@@ -120,14 +127,15 @@ TEST(CSPContextTest, SchemeShouldBypassCSP) {
TEST(CSPContextTest, MultiplePolicies) {
CSPContextTest context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
+ auto self_source = network::mojom::CSPSource::New("http", "example.com", 80,
+ "", false, false);
- context.AddContentSecurityPolicy(BuildPolicy(CSPDirectiveName::FrameSrc,
- BuildCSPSource("", "a.com"),
- BuildCSPSource("", "b.com")));
- context.AddContentSecurityPolicy(BuildPolicy(CSPDirectiveName::FrameSrc,
- BuildCSPSource("", "a.com"),
- BuildCSPSource("", "c.com")));
+ context.AddContentSecurityPolicy(
+ BuildPolicy(self_source.Clone(), CSPDirectiveName::FrameSrc,
+ BuildCSPSource("", "a.com"), BuildCSPSource("", "b.com")));
+ context.AddContentSecurityPolicy(
+ BuildPolicy(self_source.Clone(), CSPDirectiveName::FrameSrc,
+ BuildCSPSource("", "a.com"), BuildCSPSource("", "c.com")));
EXPECT_TRUE(context.IsAllowedByCsp(
CSPDirectiveName::FrameSrc, GURL("http://a.com"), false, false,
@@ -145,11 +153,12 @@ TEST(CSPContextTest, MultiplePolicies) {
TEST(CSPContextTest, SanitizeDataForUseInCspViolation) {
CSPContextTest context;
- context.SetSelf(url::Origin::Create(GURL("http://a.com")));
+ auto self_source =
+ network::mojom::CSPSource::New("http", "a.com", 80, "", false, false);
// Content-Security-Policy: frame-src "a.com/iframe"
context.AddContentSecurityPolicy(
- BuildPolicy(CSPDirectiveName::FrameSrc,
+ BuildPolicy(self_source.Clone(), CSPDirectiveName::FrameSrc,
mojom::CSPSource::New("", "a.com", url::PORT_UNSPECIFIED,
"/iframe", false, false)));
@@ -196,14 +205,18 @@ TEST(CSPContextTest, SanitizeDataForUseInCspViolation) {
// When several policies are infringed, all of them must be reported.
TEST(CSPContextTest, MultipleInfringement) {
CSPContextTest context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
-
- context.AddContentSecurityPolicy(
- BuildPolicy(CSPDirectiveName::FrameSrc, BuildCSPSource("", "a.com")));
- context.AddContentSecurityPolicy(
- BuildPolicy(CSPDirectiveName::FrameSrc, BuildCSPSource("", "b.com")));
- context.AddContentSecurityPolicy(
- BuildPolicy(CSPDirectiveName::FrameSrc, BuildCSPSource("", "c.com")));
+ auto self_source = network::mojom::CSPSource::New("http", "example.com", 80,
+ "", false, false);
+
+ context.AddContentSecurityPolicy(BuildPolicy(self_source.Clone(),
+ CSPDirectiveName::FrameSrc,
+ BuildCSPSource("", "a.com")));
+ context.AddContentSecurityPolicy(BuildPolicy(self_source.Clone(),
+ CSPDirectiveName::FrameSrc,
+ BuildCSPSource("", "b.com")));
+ context.AddContentSecurityPolicy(BuildPolicy(self_source.Clone(),
+ CSPDirectiveName::FrameSrc,
+ BuildCSPSource("", "c.com")));
EXPECT_FALSE(context.IsAllowedByCsp(
CSPDirectiveName::FrameSrc, GURL("http://c.com"), false, false,
@@ -222,13 +235,17 @@ TEST(CSPContextTest, MultipleInfringement) {
// Tests that the CheckCSPDisposition parameter is obeyed.
TEST(CSPContextTest, CheckCSPDisposition) {
CSPContextTest context;
+ auto self_source = network::mojom::CSPSource::New("http", "example.com", 80,
+ "", false, false);
// Add an enforced policy.
- auto enforce_csp = BuildPolicy(CSPDirectiveName::FrameSrc,
- BuildCSPSource("", "example.com"));
+ auto enforce_csp =
+ BuildPolicy(self_source.Clone(), CSPDirectiveName::FrameSrc,
+ BuildCSPSource("", "example.com"));
// Add a report-only policy.
- auto report_only_csp = BuildPolicy(CSPDirectiveName::DefaultSrc,
- BuildCSPSource("", "example.com"));
+ auto report_only_csp =
+ BuildPolicy(self_source.Clone(), CSPDirectiveName::DefaultSrc,
+ BuildCSPSource("", "example.com"));
report_only_csp->header->type = mojom::ContentSecurityPolicyType::kReport;
context.AddContentSecurityPolicy(std::move(enforce_csp));
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source.cc b/chromium/services/network/public/cpp/content_security_policy/csp_source.cc
index 70a11e6550b..3fe19c79071 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source.cc
@@ -9,7 +9,6 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "url/url_canon.h"
#include "url/url_util.h"
@@ -18,8 +17,8 @@ namespace network {
namespace {
-bool HasHost(const mojom::CSPSourcePtr& source) {
- return !source->host.empty() || source->is_host_wildcard;
+bool HasHost(const mojom::CSPSource& source) {
+ return !source.host.empty() || source.is_host_wildcard;
}
bool DecodePath(const base::StringPiece& path, std::string* output) {
@@ -55,66 +54,65 @@ SchemeMatchingResult MatchScheme(const std::string& scheme_a,
return SchemeMatchingResult::NotMatching;
}
-SchemeMatchingResult SourceAllowScheme(const mojom::CSPSourcePtr& source,
+SchemeMatchingResult SourceAllowScheme(const mojom::CSPSource& source,
const GURL& url,
- CSPContext* context) {
+ const mojom::CSPSource& self_source) {
// The source doesn't specify a scheme and the current origin is unique. In
// this case, the url doesn't match regardless of its scheme.
- if (source->scheme.empty() && !context->self_source())
+ if (source.scheme.empty() && self_source.scheme.empty())
return SchemeMatchingResult::NotMatching;
// |allowed_scheme| is guaranteed to be non-empty.
const std::string& allowed_scheme =
- source->scheme.empty() ? context->self_source()->scheme : source->scheme;
+ source.scheme.empty() ? self_source.scheme : source.scheme;
return MatchScheme(allowed_scheme, url.scheme());
}
-bool SourceAllowHost(const mojom::CSPSourcePtr& source,
- const std::string& host) {
- if (source->is_host_wildcard) {
- if (source->host.empty())
+bool SourceAllowHost(const mojom::CSPSource& source, const std::string& host) {
+ if (source.is_host_wildcard) {
+ if (source.host.empty())
return true;
// TODO(arthursonzogni): Chrome used to, incorrectly, match *.x.y to x.y.
// The renderer version of this function counts how many times it happens.
// It might be useful to do it outside of blink too.
// See third_party/blink/renderer/core/frame/csp/csp_source.cc
- return base::EndsWith(host, '.' + source->host,
+ return base::EndsWith(host, '.' + source.host,
base::CompareCase::INSENSITIVE_ASCII);
} else {
- return base::EqualsCaseInsensitiveASCII(host, source->host);
+ return base::EqualsCaseInsensitiveASCII(host, source.host);
}
}
-bool SourceAllowHost(const mojom::CSPSourcePtr& source, const GURL& url) {
+bool SourceAllowHost(const mojom::CSPSource& source, const GURL& url) {
return SourceAllowHost(source, url.host());
}
-PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source,
+PortMatchingResult SourceAllowPort(const mojom::CSPSource& source,
int port,
const std::string& scheme) {
- if (source->is_port_wildcard)
+ if (source.is_port_wildcard)
return PortMatchingResult::MatchingWildcard;
- if (source->port == port) {
- if (source->port == url::PORT_UNSPECIFIED)
+ if (source.port == port) {
+ if (source.port == url::PORT_UNSPECIFIED)
return PortMatchingResult::MatchingWildcard;
return PortMatchingResult::MatchingExact;
}
- if (source->port == url::PORT_UNSPECIFIED) {
+ if (source.port == url::PORT_UNSPECIFIED) {
if (DefaultPortForScheme(scheme) == port)
return PortMatchingResult::MatchingWildcard;
}
if (port == url::PORT_UNSPECIFIED) {
- if (source->port == DefaultPortForScheme(scheme))
+ if (source.port == DefaultPortForScheme(scheme))
return PortMatchingResult::MatchingWildcard;
}
- int source_port = source->port;
+ int source_port = source.port;
if (source_port == url::PORT_UNSPECIFIED)
- source_port = DefaultPortForScheme(source->scheme);
+ source_port = DefaultPortForScheme(source.scheme);
if (port == url::PORT_UNSPECIFIED)
port = DefaultPortForScheme(scheme);
@@ -125,13 +123,12 @@ PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source,
return PortMatchingResult::NotMatching;
}
-PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source,
+PortMatchingResult SourceAllowPort(const mojom::CSPSource& source,
const GURL& url) {
return SourceAllowPort(source, url.EffectiveIntPort(), url.scheme());
}
-bool SourceAllowPath(const mojom::CSPSourcePtr& source,
- const std::string& path) {
+bool SourceAllowPath(const mojom::CSPSource& source, const std::string& path) {
std::string path_decoded;
if (!DecodePath(path, &path_decoded)) {
// TODO(arthursonzogni): try to figure out if that could happen and how to
@@ -139,20 +136,20 @@ bool SourceAllowPath(const mojom::CSPSourcePtr& source,
return false;
}
- if (source->path.empty() || (source->path == "/" && path_decoded.empty()))
+ if (source.path.empty() || (source.path == "/" && path_decoded.empty()))
return true;
// If the path represents a directory.
- if (base::EndsWith(source->path, "/", base::CompareCase::SENSITIVE)) {
- return base::StartsWith(path_decoded, source->path,
+ if (base::EndsWith(source.path, "/", base::CompareCase::SENSITIVE)) {
+ return base::StartsWith(path_decoded, source.path,
base::CompareCase::SENSITIVE);
}
// The path represents a file.
- return source->path == path_decoded;
+ return source.path == path_decoded;
}
-bool SourceAllowPath(const mojom::CSPSourcePtr& source,
+bool SourceAllowPath(const mojom::CSPSource& source,
const GURL& url,
bool has_followed_redirect) {
if (has_followed_redirect)
@@ -180,20 +177,21 @@ bool canUpgrade(const SchemeMatchingResult result) {
} // namespace
-bool CSPSourceIsSchemeOnly(const mojom::CSPSourcePtr& source) {
+bool CSPSourceIsSchemeOnly(const mojom::CSPSource& source) {
return !HasHost(source);
}
-bool CheckCSPSource(const mojom::CSPSourcePtr& source,
+bool CheckCSPSource(const mojom::CSPSource& source,
const GURL& url,
- CSPContext* context,
+ const mojom::CSPSource& self_source,
bool has_followed_redirect) {
if (CSPSourceIsSchemeOnly(source)) {
- return SourceAllowScheme(source, url, context) !=
+ return SourceAllowScheme(source, url, self_source) !=
SchemeMatchingResult::NotMatching;
}
PortMatchingResult portResult = SourceAllowPort(source, url);
- SchemeMatchingResult schemeResult = SourceAllowScheme(source, url, context);
+ SchemeMatchingResult schemeResult =
+ SourceAllowScheme(source, url, self_source);
if (requiresUpgrade(schemeResult) && !canUpgrade(portResult))
return false;
if (requiresUpgrade(portResult) && !canUpgrade(schemeResult))
@@ -204,71 +202,71 @@ bool CheckCSPSource(const mojom::CSPSourcePtr& source,
SourceAllowPath(source, url, has_followed_redirect);
}
-mojom::CSPSourcePtr CSPSourcesIntersect(const mojom::CSPSourcePtr& source_a,
- const mojom::CSPSourcePtr& source_b) {
+mojom::CSPSourcePtr CSPSourcesIntersect(const mojom::CSPSource& source_a,
+ const mojom::CSPSource& source_b) {
// If the original source expressions didn't have a scheme, we should have
// filled that already with origin's scheme.
- DCHECK(!source_a->scheme.empty());
- DCHECK(!source_b->scheme.empty());
+ DCHECK(!source_a.scheme.empty());
+ DCHECK(!source_b.scheme.empty());
auto result = mojom::CSPSource::New();
- if (MatchScheme(source_a->scheme, source_b->scheme) !=
+ if (MatchScheme(source_a.scheme, source_b.scheme) !=
SchemeMatchingResult::NotMatching) {
- result->scheme = source_b->scheme;
- } else if (MatchScheme(source_b->scheme, source_a->scheme) !=
+ result->scheme = source_b.scheme;
+ } else if (MatchScheme(source_b.scheme, source_a.scheme) !=
SchemeMatchingResult::NotMatching) {
- result->scheme = source_a->scheme;
+ result->scheme = source_a.scheme;
} else {
return nullptr;
}
if (CSPSourceIsSchemeOnly(source_a)) {
- auto new_result = source_b->Clone();
+ auto new_result = source_b.Clone();
new_result->scheme = result->scheme;
return new_result;
} else if (CSPSourceIsSchemeOnly(source_b)) {
- auto new_result = source_a->Clone();
+ auto new_result = source_a.Clone();
new_result->scheme = result->scheme;
return new_result;
}
const std::string host_a =
- (source_a->is_host_wildcard ? "*." : "") + source_a->host;
+ (source_a.is_host_wildcard ? "*." : "") + source_a.host;
const std::string host_b =
- (source_b->is_host_wildcard ? "*." : "") + source_b->host;
+ (source_b.is_host_wildcard ? "*." : "") + source_b.host;
if (SourceAllowHost(source_a, host_b)) {
- result->host = source_b->host;
- result->is_host_wildcard = source_b->is_host_wildcard;
+ result->host = source_b.host;
+ result->is_host_wildcard = source_b.is_host_wildcard;
} else if (SourceAllowHost(source_b, host_a)) {
- result->host = source_a->host;
- result->is_host_wildcard = source_a->is_host_wildcard;
+ result->host = source_a.host;
+ result->is_host_wildcard = source_a.is_host_wildcard;
} else {
return nullptr;
}
- if (source_b->is_port_wildcard) {
- result->port = source_a->port;
- result->is_port_wildcard = source_a->is_port_wildcard;
- } else if (source_a->is_port_wildcard) {
- result->port = source_b->port;
- } else if (SourceAllowPort(source_a, source_b->port, source_b->scheme) !=
+ if (source_b.is_port_wildcard) {
+ result->port = source_a.port;
+ result->is_port_wildcard = source_a.is_port_wildcard;
+ } else if (source_a.is_port_wildcard) {
+ result->port = source_b.port;
+ } else if (SourceAllowPort(source_a, source_b.port, source_b.scheme) !=
PortMatchingResult::NotMatching &&
// If port_a is explicitly specified but port_b is omitted, then we
// should take port_a instead of port_b, since port_a is stricter.
- !(source_a->port != url::PORT_UNSPECIFIED &&
- source_b->port == url::PORT_UNSPECIFIED)) {
- result->port = source_b->port;
- } else if (SourceAllowPort(source_b, source_a->port, source_a->scheme) !=
+ !(source_a.port != url::PORT_UNSPECIFIED &&
+ source_b.port == url::PORT_UNSPECIFIED)) {
+ result->port = source_b.port;
+ } else if (SourceAllowPort(source_b, source_a.port, source_a.scheme) !=
PortMatchingResult::NotMatching) {
- result->port = source_a->port;
+ result->port = source_a.port;
} else {
return nullptr;
}
- if (SourceAllowPath(source_a, source_b->path))
- result->path = source_b->path;
- else if (SourceAllowPath(source_b, source_a->path))
- result->path = source_a->path;
+ if (SourceAllowPath(source_a, source_b.path))
+ result->path = source_b.path;
+ else if (SourceAllowPath(source_b, source_a.path))
+ result->path = source_a.path;
else
return nullptr;
@@ -276,14 +274,14 @@ mojom::CSPSourcePtr CSPSourcesIntersect(const mojom::CSPSourcePtr& source_a,
}
// Check whether |source_a| subsumes |source_b|.
-bool CSPSourceSubsumes(const mojom::CSPSourcePtr& source_a,
- const mojom::CSPSourcePtr& source_b) {
+bool CSPSourceSubsumes(const mojom::CSPSource& source_a,
+ const mojom::CSPSource& source_b) {
// If the original source expressions didn't have a scheme, we should have
// filled that already with origin's scheme.
- DCHECK(!source_a->scheme.empty());
- DCHECK(!source_b->scheme.empty());
+ DCHECK(!source_a.scheme.empty());
+ DCHECK(!source_b.scheme.empty());
- if (MatchScheme(source_a->scheme, source_b->scheme) ==
+ if (MatchScheme(source_a.scheme, source_b.scheme) ==
SchemeMatchingResult::NotMatching) {
return false;
}
@@ -293,51 +291,51 @@ bool CSPSourceSubsumes(const mojom::CSPSourcePtr& source_a,
if (CSPSourceIsSchemeOnly(source_b))
return false;
- if (!SourceAllowHost(source_a, (source_b->is_host_wildcard ? "*." : "") +
- source_b->host)) {
+ if (!SourceAllowHost(
+ source_a, (source_b.is_host_wildcard ? "*." : "") + source_b.host)) {
return false;
}
- if (source_b->is_port_wildcard && !source_a->is_port_wildcard)
+ if (source_b.is_port_wildcard && !source_a.is_port_wildcard)
return false;
PortMatchingResult port_matching =
- SourceAllowPort(source_a, source_b->port, source_b->scheme);
+ SourceAllowPort(source_a, source_b.port, source_b.scheme);
if (port_matching == PortMatchingResult::NotMatching)
return false;
- if (!SourceAllowPath(source_a, source_b->path))
+ if (!SourceAllowPath(source_a, source_b.path))
return false;
return true;
}
-std::string ToString(const mojom::CSPSourcePtr& source) {
+std::string ToString(const mojom::CSPSource& source) {
// scheme
if (CSPSourceIsSchemeOnly(source))
- return source->scheme + ":";
+ return source.scheme + ":";
std::stringstream text;
- if (!source->scheme.empty())
- text << source->scheme << "://";
+ if (!source.scheme.empty())
+ text << source.scheme << "://";
// host
- if (source->is_host_wildcard) {
- if (source->host.empty())
+ if (source.is_host_wildcard) {
+ if (source.host.empty())
text << "*";
else
- text << "*." << source->host;
+ text << "*." << source.host;
} else {
- text << source->host;
+ text << source.host;
}
// port
- if (source->is_port_wildcard)
+ if (source.is_port_wildcard)
text << ":*";
- if (source->port != url::PORT_UNSPECIFIED)
- text << ":" << source->port;
+ if (source.port != url::PORT_UNSPECIFIED)
+ text << ":" << source.port;
// path
- text << source->path;
+ text << source.path;
return text.str();
}
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source.h b/chromium/services/network/public/cpp/content_security_policy/csp_source.h
index 8e65b494693..49f9948ff6e 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source.h
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source.h
@@ -13,34 +13,32 @@ class GURL;
namespace network {
-class CSPContext;
-
// Check if a CSP |source| matches the scheme-source grammar.
-bool CSPSourceIsSchemeOnly(const mojom::CSPSourcePtr& source);
+bool CSPSourceIsSchemeOnly(const mojom::CSPSource& source);
// Check if a |url| matches with a CSP |source| matches.
COMPONENT_EXPORT(NETWORK_CPP)
-bool CheckCSPSource(const mojom::CSPSourcePtr& source,
+bool CheckCSPSource(const mojom::CSPSource& source,
const GURL& url,
- CSPContext* context,
+ const mojom::CSPSource& self_source,
bool has_followed_redirect = false);
// Compute the source intersection of |source_a| and |source_b|.
// https://w3c.github.io/webappsec-cspee/#intersection-source-expressions
COMPONENT_EXPORT(NETWORK_CPP)
-mojom::CSPSourcePtr CSPSourcesIntersect(const mojom::CSPSourcePtr& source_a,
- const mojom::CSPSourcePtr& source_b);
+mojom::CSPSourcePtr CSPSourcesIntersect(const mojom::CSPSource& source_a,
+ const mojom::CSPSource& source_b);
// Check if |source_a| subsumes |source_b| according to
// https://w3c.github.io/webappsec-cspee/#subsume-source-expressions
COMPONENT_EXPORT(NETWORK_CPP)
-bool CSPSourceSubsumes(const mojom::CSPSourcePtr& source_a,
- const mojom::CSPSourcePtr& source_b);
+bool CSPSourceSubsumes(const mojom::CSPSource& source_a,
+ const mojom::CSPSource& source_b);
// Serialize the CSPSource |source| as a string. This is used for reporting
// violations.
COMPONENT_EXPORT(NETWORK_CPP)
-std::string ToString(const mojom::CSPSourcePtr& source);
+std::string ToString(const mojom::CSPSource& source);
} // namespace network
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source_list.cc b/chromium/services/network/public/cpp/content_security_policy/csp_source_list.cc
index 60443a74b7e..d20cd476017 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source_list.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source_list.cc
@@ -7,7 +7,6 @@
#include "base/containers/flat_set.h"
#include "base/ranges/algorithm.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "services/network/public/cpp/content_security_policy/csp_source.h"
namespace network {
@@ -18,10 +17,10 @@ namespace {
bool AllowFromSources(const GURL& url,
const std::vector<mojom::CSPSourcePtr>& sources,
- CSPContext* context,
+ const mojom::CSPSource& self_source,
bool has_followed_redirect) {
for (const auto& source : sources) {
- if (CheckCSPSource(source, url, context, has_followed_redirect))
+ if (CheckCSPSource(*source, url, self_source, has_followed_redirect))
return true;
}
return false;
@@ -73,14 +72,14 @@ base::flat_set<std::string> IntersectSchemesOnly(
const std::vector<mojom::CSPSourcePtr>& list_b) {
base::flat_set<std::string> schemes_a;
for (const auto& source_a : list_a) {
- if (CSPSourceIsSchemeOnly(source_a)) {
+ if (CSPSourceIsSchemeOnly(*source_a)) {
AddSourceSchemesToSet(schemes_a, source_a.get());
}
}
base::flat_set<std::string> intersection;
for (const auto& source_b : list_b) {
- if (CSPSourceIsSchemeOnly(source_b)) {
+ if (CSPSourceIsSchemeOnly(*source_b)) {
if (schemes_a.contains(source_b->scheme))
AddSourceSchemesToSet(intersection, source_b.get());
else if (source_b->scheme == url::kHttpScheme &&
@@ -98,14 +97,13 @@ base::flat_set<std::string> IntersectSchemesOnly(
std::vector<mojom::CSPSourcePtr> ExpandSchemeStarAndSelf(
const mojom::CSPSourceList& source_list,
- const mojom::CSPSource& self) {
+ const mojom::CSPSource* self) {
std::vector<mojom::CSPSourcePtr> result;
for (const mojom::CSPSourcePtr& item : source_list.sources) {
mojom::CSPSourcePtr new_item = item->Clone();
if (new_item->scheme.empty()) {
- if (self.scheme.empty())
- continue;
- new_item->scheme = self.scheme;
+ if (self && !self->scheme.empty())
+ new_item->scheme = self->scheme;
}
result.push_back(std::move(new_item));
}
@@ -117,15 +115,16 @@ std::vector<mojom::CSPSourcePtr> ExpandSchemeStarAndSelf(
url::kWsScheme, "", url::PORT_UNSPECIFIED, "", false, false));
result.push_back(mojom::CSPSource::New(
url::kHttpScheme, "", url::PORT_UNSPECIFIED, "", false, false));
- if (!self.scheme.empty()) {
+ if (self && !self->scheme.empty()) {
result.push_back(mojom::CSPSource::New(
- self.scheme, "", url::PORT_UNSPECIFIED, "", false, false));
+ self->scheme, "", url::PORT_UNSPECIFIED, "", false, false));
}
}
- if (source_list.allow_self && !self.scheme.empty() && !self.host.empty()) {
+ if (source_list.allow_self && self && !self->scheme.empty() &&
+ !self->host.empty()) {
// If |self| is an opaque origin we should ignore it.
- result.push_back(self.Clone());
+ result.push_back(self->Clone());
}
return result;
}
@@ -133,7 +132,7 @@ std::vector<mojom::CSPSourcePtr> ExpandSchemeStarAndSelf(
std::vector<mojom::CSPSourcePtr> IntersectSources(
const mojom::CSPSourceList& source_list_a,
const std::vector<mojom::CSPSourcePtr>& source_list_b,
- const mojom::CSPSource& self) {
+ const mojom::CSPSource* self) {
auto schemes = IntersectSchemesOnly(source_list_a.sources, source_list_b);
std::vector<mojom::CSPSourcePtr> normalized;
@@ -160,7 +159,7 @@ std::vector<mojom::CSPSourcePtr> IntersectSources(
if (schemes.contains(source_b->scheme))
continue;
if (mojom::CSPSourcePtr local_match =
- CSPSourcesIntersect(source_a, source_b)) {
+ CSPSourcesIntersect(*source_a, *source_b)) {
normalized.emplace_back(std::move(local_match));
}
}
@@ -179,21 +178,21 @@ bool UrlSourceListSubsumes(
// |source_list_a|.
return base::ranges::all_of(source_list_b, [&](const auto& source_b) {
return base::ranges::any_of(source_list_a, [&](const auto& source_a) {
- return CSPSourceSubsumes(source_a, source_b);
+ return CSPSourceSubsumes(*source_a, *source_b);
});
});
}
} // namespace
-bool CheckCSPSourceList(const mojom::CSPSourceListPtr& source_list,
+bool CheckCSPSourceList(const mojom::CSPSourceList& source_list,
const GURL& url,
- CSPContext* context,
+ const mojom::CSPSource& self_source,
bool has_followed_redirect,
bool is_response_check) {
// If the source list allows all redirects, the decision can't be made until
// the response is received.
- if (source_list->allow_response_redirects && !is_response_check)
+ if (source_list.allow_response_redirects && !is_response_check)
return true;
// Wildcards match network schemes ('http', 'https', 'ftp', 'ws', 'wss'), and
@@ -201,22 +200,21 @@ bool CheckCSPSourceList(const mojom::CSPSourceListPtr& source_list,
// https://w3c.github.io/webappsec-csp/#match-url-to-source-expression. Other
// schemes, including custom schemes, must be explicitly listed in a source
// list.
- if (source_list->allow_star) {
+ if (source_list.allow_star) {
if (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS() ||
url.SchemeIs("ftp")) {
return true;
}
- if (context->self_source() && url.SchemeIs(context->self_source()->scheme))
+ if (!self_source.scheme.empty() && url.SchemeIs(self_source.scheme))
return true;
}
- if (source_list->allow_self && context->self_source() &&
- CheckCSPSource(context->self_source(), url, context,
- has_followed_redirect)) {
+ if (source_list.allow_self &&
+ CheckCSPSource(self_source, url, self_source, has_followed_redirect)) {
return true;
}
- return AllowFromSources(url, source_list->sources, context,
+ return AllowFromSources(url, source_list.sources, self_source,
has_followed_redirect);
}
@@ -224,7 +222,7 @@ bool CSPSourceListSubsumes(
const mojom::CSPSourceList& source_list_a,
const std::vector<const mojom::CSPSourceList*>& source_list_b,
CSPDirectiveName directive,
- const url::Origin& origin_b) {
+ const mojom::CSPSource* origin_b) {
if (source_list_b.empty())
return false;
@@ -239,10 +237,8 @@ bool CSPSourceListSubsumes(
base::flat_set<std::string> nonces_b((*it)->nonces);
base::flat_set<mojom::CSPHashSourcePtr> hashes_b(mojo::Clone((*it)->hashes));
- auto origin_b_as_csp_source = mojom::CSPSource::New(
- origin_b.scheme(), origin_b.host(), origin_b.port(), "", false, false);
std::vector<mojom::CSPSourcePtr> normalized_sources_b =
- ExpandSchemeStarAndSelf(**it, *origin_b_as_csp_source);
+ ExpandSchemeStarAndSelf(**it, origin_b);
++it;
for (; it != source_list_b.end(); ++it) {
@@ -262,7 +258,7 @@ bool CSPSourceListSubsumes(
mojo::Clone((*it)->hashes));
IntersectHashes(hashes_b, item_hashes);
normalized_sources_b =
- IntersectSources(**it, normalized_sources_b, *origin_b_as_csp_source);
+ IntersectSources(**it, normalized_sources_b, origin_b);
}
// If source_list_b enforces some nonce, then source_list_a must contain
@@ -310,7 +306,7 @@ bool CSPSourceListSubsumes(
// If embedding CSP specifies `self`, `self` refers to the embedee's origin.
std::vector<mojom::CSPSourcePtr> normalized_sources_a =
- ExpandSchemeStarAndSelf(source_list_a, *origin_b_as_csp_source);
+ ExpandSchemeStarAndSelf(source_list_a, origin_b);
return UrlSourceListSubsumes(normalized_sources_a, normalized_sources_b);
}
@@ -332,7 +328,7 @@ std::string ToString(const mojom::CSPSourceListPtr& source_list) {
for (const auto& source : source_list->sources) {
if (!is_empty)
text << " ";
- text << ToString(source);
+ text << ToString(*source);
is_empty = false;
}
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source_list.h b/chromium/services/network/public/cpp/content_security_policy/csp_source_list.h
index d2bc9742197..141b233d47f 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source_list.h
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source_list.h
@@ -13,22 +13,17 @@
class GURL;
-namespace url {
-class Origin;
-}
-
namespace network {
-class CSPContext;
COMPONENT_EXPORT(NETWORK_CPP)
std::string ToString(const mojom::CSPSourceListPtr& source_list);
// Return true when at least one source in the |source_list| matches the
-// |url| for a given |context|.
+// |url|.
COMPONENT_EXPORT(NETWORK_CPP)
-bool CheckCSPSourceList(const mojom::CSPSourceListPtr& source_list,
+bool CheckCSPSourceList(const mojom::CSPSourceList& source_list,
const GURL& url,
- CSPContext* context,
+ const mojom::CSPSource& self_source,
bool has_followed_redirect = false,
bool is_response_check = false);
@@ -40,7 +35,7 @@ bool CSPSourceListSubsumes(
const mojom::CSPSourceList& source_list_a,
const std::vector<const mojom::CSPSourceList*>& source_list_b,
mojom::CSPDirectiveName directive,
- const url::Origin& origin_b);
+ const mojom::CSPSource* origin_b);
} // namespace network
#endif // SERVICES_NETWORK_PUBLIC_CPP_CONTENT_SECURITY_POLICY_CSP_SOURCE_LIST_H_
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
index 7831ed6ffcc..4f9c3293011 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
@@ -6,7 +6,6 @@
#include "base/strings/stringprintf.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
@@ -19,10 +18,10 @@ namespace {
// test expectations on one line.
bool Allow(const mojom::CSPSourceListPtr& source_list,
const GURL& url,
- CSPContext* context,
+ const mojom::CSPSource& self,
bool is_redirect = false,
bool is_response_check = false) {
- return CheckCSPSourceList(source_list, url, context, is_redirect,
+ return CheckCSPSourceList(*source_list, url, self, is_redirect,
is_response_check);
}
@@ -77,8 +76,8 @@ std::vector<const mojom::CSPSourceList*> ToRawPointers(
} // namespace
TEST(CSPSourceList, MultipleSource) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
+ auto self = network::mojom::CSPSource::New("http", "example.com", 80, "",
+ false, false);
std::vector<mojom::CSPSourcePtr> sources;
sources.push_back(mojom::CSPSource::New("", "a.com", url::PORT_UNSPECIFIED,
"", false, false));
@@ -86,92 +85,96 @@ TEST(CSPSourceList, MultipleSource) {
"", false, false));
auto source_list = mojom::CSPSourceList::New();
source_list->sources = std::move(sources);
- EXPECT_TRUE(Allow(source_list, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source_list, GURL("http://b.com"), &context));
- EXPECT_FALSE(Allow(source_list, GURL("http://c.com"), &context));
+ EXPECT_TRUE(Allow(source_list, GURL("http://a.com"), *self));
+ EXPECT_TRUE(Allow(source_list, GURL("http://b.com"), *self));
+ EXPECT_FALSE(Allow(source_list, GURL("http://c.com"), *self));
}
TEST(CSPSourceList, AllowStar) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
+ auto self = network::mojom::CSPSource::New("http", "example.com", 80, "",
+ false, false);
auto source_list = mojom::CSPSourceList::New();
source_list->allow_star = true;
- EXPECT_TRUE(Allow(source_list, GURL("http://not-example.com"), &context));
- EXPECT_TRUE(Allow(source_list, GURL("https://not-example.com"), &context));
- EXPECT_TRUE(Allow(source_list, GURL("ws://not-example.com"), &context));
- EXPECT_TRUE(Allow(source_list, GURL("wss://not-example.com"), &context));
- EXPECT_TRUE(Allow(source_list, GURL("ftp://not-example.com"), &context));
+ EXPECT_TRUE(Allow(source_list, GURL("http://not-example.com"), *self));
+ EXPECT_TRUE(Allow(source_list, GURL("https://not-example.com"), *self));
+ EXPECT_TRUE(Allow(source_list, GURL("ws://not-example.com"), *self));
+ EXPECT_TRUE(Allow(source_list, GURL("wss://not-example.com"), *self));
+ EXPECT_TRUE(Allow(source_list, GURL("ftp://not-example.com"), *self));
- EXPECT_FALSE(Allow(source_list, GURL("file://not-example.com"), &context));
- EXPECT_FALSE(Allow(source_list, GURL("applewebdata://a.test"), &context));
+ EXPECT_FALSE(Allow(source_list, GURL("file://not-example.com"), *self));
+ EXPECT_FALSE(Allow(source_list, GURL("applewebdata://a.test"), *self));
- // With a protocol of 'file', '*' allow 'file:'
- context.SetSelf(url::Origin::Create(GURL("file://example.com")));
- EXPECT_TRUE(Allow(source_list, GURL("file://not-example.com"), &context));
- EXPECT_FALSE(Allow(source_list, GURL("applewebdata://a.test"), &context));
+ {
+ // With a protocol of 'file', '*' allow 'file:'
+ auto self = network::mojom::CSPSource::New(
+ "file", "example.com", url::PORT_UNSPECIFIED, "", false, false);
+ EXPECT_TRUE(Allow(source_list, GURL("file://not-example.com"), *self));
+ EXPECT_FALSE(Allow(source_list, GURL("applewebdata://a.test"), *self));
+ }
}
TEST(CSPSourceList, AllowSelf) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
+ auto self = network::mojom::CSPSource::New("http", "example.com", 80, "",
+ false, false);
auto source_list = mojom::CSPSourceList::New();
source_list->allow_self = true;
- EXPECT_TRUE(Allow(source_list, GURL("http://example.com"), &context));
- EXPECT_FALSE(Allow(source_list, GURL("http://not-example.com"), &context));
- EXPECT_TRUE(Allow(source_list, GURL("https://example.com"), &context));
- EXPECT_FALSE(Allow(source_list, GURL("ws://example.com"), &context));
+ EXPECT_TRUE(Allow(source_list, GURL("http://example.com"), *self));
+ EXPECT_FALSE(Allow(source_list, GURL("http://not-example.com"), *self));
+ EXPECT_TRUE(Allow(source_list, GURL("https://example.com"), *self));
+ EXPECT_FALSE(Allow(source_list, GURL("ws://example.com"), *self));
}
TEST(CSPSourceList, AllowStarAndSelf) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("https://a.com")));
+ auto self =
+ network::mojom::CSPSource::New("https", "a.com", 443, "", false, false);
auto source_list = mojom::CSPSourceList::New();
// If the request is allowed by {*} and not by {'self'} then it should be
// allowed by the union {*,'self'}.
source_list->allow_self = true;
source_list->allow_star = false;
- EXPECT_FALSE(Allow(source_list, GURL("http://b.com"), &context));
+ EXPECT_FALSE(Allow(source_list, GURL("http://b.com"), *self));
source_list->allow_self = false;
source_list->allow_star = true;
- EXPECT_TRUE(Allow(source_list, GURL("http://b.com"), &context));
+ EXPECT_TRUE(Allow(source_list, GURL("http://b.com"), *self));
source_list->allow_self = true;
source_list->allow_star = true;
- EXPECT_TRUE(Allow(source_list, GURL("http://b.com"), &context));
+ EXPECT_TRUE(Allow(source_list, GURL("http://b.com"), *self));
}
TEST(CSPSourceList, AllowSelfWithUnspecifiedPort) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("https://example.com/")));
+ auto self = network::mojom::CSPSource::New("https", "example.com", 443, "",
+ false, false);
auto source_list = mojom::CSPSourceList::New();
source_list->allow_self = true;
- EXPECT_TRUE(
- Allow(source_list, GURL("https://example.com/print.pdf"), &context));
+ EXPECT_TRUE(Allow(source_list, GURL("https://example.com/print.pdf"), *self));
}
TEST(CSPSourceList, AllowNone) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
+ auto self = network::mojom::CSPSource::New("http", "example.com", 80, "",
+ false, false);
auto source_list = mojom::CSPSourceList::New();
- EXPECT_FALSE(Allow(source_list, GURL("http://example.com"), &context));
- EXPECT_FALSE(Allow(source_list, GURL("https://example.test/"), &context));
+ EXPECT_FALSE(Allow(source_list, GURL("http://example.com"), *self));
+ EXPECT_FALSE(Allow(source_list, GURL("https://example.test/"), *self));
}
TEST(CSPSourceTest, SelfIsUnique) {
// Policy: 'self'
auto source_list = mojom::CSPSourceList::New();
source_list->allow_self = true;
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("http://a.com")));
- EXPECT_TRUE(Allow(source_list, GURL("http://a.com"), &context));
- EXPECT_FALSE(Allow(source_list, GURL("data:text/html,hello"), &context));
+ auto self =
+ network::mojom::CSPSource::New("http", "a.com", 80, "", false, false);
+ EXPECT_TRUE(Allow(source_list, GURL("http://a.com"), *self));
+ EXPECT_FALSE(Allow(source_list, GURL("data:text/html,hello"), *self));
- context.SetSelf(
- url::Origin::Create(GURL("data:text/html,<iframe src=[...]>")));
- EXPECT_FALSE(Allow(source_list, GURL("http://a.com"), &context));
- EXPECT_FALSE(Allow(source_list, GURL("data:text/html,hello"), &context));
+ // Self doesn't match anything.
+ auto no_self_source = network::mojom::CSPSource::New(
+ "", "", url::PORT_UNSPECIFIED, "", false, false);
+ EXPECT_FALSE(Allow(source_list, GURL("http://a.com"), *no_self_source));
+ EXPECT_FALSE(
+ Allow(source_list, GURL("data:text/html,hello"), *no_self_source));
}
TEST(CSPSourceList, Subsume) {
@@ -257,6 +260,8 @@ TEST(CSPSourceList, Subsume) {
{{"http://*", "http://*.com http://*.example3.com:*/bar/"}, false},
};
+ auto origin_b =
+ mojom::CSPSource::New("https", "frame.test", 443, "", false, false);
for (const auto& test : cases) {
auto response_sources = ParseToVectorOfSourceLists(
mojom::CSPDirectiveName::ScriptSrc, test.response_csp);
@@ -264,8 +269,7 @@ TEST(CSPSourceList, Subsume) {
EXPECT_EQ(test.expected,
CSPSourceListSubsumes(
*required_sources, ToRawPointers(response_sources),
- mojom::CSPDirectiveName::ScriptSrc,
- url::Origin::Create(GURL("https://frame.test"))))
+ mojom::CSPDirectiveName::ScriptSrc, origin_b.get()))
<< required << " should " << (test.expected ? "" : "not ") << "subsume "
<< base::JoinString(test.response_csp, ", ");
}
@@ -383,11 +387,14 @@ TEST(CSPSourceList, SubsumeWithSelf) {
auto response_sources = ParseToVectorOfSourceLists(
mojom::CSPDirectiveName::ScriptSrc, test.response_csp);
+ GURL parsed_test_origin(test.origin);
+ auto origin_b = mojom::CSPSource::New(
+ parsed_test_origin.scheme(), parsed_test_origin.host(),
+ parsed_test_origin.EffectiveIntPort(), "", false, false);
EXPECT_EQ(test.expected,
- CSPSourceListSubsumes(*required_sources,
- ToRawPointers(response_sources),
- mojom::CSPDirectiveName::ScriptSrc,
- url::Origin::Create(GURL(test.origin))))
+ CSPSourceListSubsumes(
+ *required_sources, ToRawPointers(response_sources),
+ mojom::CSPDirectiveName::ScriptSrc, origin_b.get()))
<< required << "from origin " << test.origin << " should "
<< (test.expected ? "" : "not ") << "subsume "
<< base::JoinString(test.response_csp, ", ");
@@ -489,17 +496,18 @@ TEST(CSPSourceList, SubsumeAllowAllInline) {
true},
};
+ auto origin_b =
+ mojom::CSPSource::New("https", "frame.test", 443, "", false, false);
for (const auto& test : cases) {
mojom::CSPSourceListPtr required_sources =
ParseToSourceList(test.directive, test.required);
auto response_sources =
ParseToVectorOfSourceLists(test.directive, test.response_csp);
- EXPECT_EQ(
- test.expected,
- CSPSourceListSubsumes(*required_sources,
- ToRawPointers(response_sources), test.directive,
- url::Origin::Create(GURL("https://frame.test"))))
+ EXPECT_EQ(test.expected,
+ CSPSourceListSubsumes(*required_sources,
+ ToRawPointers(response_sources),
+ test.directive, origin_b.get()))
<< test.required << " should " << (test.expected ? "" : "not ")
<< "subsume " << base::JoinString(test.response_csp, ", ");
}
@@ -576,17 +584,18 @@ TEST(CSPSourceList, SubsumeUnsafeAttributes) {
false},
};
+ auto origin_b =
+ mojom::CSPSource::New("https", "frame.test", 443, "", false, false);
for (const auto& test : cases) {
mojom::CSPSourceListPtr required_sources =
ParseToSourceList(test.directive, test.required);
auto response_sources =
ParseToVectorOfSourceLists(test.directive, test.response_csp);
- EXPECT_EQ(
- test.expected,
- CSPSourceListSubsumes(*required_sources,
- ToRawPointers(response_sources), test.directive,
- url::Origin::Create(GURL("https://frame.test"))))
+ EXPECT_EQ(test.expected,
+ CSPSourceListSubsumes(*required_sources,
+ ToRawPointers(response_sources),
+ test.directive, origin_b.get()))
<< test.required << " should " << (test.expected ? "" : "not ")
<< "subsume " << base::JoinString(test.response_csp, ", ");
}
@@ -728,17 +737,18 @@ TEST(CSPSourceList, SubsumeNoncesAndHashes) {
false},
};
+ auto origin_b =
+ mojom::CSPSource::New("https", "frame.test", 443, "", false, false);
for (const auto& test : cases) {
mojom::CSPSourceListPtr required_sources =
ParseToSourceList(test.directive, test.required);
auto response_sources =
ParseToVectorOfSourceLists(test.directive, test.response_csp);
- EXPECT_EQ(
- test.expected,
- CSPSourceListSubsumes(*required_sources,
- ToRawPointers(response_sources), test.directive,
- url::Origin::Create(GURL("https://frame.test"))))
+ EXPECT_EQ(test.expected,
+ CSPSourceListSubsumes(*required_sources,
+ ToRawPointers(response_sources),
+ test.directive, origin_b.get()))
<< test.required << " should " << (test.expected ? "" : "not ")
<< "subsume " << base::JoinString(test.response_csp, ", ");
}
@@ -911,17 +921,18 @@ TEST(CSPSourceList, SubsumeStrictDynamic) {
false},
};
+ auto origin_b =
+ mojom::CSPSource::New("https", "frame.test", 443, "", false, false);
for (const auto& test : cases) {
mojom::CSPSourceListPtr required_sources =
ParseToSourceList(test.directive, test.required);
auto response_sources =
ParseToVectorOfSourceLists(test.directive, test.response_csp);
- EXPECT_EQ(
- test.expected,
- CSPSourceListSubsumes(*required_sources,
- ToRawPointers(response_sources), test.directive,
- url::Origin::Create(GURL("https://frame.test"))))
+ EXPECT_EQ(test.expected,
+ CSPSourceListSubsumes(*required_sources,
+ ToRawPointers(response_sources),
+ test.directive, origin_b.get()))
<< test.required << " should " << (test.expected ? "" : "not ")
<< "subsume " << base::JoinString(test.response_csp, ", ");
}
@@ -982,6 +993,8 @@ TEST(CSPSourceList, SubsumeListWildcard) {
false},
};
+ auto origin_b =
+ mojom::CSPSource::New("https", "another.test", 443, "", false, false);
for (const auto& test : cases) {
mojom::CSPSourceListPtr required_sources =
ParseToSourceList(mojom::CSPDirectiveName::ScriptSrc, test.required);
@@ -991,33 +1004,36 @@ TEST(CSPSourceList, SubsumeListWildcard) {
EXPECT_EQ(test.expected,
CSPSourceListSubsumes(
*required_sources, ToRawPointers(response_sources),
- mojom::CSPDirectiveName::ScriptSrc,
- url::Origin::Create(GURL("https://another.test/image.png"))))
+ mojom::CSPDirectiveName::ScriptSrc, origin_b.get()))
<< test.required << " should " << (test.expected ? "" : "not ")
<< "subsume " << base::JoinString(test.response_csp, ", ");
}
}
TEST(CSPSourceList, SubsumeListNoScheme) {
+ auto origin_http =
+ mojom::CSPSource::New("http", "example.org", 80, "", false, false);
+ auto origin_https =
+ mojom::CSPSource::New("https", "example.org", 443, "", false, false);
struct TestCase {
std::string required;
std::vector<std::string> response_csp;
- std::string origin;
+ mojom::CSPSource* origin;
bool expected;
} cases[] = {
- {"http://a.com", {"a.com"}, "https://example.org", true},
- {"https://a.com", {"a.com"}, "https://example.org", true},
- {"https://a.com", {"a.com"}, "http://example.org", false},
- {"data://a.com", {"a.com"}, "https://example.org", false},
- {"a.com", {"a.com"}, "https://example.org", true},
- {"a.com", {"a.com"}, "http://example.org", true},
- {"a.com", {"https://a.com"}, "http://example.org", true},
- {"a.com", {"https://a.com"}, "https://example.org", true},
- {"a.com", {"http://a.com"}, "https://example.org", false},
- {"https:", {"a.com"}, "http://example.org", false},
- {"http:", {"a.com"}, "http://example.org", true},
- {"https:", {"a.com", "https:"}, "http://example.org", true},
- {"https:", {"a.com"}, "https://example.org", true},
+ {"http://a.com", {"a.com"}, origin_https.get(), true},
+ {"https://a.com", {"a.com"}, origin_https.get(), true},
+ {"https://a.com", {"a.com"}, origin_http.get(), false},
+ {"data://a.com", {"a.com"}, origin_https.get(), false},
+ {"a.com", {"a.com"}, origin_https.get(), true},
+ {"a.com", {"a.com"}, origin_http.get(), true},
+ {"a.com", {"https://a.com"}, origin_http.get(), true},
+ {"a.com", {"https://a.com"}, origin_https.get(), true},
+ {"a.com", {"http://a.com"}, origin_https.get(), false},
+ {"https:", {"a.com"}, origin_http.get(), false},
+ {"http:", {"a.com"}, origin_http.get(), true},
+ {"https:", {"a.com", "https:"}, origin_http.get(), true},
+ {"https:", {"a.com"}, origin_https.get(), true},
};
for (const auto& test : cases) {
@@ -1027,12 +1043,11 @@ TEST(CSPSourceList, SubsumeListNoScheme) {
mojom::CSPDirectiveName::ScriptSrc, test.response_csp);
EXPECT_EQ(test.expected,
- CSPSourceListSubsumes(*required_sources,
- ToRawPointers(response_sources),
- mojom::CSPDirectiveName::ScriptSrc,
- url::Origin::Create(GURL(test.origin))))
- << test.required << " on origin " << test.origin << " should "
- << (test.expected ? "" : "not ") << "subsume "
+ CSPSourceListSubsumes(
+ *required_sources, ToRawPointers(response_sources),
+ mojom::CSPDirectiveName::ScriptSrc, test.origin))
+ << test.required << " on origin with scheme " << test.origin->scheme
+ << " should " << (test.expected ? "" : "not ") << "subsume "
<< base::JoinString(test.response_csp, ", ");
}
}
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc
index 88f4e53f051..7ee11c202dd 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc
@@ -5,7 +5,6 @@
#include "services/network/public/cpp/content_security_policy/csp_source.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
@@ -15,11 +14,11 @@ namespace {
// Allow() is an abbreviation of CSPSource::Allow(). Useful for writing test
// expectations on one line.
-bool Allow(const network::mojom::CSPSourcePtr& source,
+bool Allow(const network::mojom::CSPSource& source,
const GURL& url,
- CSPContext* context,
+ const network::mojom::CSPSource& self_source,
bool is_redirect = false) {
- return CheckCSPSource(source, url, context, is_redirect);
+ return CheckCSPSource(source, url, self_source, is_redirect);
}
network::mojom::CSPSourcePtr CSPSource(const std::string& raw) {
@@ -36,261 +35,291 @@ network::mojom::CSPSourcePtr CSPSource(const std::string& raw) {
} // namespace
TEST(CSPSourceTest, BasicMatching) {
- CSPContext context;
-
auto source = network::mojom::CSPSource::New("http", "example.com", 8000,
"/foo/", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://example.com:8000/foo/"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://example.com:8000/foo/bar"), &context));
- EXPECT_TRUE(Allow(source, GURL("HTTP://EXAMPLE.com:8000/foo/BAR"), &context));
+ // Self doesn't match anything.
+ auto self_source = network::mojom::CSPSource::New(
+ "", "", url::PORT_UNSPECIFIED, "", false, false);
+
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://example.com:8000/foo/"), *self_source));
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://example.com:8000/foo/bar"), *self_source));
+ EXPECT_TRUE(
+ Allow(*source, GURL("HTTP://EXAMPLE.com:8000/foo/BAR"), *self_source));
- EXPECT_FALSE(Allow(source, GURL("http://example.com:8000/bar/"), &context));
- EXPECT_FALSE(Allow(source, GURL("https://example.com:8000/bar/"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://example.com:9000/bar/"), &context));
EXPECT_FALSE(
- Allow(source, GURL("HTTP://example.com:8000/FOO/bar"), &context));
+ Allow(*source, GURL("http://example.com:8000/bar/"), *self_source));
+ EXPECT_FALSE(
+ Allow(*source, GURL("https://example.com:8000/bar/"), *self_source));
+ EXPECT_FALSE(
+ Allow(*source, GURL("http://example.com:9000/bar/"), *self_source));
EXPECT_FALSE(
- Allow(source, GURL("HTTP://example.com:8000/FOO/BAR"), &context));
+ Allow(*source, GURL("HTTP://example.com:8000/FOO/bar"), *self_source));
+ EXPECT_FALSE(
+ Allow(*source, GURL("HTTP://example.com:8000/FOO/BAR"), *self_source));
}
TEST(CSPSourceTest, AllowScheme) {
- CSPContext context;
+ // Self doesn't match anything.
+ auto no_self_source = network::mojom::CSPSource::New(
+ "", "", url::PORT_UNSPECIFIED, "", false, false);
// http -> {http, https}.
{
auto source = network::mojom::CSPSource::New(
"http", "", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *no_self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com"), *no_self_source));
// This passes because the source is "scheme only" so the upgrade is
// allowed.
- EXPECT_TRUE(Allow(source, GURL("https://a.com:80"), &context));
- EXPECT_FALSE(Allow(source, GURL("ftp://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("ws://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("wss://a.com"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com:80"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("ftp://a.com"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("ws://a.com"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("wss://a.com"), *no_self_source));
}
// ws -> {ws, wss}.
{
auto source = network::mojom::CSPSource::New(
"ws", "", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("https://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("ftp://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("ws://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("wss://a.com"), &context));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("https://a.com"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("ftp://a.com"), *no_self_source));
+ EXPECT_TRUE(Allow(*source, GURL("ws://a.com"), *no_self_source));
+ EXPECT_TRUE(Allow(*source, GURL("wss://a.com"), *no_self_source));
}
// Exact matches required (ftp)
{
auto source = network::mojom::CSPSource::New(
"ftp", "", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("ftp://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("ftp://a.com"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *no_self_source));
}
// Exact matches required (https)
{
auto source = network::mojom::CSPSource::New(
"https", "", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("https://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *no_self_source));
}
// Exact matches required (wss)
{
auto source = network::mojom::CSPSource::New(
"wss", "", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("wss://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("ws://a.com"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("wss://a.com"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("ws://a.com"), *no_self_source));
}
// Scheme is empty (ProtocolMatchesSelf).
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
-
- // Self's scheme is http.
- context.SetSelf(url::Origin::Create(GURL("http://a.com")));
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("ftp://a.com"), &context));
-
- // Self's is https.
- context.SetSelf(url::Origin::Create(GURL("https://a.com")));
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("ftp://a.com"), &context));
-
- // Self's scheme is not in the http familly.
- context.SetSelf(url::Origin::Create(GURL("ftp://a.com/")));
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("ftp://a.com"), &context));
-
- // Self's scheme is unique (non standard scheme).
- context.SetSelf(url::Origin::Create(GURL("non-standard-scheme://a.com")));
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("non-standard-scheme://a.com"), &context));
-
- // Self's scheme is unique (data-url).
- context.SetSelf(
- url::Origin::Create(GURL("data:text/html,<iframe src=[...]>")));
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("data:text/html,hello"), &context));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *no_self_source));
+
+ {
+ // Self's scheme is http.
+ auto self_source =
+ network::mojom::CSPSource::New("http", "a.com", 80, "", false, false);
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("ftp://a.com"), *self_source));
+ }
+
+ {
+ // Self's is https.
+ auto self_source = network::mojom::CSPSource::New("https", "a.com", 443,
+ "", false, false);
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("ftp://a.com"), *self_source));
+ }
+
+ {
+ // Self's scheme is not in the http family.
+ auto self_source =
+ network::mojom::CSPSource::New("ftp", "a.com", 21, "", false, false);
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("ftp://a.com"), *self_source));
+ }
+
+ {
+ // Self's scheme is unique (non standard scheme).
+ auto self_source = network::mojom::CSPSource::New(
+ "non-standard-scheme", "a.com", url::PORT_UNSPECIFIED, "", false,
+ false);
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_FALSE(
+ Allow(*source, GURL("non-standard-scheme://a.com"), *self_source));
+ }
+
+ // Self's scheme is unique (e.g. data-url).
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *no_self_source));
+ EXPECT_FALSE(Allow(*source, GURL("data:text/html,hello"), *no_self_source));
}
}
TEST(CSPSourceTest, AllowHost) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
+ auto self_source = network::mojom::CSPSource::New("http", "example.com", 80,
+ "", false, false);
+
+ // Self doesn't match anything.
+ auto no_self_source = network::mojom::CSPSource::New(
+ "", "", url::PORT_UNSPECIFIED, "", false, false);
// Host is * (source-expression = "http://*")
{
auto source = network::mojom::CSPSource::New(
"http", "", url::PORT_UNSPECIFIED, "", true, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://."), &context));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://."), *self_source));
}
// Host is *.foo.bar
{
auto source = network::mojom::CSPSource::New(
"", "foo.bar", url::PORT_UNSPECIFIED, "", true, false);
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://bar"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://foo.bar"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://o.bar"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://*.foo.bar"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://sub.foo.bar"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://sub.sub.foo.bar"), &context));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://bar"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://foo.bar"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://o.bar"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://*.foo.bar"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://sub.foo.bar"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://sub.sub.foo.bar"), *self_source));
// Please see http://crbug.com/692505
- EXPECT_TRUE(Allow(source, GURL("http://.foo.bar"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("http://.foo.bar"), *self_source));
}
// Host is exact.
{
auto source = network::mojom::CSPSource::New(
"", "foo.bar", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://foo.bar"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://sub.foo.bar"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://bar"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("http://foo.bar"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://sub.foo.bar"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://bar"), *self_source));
// Please see http://crbug.com/692505
- EXPECT_FALSE(Allow(source, GURL("http://.foo.bar"), &context));
+ EXPECT_FALSE(Allow(*source, GURL("http://.foo.bar"), *self_source));
}
}
TEST(CSPSourceTest, AllowPort) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
+ auto self_source = network::mojom::CSPSource::New("http", "example.com", 80,
+ "", false, false);
// Source's port unspecified.
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com:80"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com:8080"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com:443"), &context));
- EXPECT_FALSE(Allow(source, GURL("https://a.com:80"), &context));
- EXPECT_FALSE(Allow(source, GURL("https://a.com:8080"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com:443"), &context));
- EXPECT_FALSE(Allow(source, GURL("unknown://a.com:80"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com:80"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com:8080"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com:443"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("https://a.com:80"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("https://a.com:8080"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com:443"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("unknown://a.com:80"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com"), *self_source));
}
// Source's port is "*".
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "", false, true);
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com:80"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com:8080"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com:8080"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com:0"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com:80"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com:8080"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com:8080"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com:0"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com"), *self_source));
}
// Source has a port.
{
auto source =
network::mojom::CSPSource::New("", "a.com", 80, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com:80"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com:8080"), &context));
- EXPECT_TRUE(Allow(source, GURL("https://a.com"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com:80"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com:8080"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com"), *self_source));
}
// Allow upgrade from :80 to :443
{
auto source =
network::mojom::CSPSource::New("", "a.com", 80, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("https://a.com:443"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com:443"), *self_source));
// Should not allow scheme upgrades unless both port and scheme are
// upgraded.
- EXPECT_FALSE(Allow(source, GURL("http://a.com:443"), &context));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com:443"), *self_source));
}
// Host is * but port is specified
{
auto source =
network::mojom::CSPSource::New("http", "", 111, "", true, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com:111"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com:222"), &context));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com:111"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com:222"), *self_source));
}
}
TEST(CSPSourceTest, AllowPath) {
- CSPContext context;
- context.SetSelf(url::Origin::Create(GURL("http://example.com")));
+ auto self_source = network::mojom::CSPSource::New("http", "example.com", 80,
+ "", false, false);
// Path to a file
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "/path/to/file", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com/path/to/file"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com/path/to/"), &context));
- EXPECT_FALSE(
- Allow(source, GURL("http://a.com/path/to/file/subpath"), &context));
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://a.com/path/to/file"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com/path/to/"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com/path/to/file/subpath"),
+ *self_source));
EXPECT_FALSE(
- Allow(source, GURL("http://a.com/path/to/something"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com/"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
+ Allow(*source, GURL("http://a.com/path/to/something"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com/"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *self_source));
}
// Path to a directory
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "/path/to/", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com/path/to/file"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com/path/to/"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com/path/"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com/path/to"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com/path/to"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com/"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://a.com/path/to/file"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com/path/to/"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com/path/"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com/path/to"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com/path/to"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com/"), *self_source));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com"), *self_source));
}
// Empty path
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com/path/to/file"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com/path/to/"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com/"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://a.com/path/to/file"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com/path/to/"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com/"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *self_source));
}
// Almost empty path
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "/", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com/path/to/file"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com/path/to/"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com/"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com"), &context));
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://a.com/path/to/file"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com/path/to/"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com/"), *self_source));
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com"), *self_source));
}
// Path encoded.
@@ -298,29 +327,39 @@ TEST(CSPSourceTest, AllowPath) {
auto source = network::mojom::CSPSource::New(
"http", "a.com", url::PORT_UNSPECIFIED, "/Hello Günter", false, false);
EXPECT_TRUE(
- Allow(source, GURL("http://a.com/Hello%20G%C3%BCnter"), &context));
- EXPECT_TRUE(Allow(source, GURL("http://a.com/Hello Günter"), &context));
+ Allow(*source, GURL("http://a.com/Hello%20G%C3%BCnter"), *self_source));
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://a.com/Hello Günter"), *self_source));
}
// Host is * but path is specified.
{
auto source = network::mojom::CSPSource::New(
"http", "", url::PORT_UNSPECIFIED, "/allowed-path", true, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com/allowed-path"), &context));
- EXPECT_FALSE(Allow(source, GURL("http://a.com/disallowed-path"), &context));
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://a.com/allowed-path"), *self_source));
+ EXPECT_FALSE(
+ Allow(*source, GURL("http://a.com/disallowed-path"), *self_source));
}
}
TEST(CSPSourceTest, RedirectMatching) {
- CSPContext context;
auto source = network::mojom::CSPSource::New("http", "a.com", 8000, "/bar/",
false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com:8000/"), &context, true));
- EXPECT_TRUE(Allow(source, GURL("http://a.com:8000/foo"), &context, true));
- EXPECT_FALSE(Allow(source, GURL("https://a.com:8000/foo"), &context, true));
+
+ // Self doesn't match anything.
+ auto self_source = network::mojom::CSPSource::New(
+ "", "", url::PORT_UNSPECIFIED, "", false, false);
+
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com:8000/"), *self_source, true));
+ EXPECT_TRUE(
+ Allow(*source, GURL("http://a.com:8000/foo"), *self_source, true));
+ EXPECT_FALSE(
+ Allow(*source, GURL("https://a.com:8000/foo"), *self_source, true));
EXPECT_FALSE(
- Allow(source, GURL("http://not-a.com:8000/foo"), &context, true));
- EXPECT_FALSE(Allow(source, GURL("http://a.com:9000/foo/"), &context, false));
+ Allow(*source, GURL("http://not-a.com:8000/foo"), *self_source, true));
+ EXPECT_FALSE(
+ Allow(*source, GURL("http://a.com:9000/foo/"), *self_source, false));
}
TEST(CSPSourceTest, Intersect) {
@@ -373,14 +412,14 @@ TEST(CSPSourceTest, Intersect) {
auto a = CSPSource(test.a);
auto b = CSPSource(test.b);
- auto a_intersect_b = CSPSourcesIntersect(a, b);
- auto b_intersect_a = CSPSourcesIntersect(b, a);
+ auto a_intersect_b = CSPSourcesIntersect(*a, *b);
+ auto b_intersect_a = CSPSourcesIntersect(*b, *a);
if (test.intersection) {
- EXPECT_EQ(test.intersection, ToString(a_intersect_b))
+ EXPECT_EQ(test.intersection, ToString(*a_intersect_b))
<< "The intersection of " << test.a << " and " << test.b
<< " should be " << test.intersection;
// Intersection should be symmetric.
- EXPECT_EQ(test.intersection, ToString(b_intersect_a))
+ EXPECT_EQ(test.intersection, ToString(*b_intersect_a))
<< "The intersection of " << test.b << " and " << test.a
<< " should be " << test.intersection;
} else {
@@ -416,9 +455,9 @@ TEST(CSPSourceTest, DoesNotSubsume) {
auto a = CSPSource(test.a);
auto b = CSPSource(test.b);
- EXPECT_FALSE(CSPSourceSubsumes(a, b))
+ EXPECT_FALSE(CSPSourceSubsumes(*a, *b))
<< test.a << " should not subsume " << test.b;
- EXPECT_FALSE(CSPSourceSubsumes(b, a))
+ EXPECT_FALSE(CSPSourceSubsumes(*b, *a))
<< test.b << " should not subsume " << test.a;
}
}
@@ -466,22 +505,22 @@ TEST(CSPSourceTest, Subsumes) {
auto a = CSPSource(test.a);
auto b = CSPSource(test.b);
- EXPECT_EQ(CSPSourceSubsumes(a, b), test.expected_a_subsumes_b)
+ EXPECT_EQ(CSPSourceSubsumes(*a, *b), test.expected_a_subsumes_b)
<< test.a << " subsumes " << test.b << " should return "
<< test.expected_a_subsumes_b;
- EXPECT_EQ(CSPSourceSubsumes(b, a), test.expected_b_subsumes_a)
+ EXPECT_EQ(CSPSourceSubsumes(*b, *a), test.expected_b_subsumes_a)
<< test.b << " subsumes " << test.a << " should return "
<< test.expected_b_subsumes_a;
a->is_host_wildcard = true;
- EXPECT_FALSE(CSPSourceSubsumes(b, a))
- << test.b << " should not subsume " << ToString(a);
+ EXPECT_FALSE(CSPSourceSubsumes(*b, *a))
+ << test.b << " should not subsume " << ToString(*a);
// If also |b| has a wildcard host, then the result should be the expected
// one.
b->is_host_wildcard = true;
- EXPECT_EQ(CSPSourceSubsumes(b, a), test.expected_b_subsumes_a)
- << ToString(b) << " subsumes " << ToString(a) << " should return "
+ EXPECT_EQ(CSPSourceSubsumes(*b, *a), test.expected_b_subsumes_a)
+ << ToString(*b) << " subsumes " << ToString(*a) << " should return "
<< test.expected_b_subsumes_a;
}
}
@@ -498,21 +537,21 @@ TEST(CSPSourceTest, HostWildcardSubsumes) {
auto source_d = CSPSource(d);
// *.example.com subsumes www.example.com.
- EXPECT_TRUE(CSPSourceSubsumes(source_a, source_b))
+ EXPECT_TRUE(CSPSourceSubsumes(*source_a, *source_b))
<< a << " should subsume " << b;
- EXPECT_FALSE(CSPSourceSubsumes(source_b, source_a))
+ EXPECT_FALSE(CSPSourceSubsumes(*source_b, *source_a))
<< b << " should not subsume " << a;
// *.example.com and example.com have no relations.
- EXPECT_FALSE(CSPSourceSubsumes(source_a, source_c))
+ EXPECT_FALSE(CSPSourceSubsumes(*source_a, *source_c))
<< a << " should not subsume " << c;
- EXPECT_FALSE(CSPSourceSubsumes(source_c, source_a))
+ EXPECT_FALSE(CSPSourceSubsumes(*source_c, *source_a))
<< c << " should not subsume " << a;
// https://*.example.com and http://www.example.com have no relations.
- EXPECT_FALSE(CSPSourceSubsumes(source_d, source_b))
+ EXPECT_FALSE(CSPSourceSubsumes(*source_d, *source_b))
<< d << " should not subsume " << b;
- EXPECT_FALSE(CSPSourceSubsumes(source_b, source_d))
+ EXPECT_FALSE(CSPSourceSubsumes(*source_b, *source_d))
<< b << " should not subsume " << d;
}
@@ -525,15 +564,15 @@ TEST(CSPSourceTest, PortWildcardSubsumes) {
auto source_b = CSPSource(b);
auto source_c = CSPSource(c);
- EXPECT_TRUE(CSPSourceSubsumes(source_a, source_b))
+ EXPECT_TRUE(CSPSourceSubsumes(*source_a, *source_b))
<< a << " should subsume " << b;
- EXPECT_FALSE(CSPSourceSubsumes(source_b, source_a))
+ EXPECT_FALSE(CSPSourceSubsumes(*source_b, *source_a))
<< b << " should not subsume " << a;
// https://example.com:* and http://example.com have no relations.
- EXPECT_FALSE(CSPSourceSubsumes(source_b, source_c))
+ EXPECT_FALSE(CSPSourceSubsumes(*source_b, *source_c))
<< b << " should not subsume " << c;
- EXPECT_FALSE(CSPSourceSubsumes(source_c, source_b))
+ EXPECT_FALSE(CSPSourceSubsumes(*source_c, *source_b))
<< c << " should not subsume " << b;
}
@@ -564,7 +603,7 @@ TEST(CSPSourceTest, SchemesOnlySubsumes) {
for (const auto& test : cases) {
auto source_a = CSPSource(test.a);
auto source_b = CSPSource(test.b);
- EXPECT_EQ(CSPSourceSubsumes(source_a, source_b), test.expected)
+ EXPECT_EQ(CSPSourceSubsumes(*source_a, *source_b), test.expected)
<< test.a << " subsumes " << test.b << " should return "
<< test.expected;
}
@@ -574,54 +613,58 @@ TEST(CSPSourceTest, ToString) {
{
auto source = network::mojom::CSPSource::New(
"http", "", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_EQ("http:", ToString(source));
+ EXPECT_EQ("http:", ToString(*source));
}
{
auto source = network::mojom::CSPSource::New(
"http", "a.com", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_EQ("http://a.com", ToString(source));
+ EXPECT_EQ("http://a.com", ToString(*source));
}
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "", false, false);
- EXPECT_EQ("a.com", ToString(source));
+ EXPECT_EQ("a.com", ToString(*source));
}
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "", true, false);
- EXPECT_EQ("*.a.com", ToString(source));
+ EXPECT_EQ("*.a.com", ToString(*source));
}
{
auto source = network::mojom::CSPSource::New("", "", url::PORT_UNSPECIFIED,
"", true, false);
- EXPECT_EQ("*", ToString(source));
+ EXPECT_EQ("*", ToString(*source));
}
{
auto source =
network::mojom::CSPSource::New("", "a.com", 80, "", false, false);
- EXPECT_EQ("a.com:80", ToString(source));
+ EXPECT_EQ("a.com:80", ToString(*source));
}
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "", false, true);
- EXPECT_EQ("a.com:*", ToString(source));
+ EXPECT_EQ("a.com:*", ToString(*source));
}
{
auto source = network::mojom::CSPSource::New(
"", "a.com", url::PORT_UNSPECIFIED, "/path", false, false);
- EXPECT_EQ("a.com/path", ToString(source));
+ EXPECT_EQ("a.com/path", ToString(*source));
}
}
TEST(CSPSourceTest, UpgradeRequests) {
- CSPContext context;
auto source =
network::mojom::CSPSource::New("http", "a.com", 80, "", false, false);
- EXPECT_TRUE(Allow(source, GURL("http://a.com:80"), &context, true));
- EXPECT_FALSE(Allow(source, GURL("https://a.com:80"), &context, true));
- EXPECT_FALSE(Allow(source, GURL("http://a.com:443"), &context, true));
- EXPECT_TRUE(Allow(source, GURL("https://a.com:443"), &context, true));
- EXPECT_TRUE(Allow(source, GURL("https://a.com"), &context, true));
+
+ // Self doesn't match anything.
+ auto self_source = network::mojom::CSPSource::New(
+ "", "", url::PORT_UNSPECIFIED, "", false, false);
+
+ EXPECT_TRUE(Allow(*source, GURL("http://a.com:80"), *self_source, true));
+ EXPECT_FALSE(Allow(*source, GURL("https://a.com:80"), *self_source, true));
+ EXPECT_FALSE(Allow(*source, GURL("http://a.com:443"), *self_source, true));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com:443"), *self_source, true));
+ EXPECT_TRUE(Allow(*source, GURL("https://a.com"), *self_source, true));
}
} // namespace content
diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
index 215258c78ac..da8102781ae 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -320,6 +320,35 @@ bool StructTraits<network::mojom::CookieSameSiteContextDataView,
return true;
}
+bool EnumTraits<network::mojom::SamePartyCookieContextType,
+ net::CookieOptions::SamePartyCookieContextType>::
+ FromMojom(network::mojom::SamePartyCookieContextType context_type,
+ net::CookieOptions::SamePartyCookieContextType* out) {
+ switch (context_type) {
+ case network::mojom::SamePartyCookieContextType::kCrossParty:
+ *out = net::CookieOptions::SamePartyCookieContextType::kCrossParty;
+ return true;
+ case network::mojom::SamePartyCookieContextType::kSameParty:
+ *out = net::CookieOptions::SamePartyCookieContextType::kSameParty;
+ return true;
+ }
+ return false;
+}
+
+network::mojom::SamePartyCookieContextType
+EnumTraits<network::mojom::SamePartyCookieContextType,
+ net::CookieOptions::SamePartyCookieContextType>::
+ ToMojom(net::CookieOptions::SamePartyCookieContextType context_type) {
+ switch (context_type) {
+ case net::CookieOptions::SamePartyCookieContextType::kCrossParty:
+ return network::mojom::SamePartyCookieContextType::kCrossParty;
+ case net::CookieOptions::SamePartyCookieContextType::kSameParty:
+ return network::mojom::SamePartyCookieContextType::kSameParty;
+ }
+ NOTREACHED();
+ return network::mojom::SamePartyCookieContextType::kCrossParty;
+}
+
bool StructTraits<network::mojom::CookieOptionsDataView, net::CookieOptions>::
Read(network::mojom::CookieOptionsDataView mojo_options,
net::CookieOptions* cookie_options) {
@@ -343,17 +372,18 @@ bool StructTraits<network::mojom::CookieOptionsDataView, net::CookieOptions>::
else
cookie_options->unset_return_excluded_cookies();
- base::Optional<std::vector<net::SchemefulSite>> mojo_full_party_context;
- if (!mojo_options.ReadFullPartyContext(&mojo_full_party_context))
+ net::CookieOptions::SamePartyCookieContextType same_party_cookie_context_type;
+ if (!mojo_options.ReadSamePartyCookieContextType(
+ &same_party_cookie_context_type))
return false;
- base::Optional<std::set<net::SchemefulSite>> full_party_context;
- if (mojo_full_party_context.has_value()) {
- full_party_context.emplace(mojo_full_party_context->begin(),
- mojo_full_party_context->end());
- if (mojo_full_party_context->size() != full_party_context->size())
- return false;
- }
- cookie_options->set_full_party_context(full_party_context);
+ cookie_options->set_same_party_cookie_context_type(
+ same_party_cookie_context_type);
+
+ cookie_options->set_full_party_context_size(
+ mojo_options.full_party_context_size());
+
+ cookie_options->set_is_in_nontrivial_first_party_set(
+ mojo_options.is_in_nontrivial_first_party_set());
return true;
}
@@ -457,7 +487,8 @@ bool StructTraits<
if (!c.ReadAccessSemantics(&access_semantics))
return false;
- *out = {effective_same_site, status, access_semantics};
+ *out = {effective_same_site, status, access_semantics,
+ c.is_allowed_to_access_secure_cookies()};
return true;
}
diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
index cde54d9247c..d8cd73f3e66 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
@@ -13,13 +13,8 @@
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_options.h"
-#include "services/network/public/cpp/schemeful_site_mojom_traits.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
-namespace net {
-class SchemefulSite;
-} // namespace net
-
namespace mojo {
template <>
@@ -100,6 +95,16 @@ struct StructTraits<network::mojom::CookieSameSiteContextDataView,
};
template <>
+struct EnumTraits<network::mojom::SamePartyCookieContextType,
+ net::CookieOptions::SamePartyCookieContextType> {
+ static network::mojom::SamePartyCookieContextType ToMojom(
+ net::CookieOptions::SamePartyCookieContextType context_type);
+
+ static bool FromMojom(network::mojom::SamePartyCookieContextType context_type,
+ net::CookieOptions::SamePartyCookieContextType* out);
+};
+
+template <>
struct StructTraits<network::mojom::CookieOptionsDataView, net::CookieOptions> {
static bool exclude_httponly(const net::CookieOptions& o) {
return o.exclude_httponly();
@@ -115,9 +120,17 @@ struct StructTraits<network::mojom::CookieOptionsDataView, net::CookieOptions> {
return o.return_excluded_cookies();
}
- static const base::Optional<std::set<net::SchemefulSite>>& full_party_context(
- const net::CookieOptions& o) {
- return o.full_party_context();
+ static net::CookieOptions::SamePartyCookieContextType
+ same_party_cookie_context_type(const net::CookieOptions& o) {
+ return o.same_party_cookie_context_type();
+ }
+
+ static uint32_t full_party_context_size(const net::CookieOptions& o) {
+ return o.full_party_context_size();
+ }
+
+ static bool is_in_nontrivial_first_party_set(const net::CookieOptions& o) {
+ return o.is_in_nontrivial_first_party_set();
}
static bool Read(network::mojom::CookieOptionsDataView mojo_options,
@@ -217,6 +230,10 @@ struct StructTraits<network::mojom::CookieAccessResultDataView,
const net::CookieAccessResult& c) {
return c.access_semantics;
}
+ static bool is_allowed_to_access_secure_cookies(
+ const net::CookieAccessResult& c) {
+ return c.is_allowed_to_access_secure_cookies;
+ }
static bool Read(network::mojom::CookieAccessResultDataView access_result,
net::CookieAccessResult* out);
};
diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
index 639592a4392..6164206812a 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
@@ -4,13 +4,11 @@
#include "services/network/public/cpp/cookie_manager_mojom_traits.h"
-#include <set>
#include <vector>
#include "base/test/gtest_util.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/test_support/test_utils.h"
-#include "net/base/schemeful_site.h"
#include "net/cookies/cookie_constants.h"
#include "services/network/public/cpp/cookie_manager_mojom_traits.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
@@ -20,14 +18,8 @@
namespace network {
namespace {
-template <typename MojoType, typename NativeType>
-bool SerializeAndDeserializeEnum(NativeType in, NativeType* out) {
- MojoType intermediate = mojo::EnumTraits<MojoType, NativeType>::ToMojom(in);
- return mojo::EnumTraits<MojoType, NativeType>::FromMojom(intermediate, out);
-}
-
TEST(CookieManagerTraitsTest, Roundtrips_CanonicalCookie) {
- net::CanonicalCookie original(
+ auto original = net::CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false,
false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW,
false, net::CookieSourceScheme::kSecure, 8433);
@@ -35,57 +27,60 @@ TEST(CookieManagerTraitsTest, Roundtrips_CanonicalCookie) {
net::CanonicalCookie copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
- &original, &copied));
-
- EXPECT_EQ(original.Name(), copied.Name());
- EXPECT_EQ(original.Value(), copied.Value());
- EXPECT_EQ(original.Domain(), copied.Domain());
- EXPECT_EQ(original.Path(), copied.Path());
- EXPECT_EQ(original.CreationDate(), copied.CreationDate());
- EXPECT_EQ(original.LastAccessDate(), copied.LastAccessDate());
- EXPECT_EQ(original.ExpiryDate(), copied.ExpiryDate());
- EXPECT_EQ(original.IsSecure(), copied.IsSecure());
- EXPECT_EQ(original.IsHttpOnly(), copied.IsHttpOnly());
- EXPECT_EQ(original.SameSite(), copied.SameSite());
- EXPECT_EQ(original.Priority(), copied.Priority());
- EXPECT_EQ(original.IsSameParty(), copied.IsSameParty());
- EXPECT_EQ(original.SourceScheme(), copied.SourceScheme());
- EXPECT_EQ(original.SourcePort(), copied.SourcePort());
+ *original, copied));
+
+ EXPECT_EQ(original->Name(), copied.Name());
+ EXPECT_EQ(original->Value(), copied.Value());
+ EXPECT_EQ(original->Domain(), copied.Domain());
+ EXPECT_EQ(original->Path(), copied.Path());
+ EXPECT_EQ(original->CreationDate(), copied.CreationDate());
+ EXPECT_EQ(original->LastAccessDate(), copied.LastAccessDate());
+ EXPECT_EQ(original->ExpiryDate(), copied.ExpiryDate());
+ EXPECT_EQ(original->IsSecure(), copied.IsSecure());
+ EXPECT_EQ(original->IsHttpOnly(), copied.IsHttpOnly());
+ EXPECT_EQ(original->SameSite(), copied.SameSite());
+ EXPECT_EQ(original->Priority(), copied.Priority());
+ EXPECT_EQ(original->IsSameParty(), copied.IsSameParty());
+ EXPECT_EQ(original->SourceScheme(), copied.SourceScheme());
+ EXPECT_EQ(original->SourcePort(), copied.SourcePort());
// Test port edge cases: unspecified.
- net::CanonicalCookie original_unspecified(
- "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false,
- false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW,
- false, net::CookieSourceScheme::kSecure, url::PORT_UNSPECIFIED);
+ auto original_unspecified =
+ net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
+ false, false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_LOW, false, net::CookieSourceScheme::kSecure,
+ url::PORT_UNSPECIFIED);
net::CanonicalCookie copied_unspecified;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
- &original_unspecified, &copied_unspecified));
+ *original_unspecified, copied_unspecified));
- EXPECT_EQ(original_unspecified.SourcePort(), copied_unspecified.SourcePort());
+ EXPECT_EQ(original_unspecified->SourcePort(),
+ copied_unspecified.SourcePort());
// Test port edge cases: invalid.
- net::CanonicalCookie original_invalid(
+ auto original_invalid = net::CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false,
false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW,
false, net::CookieSourceScheme::kSecure, url::PORT_INVALID);
net::CanonicalCookie copied_invalid;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
- &original_invalid, &copied_invalid));
+ *original_invalid, copied_invalid));
- EXPECT_EQ(original_invalid.SourcePort(), copied_invalid.SourcePort());
+ EXPECT_EQ(original_invalid->SourcePort(), copied_invalid.SourcePort());
// Serializer returns false if cookie is non-canonical.
// Example is non-canonical because of newline in name.
- original = net::CanonicalCookie("A\n", "B", "x.y", "/path", base::Time(),
- base::Time(), base::Time(), false, false,
- net::CookieSameSite::NO_RESTRICTION,
- net::COOKIE_PRIORITY_LOW, false);
+ original = net::CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A\n", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
+ false, false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_LOW, false);
EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
- &original, &copied));
+ *original, copied));
}
TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
@@ -105,7 +100,7 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
net::CookieInclusionStatus copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieInclusionStatus>(
- &original, &copied));
+ original, copied));
EXPECT_TRUE(copied.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
net::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
@@ -121,10 +116,10 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
EXPECT_FALSE(
mojo::test::SerializeAndDeserialize<mojom::CookieInclusionStatus>(
- &invalid, &copied));
+ invalid, copied));
}
-TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) {
+TEST(CookieManagerTraitsTest, Roundtrips_CookieAccessResult) {
net::CookieAccessResult original = net::CookieAccessResult(
net::CookieEffectiveSameSite::LAX_MODE,
net::CookieInclusionStatus(
@@ -132,11 +127,12 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) {
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
net::CookieInclusionStatus::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
- net::CookieAccessSemantics::LEGACY);
+ net::CookieAccessSemantics::LEGACY,
+ true /* is_allowed_to_access_secure_cookies */);
net::CookieAccessResult copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieAccessResult>(
- &original, &copied));
+ original, copied));
EXPECT_EQ(original.effective_same_site, copied.effective_same_site);
EXPECT_TRUE(copied.status.HasExactlyExclusionReasonsForTesting(
@@ -145,21 +141,23 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) {
EXPECT_TRUE(copied.status.HasExactlyWarningReasonsForTesting(
{net::CookieInclusionStatus::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
+ EXPECT_EQ(original.is_allowed_to_access_secure_cookies,
+ copied.is_allowed_to_access_secure_cookies);
}
TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) {
- net::CanonicalCookie original_cookie(
+ auto original_cookie = net::CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
- /* secure = */ true, /* http_only = */ false,
+ /* secure = */ true, /* httponly = */ false,
net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, false);
- net::CookieWithAccessResult original = {original_cookie,
+ net::CookieWithAccessResult original = {*original_cookie,
net::CookieAccessResult()};
net::CookieWithAccessResult copied;
EXPECT_TRUE(
mojo::test::SerializeAndDeserialize<mojom::CookieWithAccessResult>(
- &original, &copied));
+ original, copied));
EXPECT_EQ(original.cookie.Name(), copied.cookie.Name());
EXPECT_EQ(original.cookie.Value(), copied.cookie.Value());
@@ -178,19 +176,19 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) {
EXPECT_EQ(original.access_result.status, copied.access_result.status);
}
-TEST(CookieManagerTraitsTest, Rountrips_CookieAndLineWithAccessResult) {
- net::CanonicalCookie original_cookie(
+TEST(CookieManagerTraitsTest, Roundtrips_CookieAndLineWithAccessResult) {
+ auto original_cookie = net::CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
- /* secure = */ true, /* http_only = */ false,
+ /* secure = */ true, /* httponly = */ false,
net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, false);
- net::CookieAndLineWithAccessResult original(original_cookie, "cookie-string",
+ net::CookieAndLineWithAccessResult original(*original_cookie, "cookie-string",
net::CookieAccessResult());
net::CookieAndLineWithAccessResult copied;
EXPECT_TRUE(
mojo::test::SerializeAndDeserialize<mojom::CookieAndLineWithAccessResult>(
- &original, &copied));
+ original, copied));
EXPECT_EQ(original.cookie->Name(), copied.cookie->Name());
EXPECT_EQ(original.cookie->Value(), copied.cookie->Value());
@@ -213,8 +211,8 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieSameSite) {
{net::CookieSameSite::NO_RESTRICTION, net::CookieSameSite::LAX_MODE,
net::CookieSameSite::STRICT_MODE, net::CookieSameSite::UNSPECIFIED}) {
net::CookieSameSite roundtrip;
- ASSERT_TRUE(SerializeAndDeserializeEnum<mojom::CookieSameSite>(cookie_state,
- &roundtrip));
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieSameSite>(
+ cookie_state, roundtrip));
EXPECT_EQ(cookie_state, roundtrip);
}
}
@@ -227,8 +225,9 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieEffectiveSameSite) {
net::CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
net::CookieEffectiveSameSite::UNDEFINED}) {
net::CookieEffectiveSameSite roundtrip;
- ASSERT_TRUE(SerializeAndDeserializeEnum<mojom::CookieEffectiveSameSite>(
- cookie_state, &roundtrip));
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::CookieEffectiveSameSite>(
+ cookie_state, roundtrip));
EXPECT_EQ(cookie_state, roundtrip);
}
}
@@ -239,8 +238,8 @@ TEST(CookieManagerTraitsTest, Roundtrips_ContextType) {
{ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_STRICT}) {
ContextType roundtrip;
- ASSERT_TRUE(SerializeAndDeserializeEnum<mojom::ContextType>(context_type,
- &roundtrip));
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::ContextType>(
+ context_type, roundtrip));
EXPECT_EQ(context_type, roundtrip);
}
}
@@ -251,12 +250,24 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieAccessSemantics) {
net::CookieAccessSemantics::NONLEGACY,
net::CookieAccessSemantics::LEGACY}) {
net::CookieAccessSemantics roundtrip;
- ASSERT_TRUE(SerializeAndDeserializeEnum<mojom::CookieAccessSemantics>(
- access_semantics, &roundtrip));
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::CookieAccessSemantics>(
+ access_semantics, roundtrip));
EXPECT_EQ(access_semantics, roundtrip);
}
}
+TEST(CookieManagerTraitsTest, Roundtrips_CookieSourceScheme) {
+ for (net::CookieSourceScheme source_scheme :
+ {net::CookieSourceScheme::kUnset, net::CookieSourceScheme::kNonSecure,
+ net::CookieSourceScheme::kSecure}) {
+ net::CookieSourceScheme roundtrip;
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieSourceScheme>(
+ source_scheme, roundtrip));
+ EXPECT_EQ(source_scheme, roundtrip);
+ }
+}
+
TEST(CookieManagerTraitsTest, Roundtrips_CookieChangeCause) {
for (net::CookieChangeCause change_cause :
{net::CookieChangeCause::INSERTED, net::CookieChangeCause::EXPLICIT,
@@ -265,8 +276,8 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieChangeCause) {
net::CookieChangeCause::EVICTED,
net::CookieChangeCause::EXPIRED_OVERWRITE}) {
net::CookieChangeCause roundtrip;
- ASSERT_TRUE(SerializeAndDeserializeEnum<mojom::CookieChangeCause>(
- change_cause, &roundtrip));
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieChangeCause>(
+ change_cause, roundtrip));
EXPECT_EQ(change_cause, roundtrip);
}
}
@@ -288,7 +299,7 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieSameSiteContext) {
EXPECT_EQ(
mojo::test::SerializeAndDeserialize<mojom::CookieSameSiteContext>(
- &context_in, &copy),
+ context_in, copy),
schemeful_context_type <= context_type);
if (schemeful_context_type <= context_type)
@@ -297,90 +308,82 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieSameSiteContext) {
}
}
+TEST(CookieManagerTraitsTest, Roundtrips_SamePartyCookieContextType) {
+ using ContextType = net::CookieOptions::SamePartyCookieContextType;
+ for (ContextType context_type :
+ {ContextType::kCrossParty, ContextType::kSameParty}) {
+ ContextType roundtrip;
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::SamePartyCookieContextType>(
+ context_type, roundtrip));
+ EXPECT_EQ(context_type, roundtrip);
+ }
+}
+
TEST(CookieManagerTraitsTest, Roundtrips_CookieOptions) {
{
net::CookieOptions least_trusted, copy;
EXPECT_FALSE(least_trusted.return_excluded_cookies());
-
least_trusted.set_return_excluded_cookies(); // differ from default.
+ least_trusted.set_full_party_context_size(10u);
+ least_trusted.set_is_in_nontrivial_first_party_set(
+ true); // differ from default.
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieOptions>(
- &least_trusted, &copy));
+ least_trusted, copy));
EXPECT_TRUE(copy.exclude_httponly());
EXPECT_EQ(
net::CookieOptions::SameSiteCookieContext(
net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE),
copy.same_site_cookie_context());
EXPECT_TRUE(copy.return_excluded_cookies());
+ EXPECT_EQ(net::CookieOptions::SamePartyCookieContextType::kCrossParty,
+ copy.same_party_cookie_context_type());
+ EXPECT_EQ(10u, copy.full_party_context_size());
+ EXPECT_TRUE(copy.is_in_nontrivial_first_party_set());
}
{
net::CookieOptions very_trusted, copy;
- auto kPartyContext = std::set<net::SchemefulSite>{
- net::SchemefulSite(url::Origin::Create(GURL("https://a.test")))};
very_trusted.set_include_httponly();
very_trusted.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
- very_trusted.set_full_party_context(kPartyContext);
+ very_trusted.set_same_party_cookie_context_type(
+ net::CookieOptions::SamePartyCookieContextType::kSameParty);
+ very_trusted.set_full_party_context_size(1u);
+ very_trusted.set_is_in_nontrivial_first_party_set(true);
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieOptions>(
- &very_trusted, &copy));
+ very_trusted, copy));
EXPECT_FALSE(copy.exclude_httponly());
EXPECT_EQ(net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
copy.same_site_cookie_context());
EXPECT_FALSE(copy.return_excluded_cookies());
- EXPECT_EQ(kPartyContext, copy.full_party_context());
- }
-}
-
-TEST(CookieManagerTraitsTest, Roundtrips_FullPartyContext) {
- {
- std::vector<std::set<net::SchemefulSite>> kTestCases = {
- std::set<net::SchemefulSite>(),
- std::set<net::SchemefulSite>{net::SchemefulSite()},
- std::set<net::SchemefulSite>{
- net::SchemefulSite(url::Origin::Create(GURL("https://a.test")))},
- std::set<net::SchemefulSite>{
- net::SchemefulSite(url::Origin::Create(GURL("http://a.test"))),
- net::SchemefulSite(url::Origin::Create(GURL("http://b.test")))},
- };
-
- for (const std::set<net::SchemefulSite>& fpc : kTestCases) {
- net::CookieOptions options, copy;
- options.set_full_party_context(fpc);
- EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieOptions>(
- &options, &copy));
- EXPECT_EQ(fpc, copy.full_party_context());
- }
- }
- {
- base::Optional<std::set<net::SchemefulSite>> kFullPartyContext =
- base::nullopt;
- net::CookieOptions options, copy;
- options.set_full_party_context(kFullPartyContext);
- EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieOptions>(
- &options, &copy));
- EXPECT_EQ(kFullPartyContext, copy.full_party_context());
+ EXPECT_EQ(net::CookieOptions::SamePartyCookieContextType::kSameParty,
+ copy.same_party_cookie_context_type());
+ EXPECT_EQ(1u, copy.full_party_context_size());
+ EXPECT_TRUE(copy.is_in_nontrivial_first_party_set());
}
}
TEST(CookieManagerTraitsTest, Roundtrips_CookieChangeInfo) {
- net::CanonicalCookie original_cookie(
+ auto original_cookie = net::CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
- /* secure = */ false, /* http_only = */ false,
+ /* secure = */ false, /* httponly = */ false,
net::CookieSameSite::UNSPECIFIED, net::COOKIE_PRIORITY_LOW, false);
net::CookieChangeInfo original(
- original_cookie,
+ *original_cookie,
net::CookieAccessResult(net::CookieEffectiveSameSite::UNDEFINED,
net::CookieInclusionStatus(),
- net::CookieAccessSemantics::LEGACY),
+ net::CookieAccessSemantics::LEGACY,
+ false /* is_allowed_to_access_secure_cookies */),
net::CookieChangeCause::EXPLICIT);
net::CookieChangeInfo copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieChangeInfo>(
- &original, &copied));
+ original, copied));
EXPECT_EQ(original.cookie.Name(), copied.cookie.Name());
EXPECT_EQ(original.cookie.Value(), copied.cookie.Value());
diff --git a/chromium/services/network/public/cpp/cors/cors.cc b/chromium/services/network/public/cpp/cors/cors.cc
index 7189eaa1871..f148465db9e 100644
--- a/chromium/services/network/public/cpp/cors/cors.cc
+++ b/chromium/services/network/public/cpp/cors/cors.cc
@@ -473,10 +473,11 @@ bool IsCorsSafelistedHeader(const std::string& name, const std::string& value) {
}
if (lower_name == "accept-language" || lower_name == "content-language") {
- return (value.end() == std::find_if(value.begin(), value.end(), [](char c) {
- return !isalnum(c) && c != 0x20 && c != 0x2a && c != 0x2c &&
- c != 0x2d && c != 0x2e && c != 0x3b && c != 0x3d;
- }));
+ return std::all_of(value.begin(), value.end(), [](char c) {
+ return (0x30 <= c && c <= 0x39) || (0x41 <= c && c <= 0x5a) ||
+ (0x61 <= c && c <= 0x7a) || c == 0x20 || c == 0x2a || c == 0x2c ||
+ c == 0x2d || c == 0x2e || c == 0x3b || c == 0x3d;
+ });
}
if (lower_name == "content-type")
diff --git a/chromium/services/network/public/cpp/cors/cors_legacy.cc b/chromium/services/network/public/cpp/cors/cors_legacy.cc
deleted file mode 100644
index f01af63619b..00000000000
--- a/chromium/services/network/public/cpp/cors/cors_legacy.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/public/cpp/cors/cors_legacy.h"
-
-#include <algorithm>
-
-#include "url/gurl.h"
-#include "url/url_util.h"
-
-namespace {
-
-std::vector<std::string>* secure_origins = nullptr;
-
-} // namespace
-
-namespace network {
-
-namespace cors {
-
-namespace legacy {
-
-void RegisterSecureOrigins(const std::vector<std::string>& origins) {
- delete secure_origins;
- secure_origins = new std::vector<std::string>(origins.size());
- std::copy(origins.begin(), origins.end(), secure_origins->begin());
-}
-
-const std::vector<std::string>& GetSecureOrigins() {
- if (!secure_origins)
- secure_origins = new std::vector<std::string>;
- return *secure_origins;
-}
-
-} // namespace legacy
-
-} // namespace cors
-
-} // namespace network
diff --git a/chromium/services/network/public/cpp/cors/cors_legacy.h b/chromium/services/network/public/cpp/cors/cors_legacy.h
deleted file mode 100644
index 6da3b705e1b..00000000000
--- a/chromium/services/network/public/cpp/cors/cors_legacy.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_LEGACY_H_
-#define SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_LEGACY_H_
-
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-
-namespace network {
-namespace cors {
-
-// Functions in namespace legacy are for legacy code path. Pure Network
-// Service code should not use it. Since files in public/cpp/cors are shared
-// between Network Service and legacy code path in content, but Network Service
-// should not know content dependent concepts, we need to provide abstracted
-// interfaces to implement extra checks for the case code runs in content.
-//
-// TODO(toyoshim): Remove all functions after Network Service is enabled.
-namespace legacy {
-
-// Registers allowlisted secure origins and hostname patterns for CORS checks in
-// CorsURLLoader.
-COMPONENT_EXPORT(NETWORK_CPP)
-void RegisterSecureOrigins(const std::vector<std::string>& secure_origins);
-
-// Refers the registered allowlisted secure origins and hostname patterns.
-COMPONENT_EXPORT(NETWORK_CPP)
-const std::vector<std::string>& GetSecureOrigins();
-
-} // namespace legacy
-
-} // namespace cors
-} // namespace network
-
-#endif // SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_LEGACY_H_
diff --git a/chromium/services/network/public/cpp/cors/cors_unittest.cc b/chromium/services/network/public/cpp/cors/cors_unittest.cc
index 2113d78f370..2af600635ac 100644
--- a/chromium/services/network/public/cpp/cors/cors_unittest.cc
+++ b/chromium/services/network/public/cpp/cors/cors_unittest.cc
@@ -6,6 +6,7 @@
#include <limits.h>
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
diff --git a/chromium/services/network/public/cpp/cors/preflight_cache.cc b/chromium/services/network/public/cpp/cors/preflight_cache.cc
deleted file mode 100644
index 0049fa1bc3d..00000000000
--- a/chromium/services/network/public/cpp/cors/preflight_cache.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/public/cpp/cors/preflight_cache.h"
-
-#include <iterator>
-
-#include "base/metrics/histogram_macros.h"
-#include "base/rand_util.h"
-#include "base/time/time.h"
-#include "url/gurl.h"
-
-namespace network {
-
-namespace cors {
-
-namespace {
-
-constexpr size_t kMaxCacheEntries = 1024u;
-constexpr size_t kMaxKeyLength = 1024u;
-constexpr size_t kPurgeUnit = 10u;
-
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class CacheMetric {
- kHitAndPass = 0,
- kHitAndFail = 1,
- kMiss = 2,
- kStale = 3,
-
- kMaxValue = kStale,
-};
-
-void ReportCacheMetric(CacheMetric metric) {
- UMA_HISTOGRAM_ENUMERATION("Net.Cors.PreflightCacheResult", metric);
-}
-
-} // namespace
-
-PreflightCache::PreflightCache() = default;
-PreflightCache::~PreflightCache() = default;
-
-void PreflightCache::AppendEntry(
- const url::Origin& origin,
- const GURL& url,
- const net::NetworkIsolationKey& network_isolation_key,
- std::unique_ptr<PreflightResult> preflight_result) {
- DCHECK(preflight_result);
-
- // Do not cache |preflight_result| if |url| is too long.
- const std::string url_spec = url.spec();
- if (url_spec.length() >= kMaxKeyLength)
- return;
-
- auto key = std::make_tuple(origin, url_spec, network_isolation_key);
- const auto existing_entry = cache_.find(key);
- if (existing_entry == cache_.end()) {
- // Since one new entry is always added below, let's purge one cache entry
- // if cache size is larger than kMaxCacheEntries - 1 so that the size to be
- // kMaxCacheEntries at maximum.
- MayPurge(kMaxCacheEntries - 1, kPurgeUnit);
- }
- UMA_HISTOGRAM_COUNTS_10000("Net.Cors.PreflightCacheKeySize",
- url_spec.length());
-
- cache_[key] = std::move(preflight_result);
-}
-
-bool PreflightCache::CheckIfRequestCanSkipPreflight(
- const url::Origin& origin,
- const GURL& url,
- const net::NetworkIsolationKey& network_isolation_key,
- mojom::CredentialsMode credentials_mode,
- const std::string& method,
- const net::HttpRequestHeaders& request_headers,
- bool is_revalidating) {
- // Check if the entry exists in the cache.
- auto key = std::make_tuple(origin, url.spec(), network_isolation_key);
- auto cache_entry = cache_.find(key);
- if (cache_entry == cache_.end()) {
- ReportCacheMetric(CacheMetric::kMiss);
- return false;
- }
-
- // Check if the entry is still valid.
- if (!cache_entry->second->IsExpired()) {
- // Both |origin| and |url| are in cache. Check if the entry is sufficient to
- // skip CORS-preflight.
- if (cache_entry->second->EnsureAllowedRequest(
- credentials_mode, method, request_headers, is_revalidating)) {
- ReportCacheMetric(CacheMetric::kHitAndPass);
- return true;
- }
- ReportCacheMetric(CacheMetric::kHitAndFail);
- } else {
- ReportCacheMetric(CacheMetric::kStale);
- }
-
- // The cache entry is either stale or not sufficient. Remove the item from the
- // cache.
- cache_.erase(cache_entry);
- return false;
-}
-
-size_t PreflightCache::CountEntriesForTesting() const {
- return cache_.size();
-}
-
-void PreflightCache::MayPurgeForTesting(size_t max_entries, size_t purge_unit) {
- MayPurge(max_entries, purge_unit);
-}
-
-void PreflightCache::MayPurge(size_t max_entries, size_t purge_unit) {
- if (cache_.size() <= max_entries)
- return;
- DCHECK_GE(cache_.size(), purge_unit);
- auto purge_begin_entry = cache_.begin();
- std::advance(purge_begin_entry, base::RandInt(0, cache_.size() - purge_unit));
- auto purge_end_entry = purge_begin_entry;
- std::advance(purge_end_entry, purge_unit);
- cache_.erase(purge_begin_entry, purge_end_entry);
-}
-
-} // namespace cors
-
-} // namespace network
diff --git a/chromium/services/network/public/cpp/cors/preflight_cache.h b/chromium/services/network/public/cpp/cors/preflight_cache.h
deleted file mode 100644
index 1d357965b56..00000000000
--- a/chromium/services/network/public/cpp/cors/preflight_cache.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_
-#define SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <tuple>
-
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "net/base/network_isolation_key.h"
-#include "net/http/http_request_headers.h"
-#include "services/network/public/cpp/cors/preflight_result.h"
-#include "services/network/public/mojom/fetch_api.mojom-shared.h"
-#include "url/origin.h"
-
-class GURL;
-
-namespace network {
-
-namespace cors {
-
-// A class to implement CORS-preflight cache that is defined in the fetch spec,
-// https://fetch.spec.whatwg.org/#concept-cache.
-// TODO(toyoshim): We may consider to clear all cached entries when users'
-// network configuration is changed.
-class COMPONENT_EXPORT(NETWORK_CPP) PreflightCache final {
- public:
- PreflightCache();
- ~PreflightCache();
-
- // Appends new |preflight_result| entry to the cache for a specified |origin|
- // and |url|.
- void AppendEntry(const url::Origin& origin,
- const GURL& url,
- const net::NetworkIsolationKey& network_isolation_key,
- std::unique_ptr<PreflightResult> preflight_result);
-
- // Consults with cached results, and decides if we can skip CORS-preflight or
- // not.
- bool CheckIfRequestCanSkipPreflight(
- const url::Origin& origin,
- const GURL& url,
- const net::NetworkIsolationKey& network_isolation_key,
- mojom::CredentialsMode credentials_mode,
- const std::string& method,
- const net::HttpRequestHeaders& headers,
- bool is_revalidating);
-
- // Counts cached entries for testing.
- size_t CountEntriesForTesting() const;
-
- // Purges one cache entry if number of entries is larger than |max_entries|
- // for testing.
- void MayPurgeForTesting(size_t max_entries, size_t purge_unit);
-
- private:
- void MayPurge(size_t max_entries, size_t purge_unit);
-
- // A map for caching. This is accessed by a tuple of origin,
- // url string, and NetworkIsolationKey to find a cached entry.
- std::map<std::tuple<url::Origin /* origin */,
- std::string /* url */,
- net::NetworkIsolationKey /* NIK */>,
- std::unique_ptr<PreflightResult>>
- cache_;
-
- DISALLOW_COPY_AND_ASSIGN(PreflightCache);
-};
-
-} // namespace cors
-
-} // namespace network
-
-#endif // SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_
diff --git a/chromium/services/network/public/cpp/cors/preflight_cache_unittest.cc b/chromium/services/network/public/cpp/cors/preflight_cache_unittest.cc
deleted file mode 100644
index 5bcbf48538b..00000000000
--- a/chromium/services/network/public/cpp/cors/preflight_cache_unittest.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/public/cpp/cors/preflight_cache.h"
-
-#include "base/test/scoped_feature_list.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/test/task_environment.h"
-#include "base/time/time.h"
-#include "net/base/features.h"
-#include "net/http/http_request_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace network {
-
-namespace cors {
-
-namespace {
-
-class PreflightCacheTest : public testing::Test {
- public:
- PreflightCacheTest() = default;
-
- protected:
- size_t CountEntries() const { return cache_.CountEntriesForTesting(); }
- void MayPurge(size_t max_entries, size_t purge_unit) {
- cache_.MayPurgeForTesting(max_entries, purge_unit);
- }
- PreflightCache* cache() { return &cache_; }
-
- std::unique_ptr<PreflightResult> CreateEntry() {
- return PreflightResult::Create(mojom::CredentialsMode::kInclude,
- std::string("POST"), base::nullopt,
- std::string("5"), nullptr);
- }
-
- void AppendEntry(const url::Origin& origin,
- const GURL& url,
- const net::NetworkIsolationKey& network_isolation_key) {
- cache_.AppendEntry(origin, url, network_isolation_key, CreateEntry());
- }
-
- bool CheckEntryAndRefreshCache(
- const url::Origin& origin,
- const GURL& url,
- const net::NetworkIsolationKey& network_isolation_key) {
- return cache_.CheckIfRequestCanSkipPreflight(
- origin, url, network_isolation_key,
- network::mojom::CredentialsMode::kInclude, "POST",
- net::HttpRequestHeaders(), false);
- }
-
- void Advance(int seconds) {
- clock_.Advance(base::TimeDelta::FromSeconds(seconds));
- }
-
- private:
- // testing::Test implementation.
- void SetUp() override { PreflightResult::SetTickClockForTesting(&clock_); }
- void TearDown() override { PreflightResult::SetTickClockForTesting(nullptr); }
-
- base::test::TaskEnvironment env_;
- PreflightCache cache_;
- base::SimpleTestTickClock clock_;
-};
-
-TEST_F(PreflightCacheTest, CacheSize) {
- const url::Origin origin;
- const url::Origin other_origin =
- url::Origin::Create(GURL("http://www.other.com:80"));
- const GURL url("http://www.test.com/A");
- const GURL other_url("http://www.test.com/B");
-
- EXPECT_EQ(0u, CountEntries());
-
- AppendEntry(origin, url, net::NetworkIsolationKey());
-
- EXPECT_EQ(1u, CountEntries());
-
- AppendEntry(origin, other_url, net::NetworkIsolationKey());
-
- EXPECT_EQ(2u, CountEntries());
-
- AppendEntry(other_origin, url, net::NetworkIsolationKey());
-
- EXPECT_EQ(3u, CountEntries());
-
- // Num of entries is 3, that is not greater than the limit 3u.
- // It results in doing nothing.
- MayPurge(3u, 2u);
- EXPECT_EQ(3u, CountEntries());
-
- // Num of entries is 3, that is greater than the limit 2u.
- // It results in purging entries by the specified unit 2u, thus only one entry
- // remains.
- MayPurge(2u, 2u);
- EXPECT_EQ(1u, CountEntries());
-
- // This will make the cache empty. Note that the cache expects the num of
- // remaining entries should be greater than the specified purge unit.
- MayPurge(0u, 1u);
- EXPECT_EQ(0u, CountEntries());
-}
-
-TEST_F(PreflightCacheTest, CacheTimeout) {
- const url::Origin origin;
- const GURL url("http://www.test.com/A");
- const GURL other_url("http://www.test.com/B");
-
- EXPECT_EQ(0u, CountEntries());
-
- AppendEntry(origin, url, net::NetworkIsolationKey());
- AppendEntry(origin, other_url, net::NetworkIsolationKey());
-
- EXPECT_EQ(2u, CountEntries());
-
- // Cache entry should still be valid.
- EXPECT_TRUE(
- CheckEntryAndRefreshCache(origin, url, net::NetworkIsolationKey()));
-
- // Advance time by ten seconds.
- Advance(10);
-
- // Cache entry should now be expired.
- EXPECT_FALSE(
- CheckEntryAndRefreshCache(origin, url, net::NetworkIsolationKey()));
-
- EXPECT_EQ(1u, CountEntries());
-
- // Cache entry should be expired.
- EXPECT_FALSE(
- CheckEntryAndRefreshCache(origin, other_url, net::NetworkIsolationKey()));
-
- EXPECT_EQ(0u, CountEntries());
-}
-
-TEST_F(PreflightCacheTest, RespectsNetworkIsolationKeys) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- net::features::kAppendFrameOriginToNetworkIsolationKey);
-
- const std::string kOriginStr1("http://www.test.com/A");
- const url::Origin kOrigin1 = url::Origin::Create(GURL(kOriginStr1));
- const net::NetworkIsolationKey kNik(kOrigin1, kOrigin1);
- const GURL kUrl1(kOriginStr1);
-
- const GURL kUrl2("http://www.other.com:80");
-
- // The cache starts empty.
- EXPECT_EQ(0u, CountEntries());
-
- AppendEntry(kOrigin1, kUrl1, net::NetworkIsolationKey());
- EXPECT_EQ(1u, CountEntries());
-
- // This should be indistinguishable from the previous key, so it should not
- // increase the size of the cache.
- AppendEntry(kOrigin1, kUrl1, net::NetworkIsolationKey());
- EXPECT_EQ(1u, CountEntries());
- EXPECT_TRUE(
- CheckEntryAndRefreshCache(kOrigin1, kUrl1, net::NetworkIsolationKey()));
- EXPECT_FALSE(CheckEntryAndRefreshCache(kOrigin1, kUrl1, kNik));
-
- // This uses a different NIK, so it should result in a new entry in the cache.
- AppendEntry(kOrigin1, kUrl1, kNik);
- EXPECT_EQ(2u, CountEntries());
- EXPECT_TRUE(CheckEntryAndRefreshCache(kOrigin1, kUrl1, kNik));
-
- // Check that an entry we never inserted is not found in the cache.
- EXPECT_FALSE(CheckEntryAndRefreshCache(kOrigin1, kUrl2, kNik));
-}
-
-TEST_F(PreflightCacheTest, HandlesOpaqueOrigins) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- net::features::kAppendFrameOriginToNetworkIsolationKey);
-
- const url::Origin kOrigin1;
- const url::Origin kOrigin2;
- const net::NetworkIsolationKey kNik1(kOrigin1, kOrigin1);
- const net::NetworkIsolationKey kNik2(kOrigin2, kOrigin2);
- const GURL kUrl("http://www.test.com/A");
-
- // The cache starts empty.
- EXPECT_EQ(0u, CountEntries());
-
- AppendEntry(kOrigin1, kUrl, kNik1);
- EXPECT_EQ(1u, CountEntries());
- EXPECT_TRUE(CheckEntryAndRefreshCache(kOrigin1, kUrl, kNik1));
-
- // The cache should report a miss if we use a new opaque origin and the same
- // URL and NIK, since the nonces of the origins differ.
- EXPECT_FALSE(CheckEntryAndRefreshCache(url::Origin(), kUrl, kNik1));
-
- // This should be distinguishable from the previous NIK, so it should
- // increase the size of the cache.
- AppendEntry(kOrigin1, kUrl, kNik2);
- EXPECT_EQ(2u, CountEntries());
- EXPECT_TRUE(CheckEntryAndRefreshCache(kOrigin1, kUrl, kNik2));
- EXPECT_FALSE(
- CheckEntryAndRefreshCache(kOrigin1, kUrl, net::NetworkIsolationKey()));
- EXPECT_FALSE(CheckEntryAndRefreshCache(
- kOrigin1, kUrl, net::NetworkIsolationKey(url::Origin(), url::Origin())));
-}
-
-} // namespace
-
-} // namespace cors
-
-} // namespace network
diff --git a/chromium/services/network/public/cpp/cors/preflight_result.cc b/chromium/services/network/public/cpp/cors/preflight_result.cc
deleted file mode 100644
index b31b171b89a..00000000000
--- a/chromium/services/network/public/cpp/cors/preflight_result.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/public/cpp/cors/preflight_result.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/time/default_tick_clock.h"
-#include "base/time/tick_clock.h"
-#include "base/time/time.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_util.h"
-#include "services/network/public/cpp/cors/cors.h"
-
-namespace network {
-
-namespace cors {
-
-namespace {
-
-// Timeout values below are at the discretion of the user agent.
-
-// Default cache expiry time for an entry that does not have
-// Access-Control-Max-Age header in its CORS-preflight response.
-constexpr base::TimeDelta kDefaultTimeout = base::TimeDelta::FromSeconds(5);
-
-// Maximum cache expiry time. Even if a CORS-preflight response contains
-// Access-Control-Max-Age header that specifies a longer expiry time, this
-// maximum time is applied.
-constexpr base::TimeDelta kMaxTimeout = base::TimeDelta::FromHours(2);
-
-// Holds TickClock instance to overwrite TimeTicks::Now() for testing.
-const base::TickClock* tick_clock_for_testing = nullptr;
-
-base::TimeTicks Now() {
- if (tick_clock_for_testing)
- return tick_clock_for_testing->NowTicks();
- return base::TimeTicks::Now();
-}
-
-bool ParseAccessControlMaxAge(const base::Optional<std::string>& max_age,
- base::TimeDelta* expiry_delta) {
- DCHECK(expiry_delta);
-
- if (!max_age)
- return false;
-
- uint64_t delta;
- if (!base::StringToUint64(*max_age, &delta))
- return false;
-
- *expiry_delta = base::TimeDelta::FromSeconds(delta);
- if (*expiry_delta > kMaxTimeout)
- *expiry_delta = kMaxTimeout;
- return true;
-}
-
-// Parses |string| as a Access-Control-Allow-* header value, storing the result
-// in |set|. This function returns false when |string| does not satisfy the
-// syntax here: https://fetch.spec.whatwg.org/#http-new-header-syntax.
-bool ParseAccessControlAllowList(const base::Optional<std::string>& string,
- base::flat_set<std::string>* set,
- bool insert_in_lower_case) {
- DCHECK(set);
-
- if (!string)
- return true;
-
- net::HttpUtil::ValuesIterator it(string->begin(), string->end(), ',', true);
- while (it.GetNext()) {
- base::StringPiece value = it.value_piece();
- if (!net::HttpUtil::IsToken(value)) {
- set->clear();
- return false;
- }
- set->insert(insert_in_lower_case ? base::ToLowerASCII(value)
- : value.as_string());
- }
- return true;
-}
-
-} // namespace
-
-// static
-void PreflightResult::SetTickClockForTesting(
- const base::TickClock* tick_clock) {
- tick_clock_for_testing = tick_clock;
-}
-
-// static
-std::unique_ptr<PreflightResult> PreflightResult::Create(
- const mojom::CredentialsMode credentials_mode,
- const base::Optional<std::string>& allow_methods_header,
- const base::Optional<std::string>& allow_headers_header,
- const base::Optional<std::string>& max_age_header,
- base::Optional<mojom::CorsError>* detected_error) {
- std::unique_ptr<PreflightResult> result =
- base::WrapUnique(new PreflightResult(credentials_mode));
- base::Optional<mojom::CorsError> error =
- result->Parse(allow_methods_header, allow_headers_header, max_age_header);
- if (error) {
- if (detected_error)
- *detected_error = error;
- return nullptr;
- }
- return result;
-}
-
-PreflightResult::PreflightResult(const mojom::CredentialsMode credentials_mode)
- : credentials_(credentials_mode == mojom::CredentialsMode::kInclude) {}
-
-PreflightResult::~PreflightResult() = default;
-
-base::Optional<CorsErrorStatus> PreflightResult::EnsureAllowedCrossOriginMethod(
- const std::string& method) const {
- // Request method is normalized to upper case, and comparison is performed in
- // case-sensitive way, that means access control header should provide an
- // upper case method list.
- const std::string normalized_method = base::ToUpperASCII(method);
- if (methods_.find(normalized_method) != methods_.end() ||
- IsCorsSafelistedMethod(normalized_method)) {
- return base::nullopt;
- }
-
- if (!credentials_ && methods_.find("*") != methods_.end())
- return base::nullopt;
-
- return CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- method);
-}
-
-base::Optional<CorsErrorStatus>
-PreflightResult::EnsureAllowedCrossOriginHeaders(
- const net::HttpRequestHeaders& headers,
- bool is_revalidating) const {
- if (!credentials_ && headers_.find("*") != headers_.end())
- return base::nullopt;
-
- // Forbidden headers are forbidden to be used by JavaScript, and checked
- // beforehand. But user-agents may add these headers internally, and it's
- // fine.
- for (const auto& name : CorsUnsafeNotForbiddenRequestHeaderNames(
- headers.GetHeaderVector(), is_revalidating)) {
- // Header list check is performed in case-insensitive way. Here, we have a
- // parsed header list set in lower case, and search each header in lower
- // case.
- if (headers_.find(name) == headers_.end()) {
- return CorsErrorStatus(
- mojom::CorsError::kHeaderDisallowedByPreflightResponse, name);
- }
- }
- return base::nullopt;
-}
-
-bool PreflightResult::IsExpired() const {
- return absolute_expiry_time_ <= Now();
-}
-
-bool PreflightResult::EnsureAllowedRequest(
- mojom::CredentialsMode credentials_mode,
- const std::string& method,
- const net::HttpRequestHeaders& headers,
- bool is_revalidating) const {
- if (!credentials_ && credentials_mode == mojom::CredentialsMode::kInclude) {
- return false;
- }
-
- if (EnsureAllowedCrossOriginMethod(method))
- return false;
-
- if (EnsureAllowedCrossOriginHeaders(headers, is_revalidating))
- return false;
-
- return true;
-}
-
-base::Optional<mojom::CorsError> PreflightResult::Parse(
- const base::Optional<std::string>& allow_methods_header,
- const base::Optional<std::string>& allow_headers_header,
- const base::Optional<std::string>& max_age_header) {
- DCHECK(methods_.empty());
- DCHECK(headers_.empty());
-
- // Keeps parsed method case for case-sensitive search.
- if (!ParseAccessControlAllowList(allow_methods_header, &methods_, false))
- return mojom::CorsError::kInvalidAllowMethodsPreflightResponse;
-
- // Holds parsed headers in lower case for case-insensitive search.
- if (!ParseAccessControlAllowList(allow_headers_header, &headers_, true))
- return mojom::CorsError::kInvalidAllowHeadersPreflightResponse;
-
- base::TimeDelta expiry_delta;
- if (max_age_header) {
- // Set expiry_delta to 0 on invalid Access-Control-Max-Age headers so to
- // invalidate the entry immediately. CORS-preflight response should be still
- // usable for the request that initiates the CORS-preflight.
- if (!ParseAccessControlMaxAge(max_age_header, &expiry_delta))
- expiry_delta = base::TimeDelta();
- } else {
- expiry_delta = kDefaultTimeout;
- }
- absolute_expiry_time_ = Now() + expiry_delta;
-
- return base::nullopt;
-}
-
-} // namespace cors
-
-} // namespace network
diff --git a/chromium/services/network/public/cpp/cors/preflight_result.h b/chromium/services/network/public/cpp/cors/preflight_result.h
deleted file mode 100644
index 49ef1997066..00000000000
--- a/chromium/services/network/public/cpp/cors/preflight_result.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_RESULT_H_
-#define SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_RESULT_H_
-
-#include <memory>
-#include <string>
-
-#include "base/component_export.h"
-#include "base/containers/flat_set.h"
-#include "base/optional.h"
-#include "services/network/public/cpp/cors/cors_error_status.h"
-#include "services/network/public/mojom/cors.mojom-shared.h"
-#include "services/network/public/mojom/fetch_api.mojom-shared.h"
-
-namespace base {
-class TickClock;
-} // namespace base
-
-namespace net {
-class HttpRequestHeaders;
-} // namespace net
-
-namespace network {
-
-namespace cors {
-
-// Holds CORS-preflight request results, and provides access check methods.
-// Each instance can be cached by CORS-preflight cache.
-// See https://fetch.spec.whatwg.org/#concept-cache.
-class COMPONENT_EXPORT(NETWORK_CPP) PreflightResult final {
- public:
- static void SetTickClockForTesting(const base::TickClock* tick_clock);
-
- // Creates a PreflightResult instance from a CORS-preflight result. Returns
- // nullptr and |detected_error| is populated with the failed reason if the
- // passed parameters contain an invalid entry, and the pointer is valid.
- static std::unique_ptr<PreflightResult> Create(
- const mojom::CredentialsMode credentials_mode,
- const base::Optional<std::string>& allow_methods_header,
- const base::Optional<std::string>& allow_headers_header,
- const base::Optional<std::string>& max_age_header,
- base::Optional<mojom::CorsError>* detected_error);
- ~PreflightResult();
-
- // Checks if the given |method| is allowed by the CORS-preflight response.
- base::Optional<CorsErrorStatus> EnsureAllowedCrossOriginMethod(
- const std::string& method) const;
-
- // Checks if the given all |headers| are allowed by the CORS-preflight
- // response.
- // This does not reject when the headers contain forbidden headers
- // (https://fetch.spec.whatwg.org/#forbidden-header-name) because they may be
- // added by the user agent. They must be checked separately and rejected for
- // JavaScript-initiated requests.
- base::Optional<CorsErrorStatus> EnsureAllowedCrossOriginHeaders(
- const net::HttpRequestHeaders& headers,
- bool is_revalidating) const;
-
- // Checks if this entry is expired.
- bool IsExpired() const;
-
- // Checks if the given combination of |credentials_mode|, |method|, and
- // |headers| is allowed by the CORS-preflight response.
- // This also does not reject the forbidden headers as
- // EnsureAllowCrossOriginHeaders does not.
- bool EnsureAllowedRequest(mojom::CredentialsMode credentials_mode,
- const std::string& method,
- const net::HttpRequestHeaders& headers,
- bool is_revalidating) const;
-
- // Refers the cache expiry time.
- base::TimeTicks absolute_expiry_time() const { return absolute_expiry_time_; }
-
- protected:
- explicit PreflightResult(const mojom::CredentialsMode credentials_mode);
-
- base::Optional<mojom::CorsError> Parse(
- const base::Optional<std::string>& allow_methods_header,
- const base::Optional<std::string>& allow_headers_header,
- const base::Optional<std::string>& max_age_header);
-
- private:
- // Holds an absolute time when the result should be expired in the
- // CORS-preflight cache.
- base::TimeTicks absolute_expiry_time_;
-
- // Corresponds to the fields of the CORS-preflight cache with the same name in
- // the fetch spec.
- // |headers_| holds strings in lower case for case-insensitive search.
- bool credentials_;
- base::flat_set<std::string> methods_;
- base::flat_set<std::string> headers_;
-
- DISALLOW_COPY_AND_ASSIGN(PreflightResult);
-};
-
-} // namespace cors
-
-} // namespace network
-
-#endif // SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_RESULT_H_
diff --git a/chromium/services/network/public/cpp/cors/preflight_result_unittest.cc b/chromium/services/network/public/cpp/cors/preflight_result_unittest.cc
deleted file mode 100644
index 6706561b69d..00000000000
--- a/chromium/services/network/public/cpp/cors/preflight_result_unittest.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/public/cpp/cors/preflight_result.h"
-
-#include "base/test/simple_test_tick_clock.h"
-#include "base/time/time.h"
-#include "net/http/http_request_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace network {
-
-namespace cors {
-
-namespace {
-
-using PreflightResultTest = ::testing::Test;
-
-constexpr base::Optional<mojom::CorsError> kNoError;
-
-struct TestCase {
- const std::string allow_methods;
- const std::string allow_headers;
- const mojom::CredentialsMode cache_credentials_mode;
-
- const std::string request_method;
- const std::string request_headers;
- const mojom::CredentialsMode request_credentials_mode;
-
- const base::Optional<CorsErrorStatus> expected_result;
-};
-
-const TestCase kMethodCases[] = {
- // Found in the preflight response.
- {"OPTIONS", "", mojom::CredentialsMode::kOmit, "OPTIONS", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"GET", "", mojom::CredentialsMode::kOmit, "GET", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"HEAD", "", mojom::CredentialsMode::kOmit, "HEAD", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"POST", "", mojom::CredentialsMode::kOmit, "POST", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"PUT", "", mojom::CredentialsMode::kOmit, "PUT", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"DELETE", "", mojom::CredentialsMode::kOmit, "DELETE", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- // Access-Control-Allow-Methods = #method, method = token.
- // So a non-standard method is accepted as well.
- {"FOOBAR", "", mojom::CredentialsMode::kOmit, "FOOBAR", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
-
- // Found in the safe list.
- {"", "", mojom::CredentialsMode::kOmit, "GET", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"", "", mojom::CredentialsMode::kOmit, "HEAD", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"", "", mojom::CredentialsMode::kOmit, "POST", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
-
- // By '*'.
- {"*", "", mojom::CredentialsMode::kOmit, "OPTIONS", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
-
- // Cache allowing multiple methods.
- {"GET, PUT, DELETE", "", mojom::CredentialsMode::kOmit, "GET", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"GET, PUT, DELETE", "", mojom::CredentialsMode::kOmit, "PUT", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"GET, PUT, DELETE", "", mojom::CredentialsMode::kOmit, "DELETE", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
-
- // Not found in the preflight response or the safe list.
- {"", "", mojom::CredentialsMode::kOmit, "OPTIONS", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- "OPTIONS")},
- {"", "", mojom::CredentialsMode::kOmit, "PUT", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- "PUT")},
- {"", "", mojom::CredentialsMode::kOmit, "DELETE", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- "DELETE")},
- {"GET", "", mojom::CredentialsMode::kOmit, "PUT", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- "PUT")},
- {"GET, POST, DELETE", "", mojom::CredentialsMode::kOmit, "PUT", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- "PUT")},
-
- // Empty entries in the allow_methods list are ignored.
- {"GET,,PUT", "", mojom::CredentialsMode::kOmit, "", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- "")},
- {"GET, ,PUT", "", mojom::CredentialsMode::kOmit, " ", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- " ")},
- // A valid list can contain empty entries so the remaining non-empty
- // entries are accepted.
- {"GET, ,PUT", "", mojom::CredentialsMode::kOmit, "PUT", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
-
- // Request method is normalized to upper-case, but allowed methods is not.
- // Comparison is in case-sensitive, that means allowed methods should be in
- // upper case.
- {"put", "", mojom::CredentialsMode::kOmit, "PUT", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- "PUT")},
- {"put", "", mojom::CredentialsMode::kOmit, "put", "",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kMethodDisallowedByPreflightResponse,
- "put")},
- {"PUT", "", mojom::CredentialsMode::kOmit, "put", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
- // ... But, GET is always allowed by the safe list.
- {"get", "", mojom::CredentialsMode::kOmit, "GET", "",
- mojom::CredentialsMode::kOmit, base::nullopt},
-};
-
-const TestCase kHeaderCases[] = {
- // Found in the preflight response.
- {"GET", "X-MY-HEADER", mojom::CredentialsMode::kOmit, "GET",
- "X-MY-HEADER:t", mojom::CredentialsMode::kOmit, base::nullopt},
- {"GET", "X-MY-HEADER, Y-MY-HEADER", mojom::CredentialsMode::kOmit, "GET",
- "X-MY-HEADER:t\r\nY-MY-HEADER:t", mojom::CredentialsMode::kOmit,
- base::nullopt},
- {"GET", "x-my-header, Y-MY-HEADER", mojom::CredentialsMode::kOmit, "GET",
- "X-MY-HEADER:t\r\ny-my-header:t", mojom::CredentialsMode::kOmit,
- base::nullopt},
-
- // Found in the safe list.
- {"GET", "", mojom::CredentialsMode::kOmit, "GET", "Accept:*/*",
- mojom::CredentialsMode::kOmit, base::nullopt},
-
- // By '*'.
- {"GET", "*", mojom::CredentialsMode::kOmit, "GET", "xyzzy:t",
- mojom::CredentialsMode::kOmit, base::nullopt},
- {"GET", "*", mojom::CredentialsMode::kInclude, "GET", "xyzzy:t",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kHeaderDisallowedByPreflightResponse,
- "xyzzy")},
-
- // Forbidden headers can pass.
- {"GET", "", mojom::CredentialsMode::kOmit, "GET", "Host: www.google.com",
- mojom::CredentialsMode::kOmit, base::nullopt},
-
- // Not found in the preflight response and the safe list.
- {"GET", "", mojom::CredentialsMode::kOmit, "GET", "X-MY-HEADER:t",
- mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kHeaderDisallowedByPreflightResponse,
- "x-my-header")},
- {"GET", "X-SOME-OTHER-HEADER", mojom::CredentialsMode::kOmit, "GET",
- "X-MY-HEADER:t", mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kHeaderDisallowedByPreflightResponse,
- "x-my-header")},
- {"GET", "X-MY-HEADER", mojom::CredentialsMode::kOmit, "GET",
- "X-MY-HEADER:t\r\nY-MY-HEADER:t", mojom::CredentialsMode::kOmit,
- CorsErrorStatus(mojom::CorsError::kHeaderDisallowedByPreflightResponse,
- "y-my-header")},
-};
-
-TEST_F(PreflightResultTest, MaxAge) {
- std::unique_ptr<base::SimpleTestTickClock> tick_clock =
- std::make_unique<base::SimpleTestTickClock>();
- PreflightResult::SetTickClockForTesting(tick_clock.get());
-
- std::unique_ptr<PreflightResult> result1 =
- PreflightResult::Create(mojom::CredentialsMode::kOmit, base::nullopt,
- base::nullopt, std::string("573"), nullptr);
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSeconds(573),
- result1->absolute_expiry_time());
-
- // Negative values are invalid. The preflight result itself can be usable, but
- // should not cache such results. PreflightResult expresses it as a result
- // with 'Access-Control-Max-Age: 0'.
- std::unique_ptr<PreflightResult> result2 =
- PreflightResult::Create(mojom::CredentialsMode::kOmit, base::nullopt,
- base::nullopt, std::string("-765"), nullptr);
- EXPECT_EQ(base::TimeTicks(), result2->absolute_expiry_time());
-
- PreflightResult::SetTickClockForTesting(nullptr);
-}
-
-TEST_F(PreflightResultTest, EnsureMethods) {
- for (const auto& test : kMethodCases) {
- std::unique_ptr<PreflightResult> result =
- PreflightResult::Create(test.cache_credentials_mode, test.allow_methods,
- test.allow_headers, base::nullopt, nullptr);
- ASSERT_TRUE(result);
- EXPECT_EQ(test.expected_result,
- result->EnsureAllowedCrossOriginMethod(test.request_method));
- }
-}
-
-TEST_F(PreflightResultTest, EnsureHeaders) {
- for (const auto& test : kHeaderCases) {
- std::unique_ptr<PreflightResult> result =
- PreflightResult::Create(test.cache_credentials_mode, test.allow_methods,
- test.allow_headers, base::nullopt, nullptr);
- ASSERT_TRUE(result);
- net::HttpRequestHeaders headers;
- headers.AddHeadersFromString(test.request_headers);
- EXPECT_EQ(test.expected_result,
- result->EnsureAllowedCrossOriginHeaders(headers, false));
- }
-}
-
-TEST_F(PreflightResultTest, EnsureRequest) {
- for (const auto& test : kMethodCases) {
- std::unique_ptr<PreflightResult> result =
- PreflightResult::Create(test.cache_credentials_mode, test.allow_methods,
- test.allow_headers, base::nullopt, nullptr);
- ASSERT_TRUE(result);
- net::HttpRequestHeaders headers;
- if (!test.request_headers.empty())
- headers.AddHeadersFromString(test.request_headers);
- EXPECT_EQ(
- test.expected_result == base::nullopt,
- result->EnsureAllowedRequest(test.request_credentials_mode,
- test.request_method, headers, false));
- }
-
- for (const auto& test : kHeaderCases) {
- std::unique_ptr<PreflightResult> result =
- PreflightResult::Create(test.cache_credentials_mode, test.allow_methods,
- test.allow_headers, base::nullopt, nullptr);
- ASSERT_TRUE(result);
- net::HttpRequestHeaders headers;
- if (!test.request_headers.empty())
- headers.AddHeadersFromString(test.request_headers);
- EXPECT_EQ(
- test.expected_result == base::nullopt,
- result->EnsureAllowedRequest(test.request_credentials_mode,
- test.request_method, headers, false));
- }
-
- struct {
- const mojom::CredentialsMode cache_credentials_mode;
- const mojom::CredentialsMode request_credentials_mode;
- const bool expected_result;
- } credentials_cases[] = {
- // Different credential modes.
- {mojom::CredentialsMode::kInclude, mojom::CredentialsMode::kOmit, true},
- {mojom::CredentialsMode::kInclude, mojom::CredentialsMode::kInclude,
- true},
-
- // Credential mode mismatch.
- {mojom::CredentialsMode::kOmit, mojom::CredentialsMode::kOmit, true},
- {mojom::CredentialsMode::kOmit, mojom::CredentialsMode::kInclude, false},
- };
-
- for (const auto& test : credentials_cases) {
- std::unique_ptr<PreflightResult> result =
- PreflightResult::Create(test.cache_credentials_mode, std::string("GET"),
- base::nullopt, base::nullopt, nullptr);
- ASSERT_TRUE(result);
- net::HttpRequestHeaders headers;
- EXPECT_EQ(test.expected_result,
- result->EnsureAllowedRequest(test.request_credentials_mode, "GET",
- headers, false));
- }
-}
-
-struct ParseAccessListTestCase {
- const std::string input;
- const std::vector<std::string> values_to_be_accepted;
- const base::Optional<mojom::CorsError> strict_check_result;
-};
-
-const ParseAccessListTestCase kParseHeadersCases[] = {
- {"bad value", {}, mojom::CorsError::kInvalidAllowHeadersPreflightResponse},
- {"X-MY-HEADER, ", {"X-MY-HEADER:t"}, kNoError},
- {"", {}, kNoError},
- {", X-MY-HEADER, Y-MY-HEADER, ,",
- {"X-MY-HEADER:t", "Y-MY-HEADER:t"},
- kNoError}};
-
-const ParseAccessListTestCase kParseMethodsCases[] = {
- {"bad value", {}, mojom::CorsError::kInvalidAllowMethodsPreflightResponse},
- {"GET, ", {"GET"}, kNoError},
- {"", {}, kNoError},
- {", GET, POST, ,", {"GET", "POST"}, kNoError}};
-
-TEST_F(PreflightResultTest, ParseAllowControlAllowHeaders) {
- for (const auto& test : kParseHeadersCases) {
- base::Optional<mojom::CorsError> error;
- std::unique_ptr<PreflightResult> result = PreflightResult::Create(
- mojom::CredentialsMode::kOmit, /*allow_methods_header=*/base::nullopt,
- test.input, /*max_age_header=*/base::nullopt, &error);
- EXPECT_EQ(error, test.strict_check_result);
-
- if (test.strict_check_result == kNoError) {
- for (const auto& request_header : test.values_to_be_accepted) {
- net::HttpRequestHeaders headers;
- headers.AddHeadersFromString(request_header);
- EXPECT_EQ(base::nullopt,
- result->EnsureAllowedCrossOriginHeaders(headers, false));
- }
- }
- }
-}
-
-TEST_F(PreflightResultTest, ParseAllowControlAllowMethods) {
- for (const auto& test : kParseMethodsCases) {
- base::Optional<mojom::CorsError> error;
- std::unique_ptr<PreflightResult> result =
- PreflightResult::Create(mojom::CredentialsMode::kOmit, test.input,
- /*allow_headers_header=*/base::nullopt,
- /*max_age_header=*/base::nullopt, &error);
- EXPECT_EQ(error, test.strict_check_result);
-
- if (test.strict_check_result == kNoError) {
- for (const auto& request_method : test.values_to_be_accepted) {
- EXPECT_EQ(base::nullopt,
- result->EnsureAllowedCrossOriginMethod(request_method));
- }
- }
- }
-}
-
-} // namespace
-
-} // namespace cors
-
-} // namespace network
diff --git a/chromium/services/network/public/cpp/cross_origin_embedder_policy_parser.cc b/chromium/services/network/public/cpp/cross_origin_embedder_policy_parser.cc
index 3f3d9967616..861cbd1f388 100644
--- a/chromium/services/network/public/cpp/cross_origin_embedder_policy_parser.cc
+++ b/chromium/services/network/public/cpp/cross_origin_embedder_policy_parser.cc
@@ -10,7 +10,6 @@
#include "base/strings/string_piece.h"
#include "net/http/http_response_headers.h"
#include "net/http/structured_headers.h"
-#include "services/network/public/cpp/features.h"
namespace network {
@@ -45,9 +44,6 @@ Parse(base::StringPiece header_value) {
CrossOriginEmbedderPolicy ParseCrossOriginEmbedderPolicy(
const net::HttpResponseHeaders& headers) {
CrossOriginEmbedderPolicy coep;
- if (!base::FeatureList::IsEnabled(features::kCrossOriginEmbedderPolicy))
- return coep;
-
std::string header_value;
if (headers.GetNormalizedHeader(kHeaderName, &header_value)) {
std::tie(coep.value, coep.reporting_endpoint) = Parse(header_value);
diff --git a/chromium/services/network/public/cpp/cross_origin_embedder_policy_parser_unittest.cc b/chromium/services/network/public/cpp/cross_origin_embedder_policy_parser_unittest.cc
index c3fb940ef20..938a542f193 100644
--- a/chromium/services/network/public/cpp/cross_origin_embedder_policy_parser_unittest.cc
+++ b/chromium/services/network/public/cpp/cross_origin_embedder_policy_parser_unittest.cc
@@ -10,16 +10,11 @@
#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "net/http/http_response_headers.h"
-#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
TEST(CrossOriginEmbedderPolicyTest, Parse) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(
- features::kCrossOriginEmbedderPolicy);
-
constexpr auto kNone = mojom::CrossOriginEmbedderPolicyValue::kNone;
constexpr auto kRequireCorp =
mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
diff --git a/chromium/services/network/public/cpp/cross_origin_read_blocking.cc b/chromium/services/network/public/cpp/cross_origin_read_blocking.cc
index a1a3b54a42e..19956a10208 100644
--- a/chromium/services/network/public/cpp/cross_origin_read_blocking.cc
+++ b/chromium/services/network/public/cpp/cross_origin_read_blocking.cc
@@ -14,13 +14,13 @@
#include "base/check_op.h"
#include "base/command_line.h"
-#include "base/containers/flat_set.h"
+#include "base/containers/contains.h"
+#include "base/containers/fixed_flat_set.h"
#include "base/feature_list.h"
#include "base/lazy_instance.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "net/base/mime_sniffer.h"
@@ -248,12 +248,14 @@ void BlockResponseHeaders(
// disclosure of "application/zip" even though Chrome doesn't have built-in
// support for this resource type. And CORB also wants to protect
// "application/pdf" even though Chrome happens to support this resource type.
-base::flat_set<std::string>& GetNeverSniffedMimeTypes() {
- static base::NoDestructor<base::flat_set<std::string>> s_types{{
+const auto& GetNeverSniffedMimeTypes() {
+ static constexpr auto kNeverSniffedMimeTypes = base::MakeFixedFlatSet<
+ base::StringPiece>({
+ // clang-format off
// The types below (zip, protobuf, etc.) are based on most commonly used
// content types according to HTTP Archive - see:
// https://github.com/whatwg/fetch/issues/860#issuecomment-457330454
- "application/gzip",
+ "application/gzip",
"application/x-gzip",
"application/x-protobuf",
"application/zip",
@@ -308,20 +310,33 @@ base::flat_set<std::string>& GetNeverSniffedMimeTypes() {
"multipart/byteranges",
// TODO(lukasza): https://crbug.com/802836#c11: Add
// application/signed-exchange.
- }};
+ // clang-format on
+ });
// All items need to be lower-case, to support case-insensitive comparisons
// later.
- DCHECK(std::all_of(
- s_types->begin(), s_types->end(),
- [](const std::string& s) { return s == base::ToLowerASCII(s); }));
+ DCHECK(std::all_of(kNeverSniffedMimeTypes.begin(),
+ kNeverSniffedMimeTypes.end(),
+ [](const auto& s) { return s == base::ToLowerASCII(s); }));
- return *s_types;
+ return kNeverSniffedMimeTypes;
}
} // namespace
// static
+bool CrossOriginReadBlocking::IsJavascriptMimeType(
+ base::StringPiece mime_type) {
+ constexpr auto kCaseInsensitive = base::CompareCase::INSENSITIVE_ASCII;
+ for (const std::string& suffix : kJavaScriptSuffixes) {
+ if (base::EndsWith(mime_type, suffix, kCaseInsensitive))
+ return true;
+ }
+
+ return false;
+}
+
+// static
MimeType CrossOriginReadBlocking::GetCanonicalMimeType(
base::StringPiece mime_type) {
// Checking for image/svg+xml and application/dash+xml early ensures that they
@@ -482,10 +497,6 @@ SniffingResult CrossOriginReadBlocking::SniffForJSON(base::StringPiece data) {
// Whitespace is ignored (outside of string literals)
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
continue;
- } else {
- // Inside string literals, control characters should result in rejection.
- if ((c >= 0 && c < 32) || c == 127)
- return kNo;
}
switch (state) {
@@ -789,9 +800,13 @@ CrossOriginReadBlocking::ResponseAnalyzer::ShouldBlockBasedOnHeaders(
// Requests from foo.example.com will consult foo.example.com's service worker
// first (if one has been registered). The service worker can handle requests
// initiated by foo.example.com even if they are cross-origin (e.g. requests
- // for bar.example.com). This is okay and should not be blocked by CORB,
- // unless the initiator opted out of CORS / opted into receiving an opaque
- // response. See also https://crbug.com/803672.
+ // for bar.example.com). This is okay, because there is no security boundary
+ // between foo.example.com and the service worker of foo.example.com + because
+ // the response data is "conjured" within the service worker of
+ // foo.example.com (rather than being fetched from bar.example.com).
+ // Therefore such responses should not be blocked by CORB, unless the
+ // initiator opted out of CORS / opted into receiving an opaque response. See
+ // also https://crbug.com/803672.
if (response.was_fetched_via_service_worker) {
switch (response.response_type) {
case network::mojom::FetchResponseType::kBasic:
@@ -841,7 +856,8 @@ CrossOriginReadBlocking::ResponseAnalyzer::ShouldBlockBasedOnHeaders(
request_url, request_url, request_initiator, response,
kOverreachingRequestMode, request_initiator_origin_lock,
network::mojom::RequestDestination::kEmpty,
- CrossOriginEmbedderPolicy())) {
+ CrossOriginEmbedderPolicy(),
+ /*reporter=*/nullptr)) {
// Ignore mime types and/or sniffing and have CORB block all responses with
// COR*P* header.
return kBlock;
@@ -902,17 +918,6 @@ CrossOriginReadBlocking::ResponseAnalyzer::ShouldBlockBasedOnHeaders(
}
// static
-bool CrossOriginReadBlocking::ResponseAnalyzer::HasNoSniff(
- const network::mojom::URLResponseHead& response) {
- if (!response.headers)
- return false;
- std::string nosniff_header;
- response.headers->GetNormalizedHeader("x-content-type-options",
- &nosniff_header);
- return base::LowerCaseEqualsASCII(nosniff_header, "nosniff");
-}
-
-// static
bool CrossOriginReadBlocking::ResponseAnalyzer::SeemsSensitiveFromCORSHeuristic(
const network::mojom::URLResponseHead& response) {
// Check if the response has an Access-Control-Allow-Origin with a value other
@@ -984,15 +989,13 @@ CrossOriginReadBlocking::ResponseAnalyzer::GetMimeTypeBucket(
// Javascript is assumed public. See also
// https://mimesniff.spec.whatwg.org/#javascript-mime-type.
- constexpr auto kCaseInsensitive = base::CompareCase::INSENSITIVE_ASCII;
- for (const std::string& suffix : kJavaScriptSuffixes) {
- if (base::EndsWith(mime_type, suffix, kCaseInsensitive)) {
- return kPublic;
- }
+ if (IsJavascriptMimeType(mime_type)) {
+ return kPublic;
}
// Images are assumed public. See also
// https://mimesniff.spec.whatwg.org/#image-mime-type.
+ constexpr auto kCaseInsensitive = base::CompareCase::INSENSITIVE_ASCII;
if (base::StartsWith(mime_type, "image", kCaseInsensitive)) {
return kPublic;
}
@@ -1187,6 +1190,17 @@ void CrossOriginReadBlocking::ResponseAnalyzer::LogBlockedResponse() {
}
// static
+bool CrossOriginReadBlocking::ResponseAnalyzer::HasNoSniff(
+ const network::mojom::URLResponseHead& response) {
+ if (!response.headers)
+ return false;
+ std::string nosniff_header;
+ response.headers->GetNormalizedHeader("x-content-type-options",
+ &nosniff_header);
+ return base::LowerCaseEqualsASCII(nosniff_header, "nosniff");
+}
+
+// static
CrossOriginReadBlocking::ResponseAnalyzer::CrossOriginProtectionDecision
CrossOriginReadBlocking::ResponseAnalyzer::BlockingDecisionToProtectionDecision(
BlockingDecision blocking_decision) {
diff --git a/chromium/services/network/public/cpp/cross_origin_read_blocking.h b/chromium/services/network/public/cpp/cross_origin_read_blocking.h
index feeac20861b..00543aceb21 100644
--- a/chromium/services/network/public/cpp/cross_origin_read_blocking.h
+++ b/chromium/services/network/public/cpp/cross_origin_read_blocking.h
@@ -35,6 +35,9 @@ namespace network {
class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginReadBlocking {
public:
+ // Not instantiable - only static methods.
+ CrossOriginReadBlocking() = delete;
+
// This enum describes how CORB should decide whether to block a given
// no-cors, cross-origin response.
//
@@ -151,6 +154,9 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginReadBlocking {
void LogAllowedResponse();
void LogBlockedResponse();
+ // Returns true if the response has a nosniff header.
+ static bool HasNoSniff(const network::mojom::URLResponseHead& response);
+
private:
FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest,
SeemsSensitiveFromCORSHeuristic);
@@ -184,9 +190,6 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginReadBlocking {
const base::Optional<url::Origin>& request_initiator_origin_lock,
MimeType canonical_mime_type);
- // Returns true if the response has a nosniff header.
- static bool HasNoSniff(const network::mojom::URLResponseHead& response);
-
// Checks if the response seems sensitive for CORB protection logging.
// Returns true if the Access-Control-Allow-Origin header has a value other
// than *.
@@ -307,15 +310,16 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginReadBlocking {
kYes,
};
- private:
- CrossOriginReadBlocking(); // Not instantiable.
+ // Returns whether `mime_type` is a Javascript MIME type based on
+ // https://mimesniff.spec.whatwg.org/#javascript-mime-type
+ static bool IsJavascriptMimeType(base::StringPiece mime_type);
// Returns the representative mime type enum value of the mime type of
// response. For example, this returns the same value for all text/xml mime
// type families such as application/xml, application/rss+xml.
static MimeType GetCanonicalMimeType(base::StringPiece mime_type);
- FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, GetCanonicalMimeType);
+ private:
// Returns whether this scheme is a target of the cross-origin read blocking
// (CORB) policy. This returns true only for http://* and https://* urls.
static bool IsBlockableScheme(const GURL& frame_origin);
diff --git a/chromium/services/network/public/cpp/cross_origin_read_blocking_unittest.cc b/chromium/services/network/public/cpp/cross_origin_read_blocking_unittest.cc
index 3f9f0b5f43f..c900543c0d8 100644
--- a/chromium/services/network/public/cpp/cross_origin_read_blocking_unittest.cc
+++ b/chromium/services/network/public/cpp/cross_origin_read_blocking_unittest.cc
@@ -366,11 +366,9 @@ const TestScenario kScenarios[] = {
},
{
// Blocked, because the unit test doesn't make a call to
- // CrossOriginReadBlocking::AddExceptionForFlash (simulating a behavior
- // of a compromised renderer that only pretends to be hosting Flash).
- //
- // The regular scenario is covered by integration tests:
- // OutOfProcessPPAPITest.URLLoaderTrusted.
+ // NetworkService::AddAllowedRequestInitiatorForPlugin (simulating a
+ // behavior of a compromised renderer that only pretends to be hosting
+ // PDF).
"Blocked: Cross-site fetch HTML from Flash without CORS",
__LINE__,
"http://www.b.com/plugin.html", // target_url
@@ -2567,9 +2565,10 @@ TEST(CrossOriginReadBlockingTest, SniffForJSON) {
EXPECT_EQ(SniffingResult::kMaybe,
CrossOriginReadBlocking::SniffForJSON("{\"\\\""))
<< "Incomplete escape results in maybe";
- EXPECT_EQ(SniffingResult::kNo,
+ EXPECT_EQ(SniffingResult::kYes,
CrossOriginReadBlocking::SniffForJSON("{\"\n\" : true}"))
- << "Unescaped control characters are rejected";
+ << "Unescaped control characters are accepted (a bit more like "
+ << "Javascript than strict reading of the JSON spec)";
EXPECT_EQ(SniffingResult::kNo, CrossOriginReadBlocking::SniffForJSON("{}"))
<< "Empty dictionary is not recognized (since it's valid JS too)";
EXPECT_EQ(SniffingResult::kNo,
diff --git a/chromium/services/network/public/cpp/cross_origin_resource_policy.cc b/chromium/services/network/public/cpp/cross_origin_resource_policy.cc
index b24addd5a5e..74a96f33f3c 100644
--- a/chromium/services/network/public/cpp/cross_origin_resource_policy.cc
+++ b/chromium/services/network/public/cpp/cross_origin_resource_policy.cc
@@ -6,12 +6,10 @@
#include <string>
-#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/cross_origin_embedder_policy.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/initiator_lock_compatibility.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h"
@@ -74,10 +72,8 @@ CrossOriginResourcePolicy::ParsedHeader ParseHeaderByString(
if (header_value == "same-site")
return CrossOriginResourcePolicy::kSameSite;
- if (base::FeatureList::IsEnabled(features::kCrossOriginEmbedderPolicy) &&
- header_value == "cross-origin") {
+ if (header_value == "cross-origin")
return CrossOriginResourcePolicy::kCrossOrigin;
- }
// TODO(lukasza): Once https://github.com/whatwg/fetch/issues/760 gets
// resolved, add support for parsing specific origins.
@@ -162,7 +158,6 @@ base::Optional<mojom::BlockedByResponseReason> IsBlockedInternal(
if ((policy == CrossOriginResourcePolicy::kNoHeader ||
policy == CrossOriginResourcePolicy::kParsingError) &&
embedder_policy == mojom::CrossOriginEmbedderPolicyValue::kRequireCorp) {
- DCHECK(base::FeatureList::IsEnabled(features::kCrossOriginEmbedderPolicy));
policy = CrossOriginResourcePolicy::kSameOrigin;
upgrade_to_same_origin = true;
}
diff --git a/chromium/services/network/public/cpp/cross_origin_resource_policy.h b/chromium/services/network/public/cpp/cross_origin_resource_policy.h
index 22c08b380a3..d01e65f25cb 100644
--- a/chromium/services/network/public/cpp/cross_origin_resource_policy.h
+++ b/chromium/services/network/public/cpp/cross_origin_resource_policy.h
@@ -48,8 +48,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginResourcePolicy {
base::Optional<url::Origin> request_initiator_origin_lock,
mojom::RequestDestination request_destination,
const CrossOriginEmbedderPolicy& embedder_policy,
- mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr)
- WARN_UNUSED_RESULT;
+ mojom::CrossOriginEmbedderPolicyReporter* reporter) WARN_UNUSED_RESULT;
// Same as IsBlocked(), but this method can take a raw value of
// Cross-Origin-Resource-Policy header instead of using a URLResponseHead.
@@ -62,8 +61,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginResourcePolicy {
base::Optional<url::Origin> request_initiator_origin_lock,
mojom::RequestDestination request_destination,
const CrossOriginEmbedderPolicy& embedder_policy,
- mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr)
- WARN_UNUSED_RESULT;
+ mojom::CrossOriginEmbedderPolicyReporter* reporter) WARN_UNUSED_RESULT;
// The CORP check for navigation requests. This is expected to be called
// from the navigation algorithm.
@@ -75,7 +73,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginResourcePolicy {
base::Optional<url::Origin> request_initiator_origin_lock,
mojom::RequestDestination request_destination,
const CrossOriginEmbedderPolicy& embedder_policy,
- mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr);
+ mojom::CrossOriginEmbedderPolicyReporter* reporter);
// Parsing of the Cross-Origin-Resource-Policy http response header.
enum ParsedHeader {
diff --git a/chromium/services/network/public/cpp/cross_origin_resource_policy_unittest.cc b/chromium/services/network/public/cpp/cross_origin_resource_policy_unittest.cc
index 5d6a99818e3..bc7014dcdda 100644
--- a/chromium/services/network/public/cpp/cross_origin_resource_policy_unittest.cc
+++ b/chromium/services/network/public/cpp/cross_origin_resource_policy_unittest.cc
@@ -6,11 +6,9 @@
#include <vector>
#include "base/memory/ref_counted.h"
-#include "base/test/scoped_feature_list.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/cross_origin_resource_policy.h"
-#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
@@ -111,19 +109,10 @@ TEST(CrossOriginResourcePolicyTest, ParseHeader) {
}
TEST(CrossOriginResourcePolicyTest, CrossSiteHeaderWithCOEP) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kCrossOriginEmbedderPolicy);
EXPECT_EQ(CrossOriginResourcePolicy::kCrossOrigin,
ParseHeader("Cross-Origin-Resource-Policy: cross-origin"));
}
-TEST(CrossOriginResourcePolicyTest, CrossSiteHeaderWithoutCOEP) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(features::kCrossOriginEmbedderPolicy);
- EXPECT_EQ(CrossOriginResourcePolicy::kParsingError,
- ParseHeader("Cross-Origin-Resource-Policy: cross-origin"));
-}
-
bool ShouldAllowSameSite(const std::string& initiator,
const std::string& target) {
return CrossOriginResourcePolicy::ShouldAllowSameSiteForTesting(
@@ -166,9 +155,6 @@ TEST(CrossOriginResourcePolicyTest, ShouldAllowSameSite) {
}
TEST(CrossOriginResourcePolicyTest, WithCOEP) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kCrossOriginEmbedderPolicy);
-
mojom::URLResponseHead corp_none;
mojom::URLResponseHead corp_same_origin;
mojom::URLResponseHead corp_cross_origin;
@@ -309,9 +295,6 @@ TEST(CrossOriginResourcePolicyTest, WithCOEP) {
}
TEST(CrossOriginResourcePolicyTest, NavigationWithCOEP) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kCrossOriginEmbedderPolicy);
-
mojom::URLResponseHead corp_none;
mojom::URLResponseHead corp_same_origin;
mojom::URLResponseHead corp_cross_origin;
diff --git a/chromium/services/network/public/cpp/data_element.cc b/chromium/services/network/public/cpp/data_element.cc
index 32879fefe7a..361eb95c9dd 100644
--- a/chromium/services/network/public/cpp/data_element.cc
+++ b/chromium/services/network/public/cpp/data_element.cc
@@ -16,63 +16,35 @@
namespace network {
-const uint64_t DataElement::kUnknownSize;
-
-DataElement::DataElement()
- : type_(mojom::DataElementType::kUnknown),
- offset_(0),
- length_(std::numeric_limits<uint64_t>::max()) {}
-
-DataElement::~DataElement() = default;
-
-DataElement::DataElement(DataElement&& other) = default;
-DataElement& DataElement::operator=(DataElement&& other) = default;
-
-void DataElement::SetToFilePathRange(
- const base::FilePath& path,
- uint64_t offset,
- uint64_t length,
- const base::Time& expected_modification_time) {
- type_ = mojom::DataElementType::kFile;
- path_ = path;
- offset_ = offset;
- length_ = length;
- expected_modification_time_ = expected_modification_time;
-}
-
-void DataElement::SetToDataPipe(
- mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter) {
- DCHECK(data_pipe_getter);
- type_ = mojom::DataElementType::kDataPipe;
- data_pipe_getter_ = std::move(data_pipe_getter);
-}
-
-void DataElement::SetToChunkedDataPipe(
- mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter) {
- type_ = mojom::DataElementType::kChunkedDataPipe;
- chunked_data_pipe_getter_ = std::move(chunked_data_pipe_getter);
-}
-
-void DataElement::SetToReadOnceStream(
- mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter) {
- type_ = mojom::DataElementType::kReadOnceStream;
- chunked_data_pipe_getter_ = std::move(chunked_data_pipe_getter);
+DataElementBytes::DataElementBytes() = default;
+DataElementBytes::DataElementBytes(std::vector<uint8_t> bytes)
+ : bytes_(std::move(bytes)) {}
+DataElementBytes::DataElementBytes(DataElementBytes&& other) = default;
+DataElementBytes& DataElementBytes::operator=(DataElementBytes&& other) =
+ default;
+DataElementBytes::~DataElementBytes() = default;
+
+DataElementDataPipe::DataElementDataPipe() = default;
+DataElementDataPipe::DataElementDataPipe(
+ mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter)
+ : data_pipe_getter_(std::move(data_pipe_getter)) {
+ DCHECK(data_pipe_getter_);
}
+DataElementDataPipe::DataElementDataPipe(DataElementDataPipe&&) = default;
+DataElementDataPipe& DataElementDataPipe::operator=(
+ DataElementDataPipe&& other) = default;
+DataElementDataPipe::~DataElementDataPipe() = default;
mojo::PendingRemote<mojom::DataPipeGetter>
-DataElement::ReleaseDataPipeGetter() {
- DCHECK_EQ(mojom::DataElementType::kDataPipe, type_);
+DataElementDataPipe::ReleaseDataPipeGetter() {
DCHECK(data_pipe_getter_.is_valid());
return std::move(data_pipe_getter_);
}
-mojo::PendingRemote<mojom::DataPipeGetter> DataElement::CloneDataPipeGetter()
- const {
- DCHECK_EQ(mojom::DataElementType::kDataPipe, type_);
+mojo::PendingRemote<mojom::DataPipeGetter>
+DataElementDataPipe::CloneDataPipeGetter() const {
DCHECK(data_pipe_getter_.is_valid());
- auto* mutable_this = const_cast<DataElement*>(this);
+ auto* mutable_this = const_cast<DataElementDataPipe*>(this);
mojo::Remote<mojom::DataPipeGetter> owned(
std::move(mutable_this->data_pipe_getter_));
mojo::PendingRemote<mojom::DataPipeGetter> clone;
@@ -81,80 +53,42 @@ mojo::PendingRemote<mojom::DataPipeGetter> DataElement::CloneDataPipeGetter()
return clone;
}
-const mojo::PendingRemote<mojom::ChunkedDataPipeGetter>&
-DataElement::chunked_data_pipe_getter() const {
- DCHECK(type_ == mojom::DataElementType::kChunkedDataPipe ||
- type_ == mojom::DataElementType::kReadOnceStream);
- return chunked_data_pipe_getter_;
+DataElementChunkedDataPipe::DataElementChunkedDataPipe() = default;
+DataElementChunkedDataPipe::DataElementChunkedDataPipe(
+ mojo::PendingRemote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter,
+ ReadOnlyOnce read_only_once)
+ : chunked_data_pipe_getter_(std::move(chunked_data_pipe_getter)),
+ read_only_once_(read_only_once) {
+ DCHECK(chunked_data_pipe_getter_);
}
+DataElementChunkedDataPipe::DataElementChunkedDataPipe(
+ DataElementChunkedDataPipe&& other) = default;
+DataElementChunkedDataPipe& DataElementChunkedDataPipe::operator=(
+ DataElementChunkedDataPipe&& other) = default;
+DataElementChunkedDataPipe::~DataElementChunkedDataPipe() = default;
mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-DataElement::ReleaseChunkedDataPipeGetter() {
- DCHECK(type_ == mojom::DataElementType::kChunkedDataPipe ||
- type_ == mojom::DataElementType::kReadOnceStream)
- << type_;
+DataElementChunkedDataPipe::ReleaseChunkedDataPipeGetter() {
+ DCHECK(chunked_data_pipe_getter_.is_valid());
return std::move(chunked_data_pipe_getter_);
}
-void PrintTo(const DataElement& x, std::ostream* os) {
- const uint64_t kMaxDataPrintLength = 40;
- *os << "<DataElement>{type: ";
- switch (x.type()) {
- case mojom::DataElementType::kBytes: {
- uint64_t length = std::min(x.length(), kMaxDataPrintLength);
- *os << "TYPE_BYTES, data: ["
- << base::HexEncode(x.bytes(), static_cast<size_t>(length));
- if (length < x.length()) {
- *os << "<...truncated due to length...>";
- }
- *os << "]";
- break;
- }
- case mojom::DataElementType::kFile:
- *os << "TYPE_FILE, path: " << x.path().AsUTF8Unsafe()
- << ", expected_modification_time: " << x.expected_modification_time();
- break;
- case mojom::DataElementType::kDataPipe:
- *os << "TYPE_DATA_PIPE";
- break;
- case mojom::DataElementType::kChunkedDataPipe:
- *os << "TYPE_CHUNKED_DATA_PIPE";
- break;
- case mojom::DataElementType::kReadOnceStream:
- *os << "TYPE_READ_ONCE_STREAM";
- break;
- case mojom::DataElementType::kUnknown:
- *os << "TYPE_UNKNOWN";
- break;
- }
- *os << ", length: " << x.length() << ", offset: " << x.offset() << "}";
-}
-
-bool operator==(const DataElement& a, const DataElement& b) {
- if (a.type() != b.type() || a.offset() != b.offset() ||
- a.length() != b.length())
- return false;
- switch (a.type()) {
- case mojom::DataElementType::kBytes:
- return memcmp(a.bytes(), b.bytes(), b.length()) == 0;
- case mojom::DataElementType::kFile:
- return a.path() == b.path() &&
- a.expected_modification_time() == b.expected_modification_time();
- case mojom::DataElementType::kDataPipe:
- return false;
- case mojom::DataElementType::kChunkedDataPipe:
- return false;
- case mojom::DataElementType::kReadOnceStream:
- return false;
- case mojom::DataElementType::kUnknown:
- NOTREACHED();
- return false;
- }
- return false;
-}
-
-bool operator!=(const DataElement& a, const DataElement& b) {
- return !(a == b);
-}
+DataElementFile::DataElementFile() = default;
+DataElementFile::DataElementFile(const base::FilePath& path,
+ uint64_t offset,
+ uint64_t length,
+ base::Time expected_modification_time)
+ : path_(path),
+ offset_(offset),
+ length_(length),
+ expected_modification_time_(expected_modification_time) {}
+DataElementFile::DataElementFile(DataElementFile&&) = default;
+DataElementFile& DataElementFile::operator=(DataElementFile&&) = default;
+DataElementFile::~DataElementFile() = default;
+
+DataElement::DataElement() = default;
+DataElement::DataElement(DataElement&& other) = default;
+DataElement& DataElement::operator=(DataElement&& other) = default;
+DataElement::~DataElement() = default;
} // namespace network
diff --git a/chromium/services/network/public/cpp/data_element.h b/chromium/services/network/public/cpp/data_element.h
index 7eeb277b4ea..84e1859aa61 100644
--- a/chromium/services/network/public/cpp/data_element.h
+++ b/chromium/services/network/public/cpp/data_element.h
@@ -10,151 +10,188 @@
#include <limits>
#include <memory>
-#include <ostream>
-#include <string>
+#include <utility>
#include <vector>
#include "base/check_op.h"
#include "base/component_export.h"
#include "base/files/file_path.h"
-#include "base/gtest_prod_util.h"
+#include "base/strings/string_piece.h"
#include "base/time/time.h"
-#include "mojo/public/cpp/bindings/enum_traits.h"
+#include "base/types/strong_alias.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/mojom/chunked_data_pipe_getter.mojom-forward.h"
#include "services/network/public/mojom/data_pipe_getter.mojom-forward.h"
#include "services/network/public/mojom/url_loader.mojom-shared.h"
-#include "url/gurl.h"
-
-namespace blink {
-namespace mojom {
-class FetchAPIDataElementDataView;
-} // namespace mojom
-} // namespace blink
+#include "third_party/abseil-cpp/absl/types/variant.h"
namespace network {
-// Represents part of an upload body. This could be one of raw bytes, file data,
-// or a mojo pipe that streams data.
-class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement {
+// Represents a part of a request body consisting of bytes.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElementBytes final {
public:
- static const uint64_t kUnknownSize = std::numeric_limits<uint64_t>::max();
-
- DataElement();
- ~DataElement();
-
- DataElement(const DataElement&) = delete;
- void operator=(const DataElement&) = delete;
- DataElement(DataElement&& other);
- DataElement& operator=(DataElement&& other);
-
- mojom::DataElementType type() const { return type_; }
- const char* bytes() const {
- return reinterpret_cast<const char*>(buf_.data());
- }
- const base::FilePath& path() const { return path_; }
- uint64_t offset() const { return offset_; }
- uint64_t length() const { return length_; }
- const base::Time& expected_modification_time() const {
- return expected_modification_time_;
- }
+ // Do NOT use this constructor outside of mojo deserialization context.
+ DataElementBytes();
- // Sets TYPE_BYTES data. This copies the given data into the element.
- void SetToBytes(const char* bytes, int bytes_len) {
- type_ = mojom::DataElementType::kBytes;
- buf_.assign(reinterpret_cast<const uint8_t*>(bytes),
- reinterpret_cast<const uint8_t*>(bytes + bytes_len));
- length_ = buf_.size();
- }
+ explicit DataElementBytes(std::vector<uint8_t> bytes);
+ DataElementBytes(const DataElementBytes&) = delete;
+ DataElementBytes(DataElementBytes&& other);
+ DataElementBytes& operator=(const DataElementBytes&) = delete;
+ DataElementBytes& operator=(DataElementBytes&& other);
+ ~DataElementBytes();
- // Sets TYPE_BYTES data. This moves the given data vector into the element.
- void SetToBytes(std::vector<uint8_t> bytes) {
- type_ = mojom::DataElementType::kBytes;
- buf_ = std::move(bytes);
- length_ = buf_.size();
- }
+ const std::vector<uint8_t>& bytes() const { return bytes_; }
- // Sets TYPE_BYTES data, and clears the internal bytes buffer.
- // For use with AppendBytes.
- void SetToEmptyBytes() {
- type_ = mojom::DataElementType::kBytes;
- buf_.clear();
- length_ = 0;
+ base::StringPiece AsStringPiece() const {
+ return base::StringPiece(reinterpret_cast<const char*>(bytes_.data()),
+ bytes_.size());
}
- // Copies and appends the given data into the element. SetToEmptyBytes or
- // SetToBytes must be called before this method.
- void AppendBytes(const char* bytes, int bytes_len) {
- DCHECK_EQ(type_, mojom::DataElementType::kBytes);
- DCHECK_NE(length_, std::numeric_limits<uint64_t>::max());
- buf_.insert(buf_.end(), reinterpret_cast<const uint8_t*>(bytes),
- reinterpret_cast<const uint8_t*>(bytes + bytes_len));
- length_ = buf_.size();
- }
+ private:
+ std::vector<uint8_t> bytes_;
+};
- // Sets TYPE_FILE data with range.
- void SetToFilePathRange(const base::FilePath& path,
- uint64_t offset,
- uint64_t length,
- const base::Time& expected_modification_time);
+// Represents a part of a request body consisting of a data pipe. This is
+// typically used for blobs.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElementDataPipe final {
+ public:
+ // Do NOT use this constructor outside of mojo deserialization context.
+ DataElementDataPipe();
- // Sets TYPE_DATA_PIPE data. The data pipe consumer can safely wait for the
- // callback passed to Read() to be invoked before reading the request body.
- void SetToDataPipe(
+ explicit DataElementDataPipe(
mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter);
+ DataElementDataPipe(const DataElementDataPipe&) = delete;
+ DataElementDataPipe(DataElementDataPipe&& other);
+ DataElementDataPipe& operator=(const DataElementDataPipe&) = delete;
+ DataElementDataPipe& operator=(DataElementDataPipe&& other);
+ ~DataElementDataPipe();
- // Sets TYPE_CHUNKED_DATA_PIPE data. The data pipe consumer must not wait
- // for the callback passed to GetSize() to be invoked before reading the
- // request body, as the length may not be known until the entire body has been
- // sent. This method triggers a chunked upload, which not all servers may
- // support, so SetToDataPipe should be used instead, unless talking with a
- // server known to support chunked uploads.
- void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter);
- // Almost same as above except |chunked_data_pipe_getter| is read only once
- // and you must talk with a server supporting chunked upload.
- void SetToReadOnceStream(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter);
-
- // Takes ownership of the DataPipeGetter, if this is of TYPE_DATA_PIPE.
mojo::PendingRemote<mojom::DataPipeGetter> ReleaseDataPipeGetter();
mojo::PendingRemote<mojom::DataPipeGetter> CloneDataPipeGetter() const;
- // Can be called only when this is of type kChunkedDataPipe or
- // kReadOnceStream.
+ private:
+ mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter_;
+};
+
+// Represents a part of a request body consisting of a data pipe without a
+// known size.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElementChunkedDataPipe final {
+ public:
+ using ReadOnlyOnce = base::StrongAlias<class ReadOnlyOnceTag, bool>;
+
+ // Do NOT use this constructor outside of mojo deserialization context.
+ DataElementChunkedDataPipe();
+
+ DataElementChunkedDataPipe(
+ mojo::PendingRemote<mojom::ChunkedDataPipeGetter> data_pipe_getter,
+ ReadOnlyOnce read_only_once);
+ DataElementChunkedDataPipe(const DataElementChunkedDataPipe&) = delete;
+ DataElementChunkedDataPipe(DataElementChunkedDataPipe&& other);
+ DataElementChunkedDataPipe& operator=(const DataElementChunkedDataPipe&) =
+ delete;
+ DataElementChunkedDataPipe& operator=(DataElementChunkedDataPipe&& other);
+ ~DataElementChunkedDataPipe();
+
const mojo::PendingRemote<mojom::ChunkedDataPipeGetter>&
- chunked_data_pipe_getter() const;
- // Takes ownership of the DataPipeGetter, if this is of
- // kChunkedDataPipe or kReadOnceStream.
+ chunked_data_pipe_getter() const {
+ return chunked_data_pipe_getter_;
+ }
mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
ReleaseChunkedDataPipeGetter();
+ ReadOnlyOnce read_only_once() const { return read_only_once_; }
+
private:
- FRIEND_TEST_ALL_PREFIXES(BlobAsyncTransportStrategyTest, TestInvalidParams);
- friend void PrintTo(const DataElement& x, ::std::ostream* os);
- friend struct mojo::StructTraits<network::mojom::DataElementDataView,
- network::DataElement>;
- friend struct mojo::StructTraits<blink::mojom::FetchAPIDataElementDataView,
- network::DataElement>;
- mojom::DataElementType type_;
- // For TYPE_BYTES.
- std::vector<uint8_t> buf_;
- // For TYPE_FILE.
- base::FilePath path_;
- // For TYPE_DATA_PIPE.
- mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter_;
- // For TYPE_CHUNKED_DATA_PIPE.
mojo::PendingRemote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter_;
- uint64_t offset_;
- uint64_t length_;
+ ReadOnlyOnce read_only_once_;
+};
+
+// Represents a part of a request body consisting of (part of) a file.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElementFile final {
+ public:
+ // Do NOT use this constructor outside of mojo deserialization context.
+ DataElementFile();
+
+ DataElementFile(const base::FilePath& path,
+ uint64_t offset,
+ uint64_t length,
+ base::Time expected_modification_time);
+ DataElementFile(const DataElementFile&);
+ DataElementFile& operator=(const DataElementFile&);
+ DataElementFile(DataElementFile&&);
+ DataElementFile& operator=(DataElementFile&&);
+ ~DataElementFile();
+
+ const base::FilePath& path() const { return path_; }
+ uint64_t offset() const { return offset_; }
+ uint64_t length() const { return length_; }
+ base::Time expected_modification_time() const {
+ return expected_modification_time_;
+ }
+
+ private:
+ base::FilePath path_;
+ uint64_t offset_ = 0;
+ uint64_t length_ = 0;
base::Time expected_modification_time_;
};
-COMPONENT_EXPORT(NETWORK_CPP_BASE)
-bool operator==(const DataElement& a, const DataElement& b);
-COMPONENT_EXPORT(NETWORK_CPP_BASE)
-bool operator!=(const DataElement& a, const DataElement& b);
+// Represents part of an upload body. This is a union of various types defined
+// above. See them for details.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement {
+ public:
+ using Tag = mojom::DataElementDataView::Tag;
+
+ // Do NOT use this constructor outside of mojo deserialization context. A
+ // DataElement created by this constructor should be considered as invalid,
+ // and replaced with a valid value as soon as possible.
+ DataElement();
+
+ template <typename T>
+ explicit DataElement(T&& t) : variant_(std::forward<T>(t)) {}
+ DataElement(const DataElement&) = delete;
+ DataElement& operator=(const DataElement&) = delete;
+ DataElement(DataElement&& other);
+ DataElement& operator=(DataElement&& other);
+ ~DataElement();
+
+ Tag type() const {
+ switch (variant_.index()) {
+ case 0:
+ NOTREACHED();
+ return Tag::kBytes;
+ case 1:
+ return Tag::kBytes;
+ case 2:
+ return Tag::kDataPipe;
+ case 3:
+ return Tag::kChunkedDataPipe;
+ case 4:
+ return Tag::kFile;
+ default:
+ NOTREACHED();
+ return Tag::kBytes;
+ }
+ }
+
+ template <typename T>
+ const T& As() const {
+ return absl::get<T>(variant_);
+ }
+
+ template <typename T>
+ T& As() {
+ return absl::get<T>(variant_);
+ }
+
+ private:
+ absl::variant<absl::monostate,
+ DataElementBytes,
+ DataElementDataPipe,
+ DataElementChunkedDataPipe,
+ DataElementFile>
+ variant_;
+};
} // namespace network
diff --git a/chromium/services/network/public/cpp/data_pipe_to_source_stream_unittest.cc b/chromium/services/network/public/cpp/data_pipe_to_source_stream_unittest.cc
index 67d30579dda..28ac773f12b 100644
--- a/chromium/services/network/public/cpp/data_pipe_to_source_stream_unittest.cc
+++ b/chromium/services/network/public/cpp/data_pipe_to_source_stream_unittest.cc
@@ -54,9 +54,8 @@ class DataPipeToSourceStreamTest
sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1,
GetParam().pipe_capacity};
mojo::ScopedDataPipeConsumerHandle consumer_end;
- CHECK_EQ(MOJO_RESULT_OK,
- mojo::CreateDataPipe(&data_pipe_options, &producer_end_,
- &consumer_end));
+ CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&data_pipe_options,
+ producer_end_, consumer_end));
adapter_ =
std::make_unique<DataPipeToSourceStream>(std::move(consumer_end));
}
diff --git a/chromium/services/network/public/cpp/digitally_signed_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/digitally_signed_mojom_traits_unittest.cc
index 7272e5e0327..34ca55e5c2a 100644
--- a/chromium/services/network/public/cpp/digitally_signed_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/digitally_signed_mojom_traits_unittest.cc
@@ -32,7 +32,7 @@ TEST(DigitallySignedTraitsTest, Roundtrips) {
net::ct::DigitallySigned copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::DigitallySigned>(
- &original, &copied))
+ original, copied))
<< "with hash " << hash_alg << " and sig " << sig_alg;
EXPECT_EQ(original.hash_algorithm, copied.hash_algorithm);
EXPECT_EQ(original.signature_algorithm, copied.signature_algorithm);
@@ -49,7 +49,7 @@ TEST(DigitallySignedTraitsTest, EmptySignatureRejected) {
net::ct::DigitallySigned copied;
EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::DigitallySigned>(
- &original, &copied));
+ original, copied));
}
TEST(DigitallySignedTraitsTest, OutOfBoundsEnumsRejected) {
@@ -61,8 +61,8 @@ TEST(DigitallySignedTraitsTest, OutOfBoundsEnumsRejected) {
net::ct::DigitallySigned copied;
EXPECT_DCHECK_DEATH(
- mojo::test::SerializeAndDeserialize<mojom::DigitallySigned>(&original,
- &copied));
+ mojo::test::SerializeAndDeserialize<mojom::DigitallySigned>(original,
+ copied));
}
} // namespace
diff --git a/chromium/services/network/public/cpp/features.cc b/chromium/services/network/public/cpp/features.cc
index cd4d9239360..3efa7d4392d 100644
--- a/chromium/services/network/public/cpp/features.cc
+++ b/chromium/services/network/public/cpp/features.cc
@@ -57,6 +57,13 @@ const base::Feature kPauseBrowserInitiatedHeavyTrafficForP2P{
"PauseBrowserInitiatedHeavyTrafficForP2P",
base::FEATURE_ENABLED_BY_DEFAULT};
+// When kPauseLowPriorityBrowserRequestsOnWeakSignal is enabled, then a subset
+// of the browser initiated requests may be deferred if the device is using
+// cellular connection and the signal quality is low. Android only.
+const base::Feature kPauseLowPriorityBrowserRequestsOnWeakSignal{
+ "PauseLowPriorityBrowserRequestsOnWeakSignal",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// When kCORBProtectionSniffing is enabled CORB sniffs additional same-origin
// resources if they look sensitive.
const base::Feature kCORBProtectionSniffing{"CORBProtectionSniffing",
@@ -85,7 +92,7 @@ const base::Feature kCrossOriginOpenerPolicyReportingOriginTrial{
// Enables Cross-Origin Opener Policy (COOP) reporting.
// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
const base::Feature kCrossOriginOpenerPolicyReporting{
- "CrossOriginOpenerPolicyReporting", base::FEATURE_DISABLED_BY_DEFAULT};
+ "CrossOriginOpenerPolicyReporting", base::FEATURE_ENABLED_BY_DEFAULT};
// Enables Cross-Origin Opener Policy (COOP) access reporting.
// https://github.com/camillelamy/explainers/blob/master/coop_reporting.md#report-blocked-accesses-to-other-windows
@@ -97,14 +104,6 @@ const base::Feature kCrossOriginOpenerPolicyAccessReporting{
const base::Feature kCrossOriginOpenerPolicyByDefault{
"CrossOriginOpenerPolicyByDefault", base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables Cross-Origin Embedder Policy (COEP).
-// https://html.spec.whatwg.org/#coep
-// Currently this feature is enabled for all platforms (including webview).
-// TODO(https://crbug.com/1140432): Remove this flag after M88 Stable + 1 week =
-// 2021-02-01.
-const base::Feature kCrossOriginEmbedderPolicy{
- "CrossOriginEmbedderPolicy", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables the most recent developments on the crossOriginIsolated property.
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/crossOriginIsolated
const base::Feature kCrossOriginIsolated{"CrossOriginIsolated",
@@ -118,7 +117,7 @@ const base::Feature kSplitAuthCacheByNetworkIsolationKey{
// Enable usage of hardcoded DoH upgrade mapping for use in automatic mode.
const base::Feature kDnsOverHttpsUpgrade {
"DnsOverHttpsUpgrade",
-#if BUILDFLAG(IS_ASH) || defined(OS_MAC) || defined(OS_ANDROID) || \
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC) || defined(OS_ANDROID) || \
defined(OS_WIN)
base::FEATURE_ENABLED_BY_DEFAULT
#else
@@ -146,12 +145,6 @@ const base::FeatureParam<std::string>
const base::Feature kDisableKeepaliveFetch{"DisableKeepaliveFetch",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Attach the origin of the destination URL to the "origin" header
-const base::Feature
- kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess{
- "DeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Controls whether a |request_initiator| that mismatches
// |request_initiator_origin_lock| leads to 1) failing the HTTP request and 2)
// calling mojo::ReportBadMessage (on desktop platforms, where NetworkService
@@ -161,17 +154,7 @@ const base::Feature
// See also https://crbug.com/920634
const base::Feature kRequestInitiatorSiteLockEnfocement = {
"RequestInitiatorSiteLockEnfocement",
-#if defined(OS_ANDROID)
- base::FEATURE_DISABLED_BY_DEFAULT};
-#else
base::FEATURE_ENABLED_BY_DEFAULT};
-#endif
-
-// When the CertVerifierService is enabled, certificate verification will not be
-// performed in the network service, but will instead be brokered to a separate
-// cert verification service potentially running in a different process.
-const base::Feature kCertVerifierService{"CertVerifierService",
- base::FEATURE_DISABLED_BY_DEFAULT};
// Enables preprocessing requests with the Trust Tokens API Fetch flags set,
// and handling their responses, according to the protocol.
@@ -212,19 +195,14 @@ const base::FeatureParam<TrustTokenOriginTrialSpec>
// Determines whether Trust Tokens issuance requests should be diverted, at the
// corresponding issuers' request, to the operating system instead of sent
// to the issuers' servers.
+//
+// WARNING: If you rename this param, you must update the corresponding flag
+// entry in about_flags.cc.
const base::FeatureParam<bool> kPlatformProvidedTrustTokenIssuance{
&kTrustTokens, "PlatformProvidedTrustTokenIssuance", false};
-// Enables the Content Security Policy Embedded Enforcement check out of blink
-const base::Feature kOutOfBlinkCSPEE{"OutOfBlinkCSPEE",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
const base::Feature kWebSocketReassembleShortMessages{
"WebSocketReassembleShortMessages", base::FEATURE_ENABLED_BY_DEFAULT};
-// Enables usage of First Party Sets to determine cookie availability.
-constexpr base::Feature kFirstPartySets{"FirstPartySets",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
} // namespace features
} // namespace network
diff --git a/chromium/services/network/public/cpp/features.h b/chromium/services/network/public/cpp/features.h
index a836a51eadc..774efb1dc4b 100644
--- a/chromium/services/network/public/cpp/features.h
+++ b/chromium/services/network/public/cpp/features.h
@@ -27,6 +27,8 @@ extern const base::Feature kDelayRequestsOnMultiplexedConnections;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kPauseBrowserInitiatedHeavyTrafficForP2P;
COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kPauseLowPriorityBrowserRequestsOnWeakSignal;
+COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCORBProtectionSniffing;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kProactivelyThrottleLowPriorityRequests;
@@ -41,8 +43,6 @@ extern const base::Feature kCrossOriginOpenerPolicyAccessReporting;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginOpenerPolicyByDefault;
COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kCrossOriginEmbedderPolicy;
-COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginIsolated;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kSplitAuthCacheByNetworkIsolationKey;
@@ -56,12 +56,7 @@ extern const base::FeatureParam<std::string>
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kDisableKeepaliveFetch;
COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature
- kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess;
-COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kRequestInitiatorSiteLockEnfocement;
-COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kCertVerifierService;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kTrustTokens;
@@ -79,14 +74,8 @@ COMPONENT_EXPORT(NETWORK_CPP)
extern const base::FeatureParam<bool> kPlatformProvidedTrustTokenIssuance;
COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kOutOfBlinkCSPEE;
-
-COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kWebSocketReassembleShortMessages;
-COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kFirstPartySets;
-
} // namespace features
} // namespace network
diff --git a/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc
index 81792349e33..07abe42a6e8 100644
--- a/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc
@@ -21,7 +21,7 @@ TEST(HostResolverMojomTraitsTest, DnsConfigOverridesRoundtrip_Empty) {
net::DnsConfigOverrides deserialized;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::DnsConfigOverrides>(
- &original, &deserialized));
+ original, deserialized));
EXPECT_EQ(original, deserialized);
}
@@ -46,7 +46,7 @@ TEST(HostResolverMojomTraitsTest, DnsConfigOverridesRoundtrip_FullySpecified) {
net::DnsConfigOverrides deserialized;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::DnsConfigOverrides>(
- &original, &deserialized));
+ original, deserialized));
EXPECT_EQ(original, deserialized);
}
@@ -70,7 +70,7 @@ TEST(HostResolverMojomTraitsTest, DnsConfigOverrides_OnlyDnsOverHttpsServers) {
net::DnsConfigOverrides deserialized;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::DnsConfigOverrides>(
- &original, &deserialized));
+ original, deserialized));
EXPECT_EQ(original, deserialized);
}
@@ -81,7 +81,7 @@ TEST(HostResolverMojomTraitsTest, ResolveErrorInfo) {
net::ResolveErrorInfo deserialized;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::ResolveErrorInfo>(
- &original, &deserialized));
+ original, deserialized));
EXPECT_EQ(original, deserialized);
}
diff --git a/chromium/services/network/public/cpp/initiator_lock_compatibility.h b/chromium/services/network/public/cpp/initiator_lock_compatibility.h
index 9275c998bf3..4608fe3f89e 100644
--- a/chromium/services/network/public/cpp/initiator_lock_compatibility.h
+++ b/chromium/services/network/public/cpp/initiator_lock_compatibility.h
@@ -44,9 +44,6 @@ enum class InitiatorLockCompatibility {
// - HTML Imports (see https://crbug.com/871827#c9).
kIncorrectLock = 4,
- // Covered by CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin.
- kExcludedCorbForPlugin = 6,
-
// Covered by AddAllowedRequestInitiatorForPlugin.
kAllowedRequestInitiatorForPlugin = 7,
diff --git a/chromium/services/network/public/cpp/ip_address_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/ip_address_mojom_traits_unittest.cc
index da85b3b5265..43af5b69106 100644
--- a/chromium/services/network/public/cpp/ip_address_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/ip_address_mojom_traits_unittest.cc
@@ -16,7 +16,7 @@ TEST(IPAddressStructTraitsTest, Ipv4) {
IPAddress deserialized;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<network::mojom::IPAddress>(
- &original, &deserialized));
+ original, deserialized));
EXPECT_EQ(original, deserialized);
}
@@ -26,7 +26,7 @@ TEST(IPAddressStructTraitsTest, Ipv6) {
IPAddress deserialized;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<network::mojom::IPAddress>(
- &original, &deserialized));
+ original, deserialized));
EXPECT_EQ(original, deserialized);
}
@@ -40,7 +40,7 @@ TEST(IPAddressStructTraitsTest, InvalidAddress) {
IPAddress deserialized;
EXPECT_FALSE(mojo::test::SerializeAndDeserialize<network::mojom::IPAddress>(
- &original, &deserialized));
+ original, deserialized));
}
} // namespace
diff --git a/chromium/services/network/public/cpp/ip_address_space_util.cc b/chromium/services/network/public/cpp/ip_address_space_util.cc
index 00eeef595da..a9824b1f17f 100644
--- a/chromium/services/network/public/cpp/ip_address_space_util.cc
+++ b/chromium/services/network/public/cpp/ip_address_space_util.cc
@@ -5,9 +5,6 @@
#include "services/network/public/cpp/ip_address_space_util.h"
#include "net/base/ip_address.h"
-#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
-#include "url/gurl.h"
namespace network {
@@ -44,46 +41,4 @@ bool IsLessPublicAddressSpace(IPAddressSpace lhs, IPAddressSpace rhs) {
return CollapseUnknown(lhs) < CollapseUnknown(rhs);
}
-// Helper for CalculateClientAddressSpace() with the same arguments.
-//
-// If the response was fetched via service workers, returns the last URL in the
-// list. Otherwise returns |request_url|.
-//
-// See: https://fetch.spec.whatwg.org/#concept-response-url-list
-const GURL& ResponseUrl(const GURL& request_url,
- const mojom::URLResponseHead* response_head) {
- if (response_head && !response_head->url_list_via_service_worker.empty()) {
- return response_head->url_list_via_service_worker.back();
- }
-
- return request_url;
-}
-
-IPAddressSpace CalculateClientAddressSpace(
- const GURL& url,
- const mojom::URLResponseHead* response_head) {
- if (ResponseUrl(url, response_head).SchemeIsFile()) {
- // See: https://wicg.github.io/cors-rfc1918/#file-url.
- return IPAddressSpace::kLocal;
- }
-
- if (!response_head) {
- return IPAddressSpace::kUnknown;
- }
-
- // First, check whether the response forces itself into a public address space
- // as per https://wicg.github.io/cors-rfc1918/#csp.
- DCHECK(response_head->parsed_headers)
- << "CalculateIPAddressSpace() called for URL " << url
- << " with null parsed_headers.";
- if (response_head->parsed_headers &&
- ShouldTreatAsPublicAddress(
- response_head->parsed_headers->content_security_policy)) {
- return IPAddressSpace::kPublic;
- }
-
- // Otherwise, calculate the address space via the provided IP address.
- return IPAddressToIPAddressSpace(response_head->remote_endpoint.address());
-}
-
} // namespace network
diff --git a/chromium/services/network/public/cpp/ip_address_space_util.h b/chromium/services/network/public/cpp/ip_address_space_util.h
index 4e8423ca1db..440e9bc8de4 100644
--- a/chromium/services/network/public/cpp/ip_address_space_util.h
+++ b/chromium/services/network/public/cpp/ip_address_space_util.h
@@ -6,9 +6,6 @@
#define SERVICES_NETWORK_PUBLIC_CPP_IP_ADDRESS_SPACE_UTIL_H_
#include "services/network/public/mojom/ip_address_space.mojom.h"
-#include "services/network/public/mojom/url_response_head.mojom-forward.h"
-
-class GURL;
namespace net {
@@ -39,30 +36,6 @@ bool COMPONENT_EXPORT(NETWORK_CPP)
IsLessPublicAddressSpace(mojom::IPAddressSpace lhs,
mojom::IPAddressSpace rhs);
-// Given a request URL and response information, this function calculates the
-// IPAddressSpace which should be associated with documents or worker global
-// scopes (collectively: request clients) instantiated from this resource.
-//
-// |response_head| may be nullptr. Caller retains ownership. If not nullptr,
-// then |response_head->parsed_headers| must be populated with the result of
-// parsing |response->headers|.
-//
-// WARNING: This function is defined here for proximity with related code and
-// the data structures involved. However since it deals with higher-level
-// concepts too (documents and worker global scopes), it should probably only be
-// used at the content/ layer or above.
-//
-// See: https://wicg.github.io/cors-rfc1918/#address-space
-//
-// TODO(https://crbug.com/1134601): This implementation treats requests that
-// don't use a URL loader (`about:blank`), as well as requests whose IP address
-// is invalid (`about:srcdoc`, `blob:`, etc.) as `kUnknown`. This is incorrect.
-// We'll eventually want to make sure we inherit from the client's creator
-// in some cases), but safe, as `kUnknown` is treated the same as `kPublic`.
-mojom::IPAddressSpace COMPONENT_EXPORT(NETWORK_CPP)
- CalculateClientAddressSpace(const GURL& url,
- const mojom::URLResponseHead* response_head);
-
} // namespace network
#endif // SERVICES_NETWORK_PUBLIC_CPP_IP_ADDRESS_SPACE_UTIL_H_
diff --git a/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc b/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc
index de54b30f8a9..6891669f9f0 100644
--- a/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc
+++ b/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc
@@ -4,26 +4,19 @@
#include "services/network/public/cpp/ip_address_space_util.h"
-#include <utility>
-
#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "services/network/public/mojom/content_security_policy.mojom.h"
-#include "services/network/public/mojom/parsed_headers.mojom.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
namespace network {
namespace {
-using mojom::ContentSecurityPolicy;
using mojom::IPAddressSpace;
-using mojom::ParsedHeaders;
-using mojom::URLResponseHead;
using net::IPAddress;
using net::IPAddressBytes;
-using net::IPEndPoint;
+
+IPAddress PublicIPv4Address() {
+ return IPAddress(64, 233, 160, 0);
+}
IPAddress PrivateIPv4Address() {
return IPAddress(192, 168, 1, 1);
@@ -32,7 +25,7 @@ IPAddress PrivateIPv4Address() {
TEST(IPAddressSpaceTest, IPAddressToIPAddressSpacev4) {
EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress()), IPAddressSpace::kUnknown);
- EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(64, 233, 160, 0)),
+ EXPECT_EQ(IPAddressToIPAddressSpace(PublicIPv4Address()),
IPAddressSpace::kPublic);
EXPECT_EQ(IPAddressToIPAddressSpace(PrivateIPv4Address()),
@@ -108,82 +101,5 @@ TEST(IPAddressSpaceTest, IsLessPublicAddressSpaceThanUnknown) {
IPAddressSpace::kUnknown));
}
-TEST(IPAddressSpaceTest, CalculateClientAddressSpaceFileURL) {
- EXPECT_EQ(IPAddressSpace::kLocal,
- CalculateClientAddressSpace(GURL("file:///foo"), nullptr));
-}
-
-TEST(IPAddressSpaceTest,
- CalculateIPAddressSpaceFetchedViaServiceWorkerFromFile) {
- URLResponseHead response_head;
- response_head.url_list_via_service_worker.emplace_back("http://bar.test");
- response_head.url_list_via_service_worker.emplace_back("file:///foo");
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(
- IPAddressSpace::kLocal,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceTest,
- CalculateIPAddressSpaceFetchedViaServiceWorkerFromHttp) {
- URLResponseHead response_head;
- response_head.url_list_via_service_worker.emplace_back("file:///foo");
- response_head.url_list_via_service_worker.emplace_back("http://bar.test");
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(
- IPAddressSpace::kUnknown,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceTest,
- CalculateIPAddressSpaceFetchedViaServiceWorkerFromHttpInsteadOfFile) {
- URLResponseHead response_head;
- response_head.url_list_via_service_worker.emplace_back("http://bar.test");
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(IPAddressSpace::kUnknown,
- CalculateClientAddressSpace(GURL("file:///foo"), &response_head));
-}
-
-TEST(IPAddressSpaceTest, CalculateClientAddressSpaceNullResponseHead) {
- EXPECT_EQ(IPAddressSpace::kUnknown,
- CalculateClientAddressSpace(GURL("http://foo.test"), nullptr));
-}
-
-TEST(IPAddressSpaceTest, CalculateClientAddressSpaceEmptyResponseHead) {
- URLResponseHead response_head;
- response_head.parsed_headers = ParsedHeaders::New();
- EXPECT_EQ(
- IPAddressSpace::kUnknown,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceTest, CalculateClientAddressSpaceIPAddress) {
- URLResponseHead response_head;
- response_head.remote_endpoint = IPEndPoint(PrivateIPv4Address(), 1234);
- response_head.parsed_headers = ParsedHeaders::New();
-
- EXPECT_EQ(
- IPAddressSpace::kPrivate,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
-TEST(IPAddressSpaceTest, CalculateClientAddressSpaceTreatAsPublicAddress) {
- URLResponseHead response_head;
- response_head.remote_endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 1234);
-
- auto csp = ContentSecurityPolicy::New();
- csp->treat_as_public_address = true;
- response_head.parsed_headers = ParsedHeaders::New();
- response_head.parsed_headers->content_security_policy.push_back(
- std::move(csp));
-
- EXPECT_EQ(
- IPAddressSpace::kPublic,
- CalculateClientAddressSpace(GURL("http://foo.test"), &response_head));
-}
-
} // namespace
} // namespace network
diff --git a/chromium/services/network/public/cpp/is_potentially_trustworthy.cc b/chromium/services/network/public/cpp/is_potentially_trustworthy.cc
index 37f6fd35b01..3dacd3c4d47 100644
--- a/chromium/services/network/public/cpp/is_potentially_trustworthy.cc
+++ b/chromium/services/network/public/cpp/is_potentially_trustworthy.cc
@@ -176,7 +176,7 @@ std::vector<std::string> ParseSecureOriginAllowlistFromCmdline() {
std::vector<std::string> origin_patterns =
ParseSecureOriginAllowlist(origins_str);
-#if BUILDFLAG(IS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
// For Crostini, we allow access to the default VM/container as a secure
// origin via the hostname penguin.linux.test. We are required to use a
// wildcard for the prefix because we do not know what the port number is.
@@ -199,11 +199,32 @@ bool IsAllowlisted(const std::vector<std::string>& allowlist,
return false;
}
+bool IsSchemeConsideredAuthenticated(base::StringPiece scheme) {
+ // The code below is based on the specification at
+ // https://w3c.github.io/webappsec-secure-contexts/#potentially-trustworthy-origin
+
+ // 7. If origin’s scheme component is one which the user agent considers to be
+ // authenticated, return "Potentially Trustworthy".
+ // Note: See §7.1 Packaged Applications for detail here.
+ //
+ // Note that this ignores some schemes that are considered trustworthy by
+ // higher layers (e.g. see GetSchemesBypassingSecureContextCheck in //chrome).
+ //
+ // See also
+ // - content::ContentClient::AddAdditionalSchemes and
+ // content::ContentClient::Schemes::local_schemes and
+ // content::ContentClient::Schemes::secure_schemes
+ // - url::AddLocalScheme
+ // - url::AddSecureScheme
+ return base::Contains(url::GetSecureSchemes(), scheme) ||
+ base::Contains(url::GetLocalSchemes(), scheme);
+}
+
} // namespace
bool IsOriginPotentiallyTrustworthy(const url::Origin& origin) {
// The code below is based on the specification at
- // https://www.w3.org/TR/powerful-features/#is-origin-trustworthy.
+ // https://w3c.github.io/webappsec-secure-contexts/#potentially-trustworthy-origin
// 1. If origin is an opaque origin, return "Not Trustworthy".
if (origin.opaque())
@@ -214,70 +235,52 @@ bool IsOriginPotentiallyTrustworthy(const url::Origin& origin) {
// 3. If origin’s scheme is either "https" or "wss", return "Potentially
// Trustworthy".
+ // This is somewhat redundant with the GetSecureSchemes()-based check below.
if (GURL::SchemeIsCryptographic(origin.scheme()))
return true;
// 4. If origin’s host component matches one of the CIDR notations 127.0.0.0/8
// or ::1/128 [RFC4632], return "Potentially Trustworthy".
- //
- // Diverging from the spec a bit here - in addition to the hostnames covered
- // by https://www.w3.org/TR/powerful-features/#is-origin-trustworthy, the code
- // below also considers "localhost" to be potentially secure.
- //
- // Cannot just pass |origin.host()| to |HostStringIsLocalhost|, because of the
- // need to also strip the brackets from things like "[::1]".
+ // 5. If origin’s host component is "localhost" or falls within ".localhost",
+ // and the user agent conforms to the name resolution rules in
+ // [let-localhost-be-localhost], return "Potentially Trustworthy".
if (net::IsLocalhost(origin.GetURL()))
return true;
- // 5. If origin’s scheme component is file, return "Potentially Trustworthy".
+ // 6. If origin’s scheme component is file, return "Potentially Trustworthy".
//
- // This is somewhat redundant with the GetLocalSchemes-based check below.
+ // This is somewhat redundant with the GetLocalSchemes-based
+ // IsSchemeConsideredAuthenticated check below.
if (origin.scheme() == url::kFileScheme)
return true;
- // 6. If origin’s scheme component is one which the user agent considers to be
+ // 7. If origin’s scheme component is one which the user agent considers to be
// authenticated, return "Potentially Trustworthy".
// Note: See §7.1 Packaged Applications for detail here.
- //
- // Note that this ignores some schemes that are considered trustworthy by
- // higher layers (e.g. see GetSchemesBypassingSecureContextCheck in //chrome).
- //
- // See also
- // - content::ContentClient::AddAdditionalSchemes and
- // content::ContentClient::Schemes::local_schemes and
- // content::ContentClient::Schemes::secure_schemes
- // - url::AddLocalScheme
- // - url::AddSecureScheme
- if (base::Contains(url::GetSecureSchemes(), origin.scheme()) ||
- base::Contains(url::GetLocalSchemes(), origin.scheme())) {
+ if (IsSchemeConsideredAuthenticated(origin.scheme()))
return true;
- }
- // 7. If origin has been configured as a trustworthy origin, return
+ // 8. If origin has been configured as a trustworthy origin, return
// "Potentially Trustworthy".
// Note: See §7.2 Development Environments for detail here.
if (SecureOriginAllowlist::GetInstance().IsOriginAllowlisted(origin))
return true;
- // 8. Return "Not Trustworthy".
+ // 9. Return "Not Trustworthy".
return false;
}
bool IsUrlPotentiallyTrustworthy(const GURL& url) {
// The code below is based on the specification at
- // https://www.w3.org/TR/powerful-features/#is-url-trustworthy.
+ // https://w3c.github.io/webappsec-secure-contexts/#potentially-trustworthy-url
- // 1. If url’s scheme is "data", return "Not Trustworthy".
- // Note: This aligns the definition of a secure context with the de facto
- // "data: URL as opaque origin" behavior that a majority of today’s
- // browsers have agreed upon, rather than the de jure "data: URL inherits
- // origin" behavior defined in HTML.
- if (url.SchemeIs(url::kDataScheme))
- return false;
-
- // 2. If url is "about:blank" or "about:srcdoc", return "Potentially
+ // 1. If url is "about:blank" or "about:srcdoc", return "Potentially
// Trustworthy".
- if (url.SchemeIs(url::kAboutScheme))
+ if (url.IsAboutBlank() || url.IsAboutSrcdoc())
+ return true;
+
+ // 2. If url’s scheme is "data", return "Potentially Trustworthy".
+ if (url.SchemeIs(url::kDataScheme))
return true;
// 3. Return the result of executing §3.2 Is origin potentially trustworthy?
@@ -285,7 +288,15 @@ bool IsUrlPotentiallyTrustworthy(const GURL& url) {
// Note: The origin of blob: and filesystem: URLs is the origin of the
// context in which they were created. Therefore, blobs created in a
// trustworthy origin will themselves be potentially trustworthy.
- return IsOriginPotentiallyTrustworthy(url::Origin::Create(url));
+ url::Origin origin = url::Origin::Create(url);
+ if (origin.opaque() && IsSchemeConsideredAuthenticated(url.scheme_piece())) {
+ // Authenticated schemes should be treated as trustworthy, even if they
+ // translate into an opaque origin (e.g. because some of them might also be
+ // registered as a no-access, like the //content-layer chrome-error:// or
+ // the //chrome-layer chrome-native://).
+ return true;
+ }
+ return IsOriginPotentiallyTrustworthy(origin);
}
// static
diff --git a/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc b/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
index 3f9adfdb3fd..947dd4a8e55 100644
--- a/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
+++ b/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "services/network/public/cpp/is_potentially_trustworthy_unittest.h"
#include "base/test/scoped_command_line.h"
#include "services/network/public/cpp/network_switches.h"
@@ -10,8 +10,10 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
+#include "url/url_util.h"
namespace network {
+namespace test {
bool IsOriginAllowlisted(const url::Origin& origin) {
return SecureOriginAllowlist::GetInstance().IsOriginAllowlisted(origin);
@@ -21,8 +23,8 @@ bool IsOriginAllowlisted(const char* str) {
return IsOriginAllowlisted(url::Origin::Create(GURL(str)));
}
-bool IsPotentiallyTrustworthy(const char* str) {
- return IsUrlPotentiallyTrustworthy(GURL(str));
+bool IsUrlPotentiallyTrustworthy(const char* str) {
+ return network::IsUrlPotentiallyTrustworthy(GURL(str));
}
std::vector<std::string> CanonicalizeAllowlist(
@@ -32,83 +34,41 @@ std::vector<std::string> CanonicalizeAllowlist(
allowlist, rejected_patterns);
}
-TEST(IsPotentiallyTrustworthy, MainTest) {
- const url::Origin unique_origin;
- EXPECT_FALSE(IsOriginPotentiallyTrustworthy(unique_origin));
- const url::Origin opaque_origin =
- url::Origin::Create(GURL("https://www.example.com"))
- .DeriveNewOpaqueOrigin();
- EXPECT_FALSE(IsOriginPotentiallyTrustworthy(opaque_origin));
-
- EXPECT_TRUE(IsPotentiallyTrustworthy("about:blank"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("about:blank#ref"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("about:srcdoc"));
-
- EXPECT_FALSE(IsPotentiallyTrustworthy("data:test/plain;blah"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("javascript:alert('blah')"));
-
- EXPECT_TRUE(IsPotentiallyTrustworthy("file:///test/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("file:///test/"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("file://localhost/test/"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("file://otherhost/test/"));
-
- EXPECT_TRUE(IsPotentiallyTrustworthy("https://example.com/fun.html"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://example.com/fun.html"));
-
- EXPECT_TRUE(IsPotentiallyTrustworthy("wss://example.com/fun.html"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("ws://example.com/fun.html"));
-
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://localhost/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://localhost./fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://pumpkin.localhost/fun.html"));
+// TODO(crbug.com/1153336 and crbug.com/1164416): Fix product behavior, so that
+// blink::SecurityOrigin::IsSecure(const KURL&) is compatible with
+// network::IsUrlPotentiallyTrustworthy(const GURL&) and then move the tests
+// below to the AbstractTrustworthinessTest.UrlFromString test case in
+// //services/network/public/cpp/is_potentially_trustworthy_unittest.h
+// See also SecurityOriginTest.IsSecure test.
+TEST(IsPotentiallyTrustworthy, Url) {
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("file:///test/fun.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("file:///test/"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("file://localhost/test/"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("file://otherhost/test/"));
+
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://localhost/fun.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://localhost./fun.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://pumpkin.localhost/fun.html"));
EXPECT_TRUE(
- IsPotentiallyTrustworthy("http://crumpet.pumpkin.localhost/fun.html"));
+ IsUrlPotentiallyTrustworthy("http://crumpet.pumpkin.localhost/fun.html"));
EXPECT_TRUE(
- IsPotentiallyTrustworthy("http://pumpkin.localhost:8080/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy(
+ IsUrlPotentiallyTrustworthy("http://pumpkin.localhost:8080/fun.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy(
"http://crumpet.pumpkin.localhost:3000/fun.html"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://localhost.com/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("https://localhost.com/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://127.0.0.1/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("ftp://127.0.0.1/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://127.3.0.1/fun.html"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://127.example.com/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("https://127.example.com/fun.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://127.0.0.1/fun.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("ftp://127.0.0.1/fun.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://127.3.0.1/fun.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://[::1]/fun.html"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://[::2]/fun.html"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://[::1].example.com/fun.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://[::1]/fun.html"));
- // IPv4 mapped IPv6 literals for loopback.
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://[::ffff:127.0.0.1]/"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://[::ffff:7f00:1]"));
-
- // IPv4 compatible IPv6 literal for loopback.
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://[::127.0.0.1]"));
-
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://loopback"));
-
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://localhost6"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("ftp://localhost6.localdomain6"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://localhost.localdomain"));
-
- EXPECT_FALSE(
- IsPotentiallyTrustworthy("filesystem:http://www.example.com/temporary/"));
- EXPECT_FALSE(
- IsPotentiallyTrustworthy("filesystem:ftp://www.example.com/temporary/"));
EXPECT_TRUE(
- IsPotentiallyTrustworthy("filesystem:ftp://127.0.0.1/temporary/"));
- EXPECT_TRUE(IsPotentiallyTrustworthy(
- "filesystem:https://www.example.com/temporary/"));
-
- EXPECT_FALSE(
- IsPotentiallyTrustworthy("blob:http://www.example.com/guid-goes-here"));
- EXPECT_FALSE(
- IsPotentiallyTrustworthy("blob:ftp://www.example.com/guid-goes-here"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("blob:ftp://127.0.0.1/guid-goes-here"));
+ IsUrlPotentiallyTrustworthy("filesystem:ftp://127.0.0.1/temporary/"));
EXPECT_TRUE(
- IsPotentiallyTrustworthy("blob:https://www.example.com/guid-goes-here"));
+ IsUrlPotentiallyTrustworthy("blob:ftp://127.0.0.1/guid-goes-here"));
+
+ EXPECT_FALSE(IsUrlPotentiallyTrustworthy("blob:data:text/html,Hello"));
+ EXPECT_FALSE(IsUrlPotentiallyTrustworthy("blob:about:blank"));
}
class SecureOriginAllowlistTest : public testing::Test {
@@ -121,8 +81,8 @@ class SecureOriginAllowlistTest : public testing::Test {
TEST_F(SecureOriginAllowlistTest, UnsafelyTreatInsecureOriginAsSecure) {
EXPECT_FALSE(IsOriginAllowlisted("http://example.com/a.html"));
EXPECT_FALSE(IsOriginAllowlisted("http://127.example.com/a.html"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://example.com/a.html"));
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://127.example.com/a.html"));
+ EXPECT_FALSE(IsUrlPotentiallyTrustworthy("http://example.com/a.html"));
+ EXPECT_FALSE(IsUrlPotentiallyTrustworthy("http://127.example.com/a.html"));
// Add http://example.com and http://127.example.com to allowlist by
// command-line and see if they are now considered secure origins.
@@ -136,13 +96,13 @@ TEST_F(SecureOriginAllowlistTest, UnsafelyTreatInsecureOriginAsSecure) {
// They should be now allow-listed.
EXPECT_TRUE(IsOriginAllowlisted("http://example.com/a.html"));
EXPECT_TRUE(IsOriginAllowlisted("http://127.example.com/a.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://example.com/a.html"));
- EXPECT_TRUE(IsPotentiallyTrustworthy("http://127.example.com/a.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://example.com/a.html"));
+ EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://127.example.com/a.html"));
// Check that similarly named sites are not considered secure.
- EXPECT_FALSE(IsPotentiallyTrustworthy("http://128.example.com/a.html"));
+ EXPECT_FALSE(IsUrlPotentiallyTrustworthy("http://128.example.com/a.html"));
EXPECT_FALSE(
- IsPotentiallyTrustworthy("http://foobar.127.example.com/a.html"));
+ IsUrlPotentiallyTrustworthy("http://foobar.127.example.com/a.html"));
// When port is not specified, default port is assumed.
EXPECT_TRUE(IsOriginAllowlisted("http://example.com:80/a.html"));
@@ -199,7 +159,8 @@ TEST_F(SecureOriginAllowlistTest, HostnamePatterns) {
GURL input_url(test.test_input);
url::Origin input_origin = url::Origin::Create(input_url);
EXPECT_EQ(test.expected_secure, IsOriginAllowlisted(input_origin));
- EXPECT_EQ(test.expected_secure, IsPotentiallyTrustworthy(test.test_input));
+ EXPECT_EQ(test.expected_secure,
+ IsUrlPotentiallyTrustworthy(test.test_input));
}
}
@@ -254,4 +215,27 @@ TEST_F(SecureOriginAllowlistTest, Canonicalization) {
EXPECT_THAT(canonicalized, ::testing::ElementsAre("*.example.com"));
}
+class TrustworthinessTestTraits : public url::UrlOriginTestTraits {
+ public:
+ using OriginType = url::Origin;
+
+ static bool IsOriginPotentiallyTrustworthy(const OriginType& origin) {
+ return network::IsOriginPotentiallyTrustworthy(origin);
+ }
+ static bool IsUrlPotentiallyTrustworthy(base::StringPiece str) {
+ return network::IsUrlPotentiallyTrustworthy(GURL(str));
+ }
+ static bool IsOriginOfLocalhost(const OriginType& origin) {
+ return net::IsLocalhost(origin.GetURL());
+ }
+
+ // Only static members = no constructors are needed.
+ TrustworthinessTestTraits() = delete;
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(UrlOrigin,
+ AbstractTrustworthinessTest,
+ TrustworthinessTestTraits);
+
+} // namespace test
} // namespace network
diff --git a/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.h b/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.h
new file mode 100644
index 00000000000..0c2ff61b289
--- /dev/null
+++ b/chromium/services/network/public/cpp/is_potentially_trustworthy_unittest.h
@@ -0,0 +1,340 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_IS_POTENTIALLY_TRUSTWORTHY_UNITTEST_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_IS_POTENTIALLY_TRUSTWORTHY_UNITTEST_H_
+
+#include "base/strings/string_piece.h"
+#include "net/base/url_util.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "url/origin_abstract_tests.h"
+
+namespace network {
+namespace test {
+
+// AbstractTrustworthinessTest below abstracts away differences between
+// network::IsOriginPotentiallyTrustworthy and
+// blink::SecurityOrigin::IsPotentiallyTrustworthy by parametrizing the tests
+// with a class that has to expose the same members as url::UrlOriginTestTraits
+// and the following extra members:
+// static bool IsOriginPotentiallyTrustworthy(const OriginType& origin);
+// static bool IsUrlPotentiallyTrustworthy(base::StringPiece str);
+// static bool IsOriginOfLocalhost(const OriginType& origin);
+template <typename TTrustworthinessTraits>
+class AbstractTrustworthinessTest
+ : public url::AbstractOriginTest<TTrustworthinessTraits> {
+ protected:
+ // Wrappers that help ellide away TTrustworthinessTraits.
+ //
+ // Note that calling the wrappers needs to be prefixed with `this->...` to
+ // avoid hitting: explicit qualification required to use member 'FooBar'
+ // from dependent base class.
+ using OriginType = typename TTrustworthinessTraits::OriginType;
+ bool IsOriginPotentiallyTrustworthy(const OriginType& origin) {
+ return TTrustworthinessTraits::IsOriginPotentiallyTrustworthy(origin);
+ }
+ bool IsOriginPotentiallyTrustworthy(base::StringPiece str) {
+ auto origin = this->CreateOriginFromString(str);
+ return TTrustworthinessTraits::IsOriginPotentiallyTrustworthy(origin);
+ }
+ bool IsUrlPotentiallyTrustworthy(base::StringPiece str) {
+ return TTrustworthinessTraits::IsUrlPotentiallyTrustworthy(str);
+ }
+ bool IsOriginOfLocalhost(const OriginType& origin) {
+ return TTrustworthinessTraits::IsOriginOfLocalhost(origin);
+ }
+};
+
+TYPED_TEST_SUITE_P(AbstractTrustworthinessTest);
+
+TYPED_TEST_P(AbstractTrustworthinessTest, OpaqueOrigins) {
+ auto unique_origin = this->CreateUniqueOpaqueOrigin();
+ EXPECT_FALSE(this->IsOriginPotentiallyTrustworthy(unique_origin));
+
+ auto example_origin = this->CreateOriginFromString("https://www.example.com");
+ auto opaque_origin = this->DeriveNewOpaqueOrigin(example_origin);
+ EXPECT_FALSE(this->IsOriginPotentiallyTrustworthy(opaque_origin));
+}
+
+TYPED_TEST_P(AbstractTrustworthinessTest, OriginFromString) {
+ EXPECT_FALSE(this->IsOriginPotentiallyTrustworthy("about:blank"));
+ EXPECT_FALSE(this->IsOriginPotentiallyTrustworthy("about:blank#ref"));
+ EXPECT_FALSE(this->IsOriginPotentiallyTrustworthy("about:srcdoc"));
+ EXPECT_FALSE(
+ this->IsOriginPotentiallyTrustworthy("javascript:alert('blah')"));
+ EXPECT_FALSE(this->IsOriginPotentiallyTrustworthy("data:test/plain;blah"));
+
+ EXPECT_TRUE(this->IsOriginPotentiallyTrustworthy(
+ "quic-transport://example.com/counter"));
+}
+
+TYPED_TEST_P(AbstractTrustworthinessTest, CustomSchemes) {
+ // Custom testing schemes are registered in url::AbstractOriginTest::SetUp.
+ // Let's double-check that schemes we test with have the expected properties.
+ EXPECT_TRUE(base::Contains(url::GetSecureSchemes(), "sec"));
+ EXPECT_TRUE(base::Contains(url::GetSecureSchemes(), "sec-std-with-host"));
+ EXPECT_TRUE(base::Contains(url::GetSecureSchemes(), "sec-noaccess"));
+ EXPECT_TRUE(base::Contains(url::GetNoAccessSchemes(), "sec-noaccess"));
+ EXPECT_TRUE(base::Contains(url::GetNoAccessSchemes(), "noaccess"));
+ EXPECT_TRUE(GURL("sec-std-with-host://blah/x.js").IsStandard());
+
+ // Unrecognized / unknown schemes are not trustworthy.
+ EXPECT_FALSE(
+ this->IsOriginPotentiallyTrustworthy("unknown-scheme://example.com"));
+ EXPECT_FALSE(
+ this->IsUrlPotentiallyTrustworthy("unknown-scheme://example.com"));
+
+ // Secure URLs are trustworthy, even if their scheme is also marked as
+ // no-access, or are not marked as standard. See also //chrome-layer
+ // ChromeContentClientTest.AdditionalSchemes test and
+ // https://crbug.com/734581.
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("sec://blah/x.js"));
+ EXPECT_TRUE(
+ this->IsUrlPotentiallyTrustworthy("sec-std-with-host://blah/x.js"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("sec-noaccess://blah/x.js"));
+ EXPECT_TRUE(
+ this->IsOriginPotentiallyTrustworthy("sec-std-with-host://blah/x.js"));
+ // No-access and non-standard/non-local schemes translate into an
+ // untrustworthy, opaque origin.
+ // TODO(lukasza): Maybe if the spec had a notion of an origin *precursor*,
+ // then it could inspect the scheme of the precursor. After this, it may be
+ // possible to EXPECT_TRUE below...
+ EXPECT_FALSE(this->IsOriginPotentiallyTrustworthy("sec://blah/x.js"));
+ EXPECT_FALSE(
+ this->IsOriginPotentiallyTrustworthy("sec-noaccess://blah/x.js"));
+
+ // No-access, non-secure schemes are untrustworthy.
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("noaccess:blah"));
+ EXPECT_FALSE(this->IsOriginPotentiallyTrustworthy("noaccess:blah"));
+
+ // Standard, but non-secure schemes are untrustworthy.
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("std-with-host://blah/x.js"));
+ EXPECT_FALSE(
+ this->IsOriginPotentiallyTrustworthy("std-with-host://blah/x.js"));
+}
+
+TYPED_TEST_P(AbstractTrustworthinessTest, UrlFromString) {
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:blank"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:blank?x=2"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:blank#ref"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:blank?x=2#ref"));
+
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:srcdoc"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:srcdoc?x=2"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:srcdoc#ref"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:srcdoc?x=2#ref"));
+
+ // The test expectations below document the current behavior, that "emerges"
+ // from how out implementation of IsUrlPotentiallyTrustworthy treats scenarios
+ // that are not covered by the spec. The current behavior might or might not
+ // be the desirable long-term behavior (it just accidentally emerged from the
+ // current implentattion). In particular, not how
+ // https://www.w3.org/TR/secure-contexts/#is-url-trustworthy only mentions how
+ // to deal with "about:srcdoc" and "about:blank", and how
+ // https://github.com/w3c/webappsec-secure-contexts/issues/85 discusses
+ // general treatment of "secure" / "authenticated" schemes (see also
+ // IsSchemeConsideredAuthenticated in product code).
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:about"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("about:mumble"));
+
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("data:test/plain;blah"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("data:text/html,Hello"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("javascript:alert('blah')"));
+
+ EXPECT_TRUE(
+ this->IsUrlPotentiallyTrustworthy("https://example.com/fun.html"));
+ EXPECT_FALSE(
+ this->IsUrlPotentiallyTrustworthy("http://example.com/fun.html"));
+
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("ftp://example.com/"));
+
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy("wss://example.com/fun.html"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("ws://example.com/fun.html"));
+
+ EXPECT_FALSE(
+ this->IsUrlPotentiallyTrustworthy("http://localhost.com/fun.html"));
+ EXPECT_TRUE(
+ this->IsUrlPotentiallyTrustworthy("https://localhost.com/fun.html"));
+
+ EXPECT_FALSE(
+ this->IsUrlPotentiallyTrustworthy("http://127.example.com/fun.html"));
+ EXPECT_TRUE(
+ this->IsUrlPotentiallyTrustworthy("https://127.example.com/fun.html"));
+
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("http://[::2]/fun.html"));
+ EXPECT_FALSE(
+ this->IsUrlPotentiallyTrustworthy("http://[::1].example.com/fun.html"));
+
+ // IPv4 mapped IPv6 literals for loopback.
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("http://[::ffff:127.0.0.1]/"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("http://[::ffff:7f00:1]"));
+
+ // IPv4 compatible IPv6 literal for loopback.
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("http://[::127.0.0.1]"));
+
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("http://loopback"));
+
+ // Legacy localhost names.
+ EXPECT_FALSE(
+ this->IsUrlPotentiallyTrustworthy("http://localhost.localdomain"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("http://localhost6"));
+ EXPECT_FALSE(
+ this->IsUrlPotentiallyTrustworthy("ftp://localhost6.localdomain6"));
+
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy(
+ "filesystem:http://www.example.com/temporary/"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy(
+ "filesystem:ftp://www.example.com/temporary/"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy(
+ "filesystem:https://www.example.com/temporary/"));
+
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy(
+ "blob:http://www.example.com/guid-goes-here"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy(
+ "blob:ftp://www.example.com/guid-goes-here"));
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy(
+ "blob:https://www.example.com/guid-goes-here"));
+
+ EXPECT_FALSE(
+ this->IsUrlPotentiallyTrustworthy("filesystem:data:text/html,Hello"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy("filesystem:about:blank"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy(
+ "blob:blob:https://example.com/578223a1-8c13-17b3-84d5-eca045ae384a"));
+ EXPECT_FALSE(this->IsUrlPotentiallyTrustworthy(
+ "filesystem:blob:https://example.com/"
+ "578223a1-8c13-17b3-84d5-eca045ae384a"));
+
+ EXPECT_TRUE(this->IsUrlPotentiallyTrustworthy(
+ "quic-transport://example.com/counter"));
+}
+
+TYPED_TEST_P(AbstractTrustworthinessTest, TestcasesInheritedFromBlink) {
+ struct TestCase {
+ bool is_potentially_trustworthy;
+ bool is_localhost;
+ const char* url;
+ };
+
+ TestCase inputs[] = {
+ // Access is granted to webservers running on localhost.
+ {true, true, "http://localhost"},
+ {true, true, "http://localhost."},
+ {true, true, "http://LOCALHOST"},
+ {true, true, "http://localhost:100"},
+ {true, true, "http://a.localhost"},
+ {true, true, "http://a.b.localhost"},
+ {true, true, "http://127.0.0.1"},
+ {true, true, "http://127.0.0.2"},
+ {true, true, "http://127.1.0.2"},
+ {true, true, "http://0177.00.00.01"},
+ {true, true, "http://[::1]"},
+ {true, true, "http://[0:0::1]"},
+ {true, true, "http://[0:0:0:0:0:0:0:1]"},
+ {true, true, "http://[::1]:21"},
+ {true, true, "http://127.0.0.1:8080"},
+ {true, true, "ftp://127.0.0.1"},
+ {true, true, "ftp://127.0.0.1:443"},
+ {true, true, "ws://127.0.0.1"},
+
+ // Non-localhost over HTTP
+ {false, false, "http://[1::]"},
+ {false, false, "http://[::2]"},
+ {false, false, "http://[1::1]"},
+ {false, false, "http://[1:2::3]"},
+ {false, false, "http://[::127.0.0.1]"},
+ {false, false, "http://a.127.0.0.1"},
+ {false, false, "http://127.0.0.1.b"},
+ {false, false, "http://localhost.a"},
+
+ // loopback resolves to localhost on Windows, but not
+ // recognized generically here.
+ {false, false, "http://loopback"},
+
+ // IPv4 mapped IPv6 literals for 127.0.0.1.
+ {false, false, "http://[::ffff:127.0.0.1]"},
+ {false, false, "http://[::ffff:7f00:1]"},
+
+ // IPv4 compatible IPv6 literal for 127.0.0.1.
+ {false, false, "http://[::127.0.0.1]"},
+
+ // Legacy localhost names.
+ {false, false, "http://localhost.localdomain"},
+ {false, false, "http://localhost6"},
+ {false, false, "ftp://localhost6.localdomain6"},
+
+ // Secure transports are considered trustworthy.
+ {true, false, "https://foobar.com"},
+ {true, false, "wss://foobar.com"},
+ {true, false, "quic-transport://example.com/counter"},
+
+ // Insecure transports are not considered trustworthy.
+ {false, false, "ftp://foobar.com"},
+ {false, false, "http://foobar.com"},
+ {false, false, "http://foobar.com:443"},
+ {false, false, "ws://foobar.com"},
+ {false, false, "custom-scheme://example.com"},
+
+ // Local files are considered trustworthy.
+ {true, false, "file:///home/foobar/index.html"},
+
+ // blob: URLs must look to the inner URL's origin, and apply the same
+ // rules as above. Spot check some of them
+ {true, true,
+ "blob:http://localhost:1000/578223a1-8c13-17b3-84d5-eca045ae384a"},
+ {true, false,
+ "blob:https://foopy:99/578223a1-8c13-17b3-84d5-eca045ae384a"},
+ {false, false, "blob:http://baz:99/578223a1-8c13-17b3-84d5-eca045ae384a"},
+ {false, false, "blob:ftp://evil:99/578223a1-8c13-17b3-84d5-eca045ae384a"},
+ {false, false, "blob:data:text/html,Hello"},
+ {false, false, "blob:about:blank"},
+ {false, false,
+ "blob:blob:https://example.com/578223a1-8c13-17b3-84d5-eca045ae384a"},
+
+ // filesystem: URLs work the same as blob: URLs, and look to the inner
+ // URL for security origin.
+ {true, true, "filesystem:http://localhost:1000/foo"},
+ {true, false, "filesystem:https://foopy:99/foo"},
+ {false, false, "filesystem:http://baz:99/foo"},
+ {false, false, "filesystem:ftp://evil:99/foo"},
+ {false, false, "filesystem:data:text/html,Hello"},
+ {false, false, "filesystem:about:blank"},
+ {false, false,
+ "filesystem:blob:https://example.com/"
+ "578223a1-8c13-17b3-84d5-eca045ae384a"},
+
+ // about: and data: URLs.
+ {false, false, "about:blank"},
+ {false, false, "about:srcdoc"},
+ {false, false, "data:text/html,Hello"},
+ };
+
+ for (size_t i = 0; i < base::size(inputs); ++i) {
+ SCOPED_TRACE(inputs[i].url);
+ auto origin = this->CreateOriginFromString(inputs[i].url);
+ EXPECT_EQ(inputs[i].is_potentially_trustworthy,
+ this->IsOriginPotentiallyTrustworthy(origin));
+ EXPECT_EQ(inputs[i].is_localhost, this->IsOriginOfLocalhost(origin));
+
+ GURL test_gurl(inputs[i].url);
+ if (!(test_gurl.SchemeIsBlob() || test_gurl.SchemeIsFileSystem())) {
+ // Check that the origin's notion of localhost matches //net's notion of
+ // localhost. This is skipped for blob: and filesystem: URLs since
+ // blink::SecurityOrigin uses their inner URL's origin.
+ EXPECT_EQ(net::IsLocalhost(GURL(inputs[i].url)),
+ this->IsOriginOfLocalhost(origin));
+ }
+ }
+}
+
+REGISTER_TYPED_TEST_SUITE_P(AbstractTrustworthinessTest,
+ OpaqueOrigins,
+ OriginFromString,
+ CustomSchemes,
+ UrlFromString,
+ TestcasesInheritedFromBlink);
+
+} // namespace test
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_IS_POTENTIALLY_TRUSTWORTHY_UNITTEST_H_
diff --git a/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc b/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc
index b9434b1a64e..a2e0f3ae2df 100644
--- a/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc
@@ -51,6 +51,7 @@ bool StructTraits<network::mojom::IsolationInfoDataView, net::IsolationInfo>::
base::Optional<url::Origin> frame_origin;
net::SiteForCookies site_for_cookies;
net::IsolationInfo::RequestType request_type;
+ base::Optional<std::vector<net::SchemefulSite>> mojo_party_context;
if (!data.ReadTopFrameOrigin(&top_frame_origin)) {
network::debug::SetDeserializationCrashKeyString("isolation_top_origin");
@@ -61,14 +62,23 @@ bool StructTraits<network::mojom::IsolationInfoDataView, net::IsolationInfo>::
return false;
}
if (!data.ReadSiteForCookies(&site_for_cookies) ||
- !data.ReadRequestType(&request_type)) {
+ !data.ReadRequestType(&request_type) ||
+ !data.ReadPartyContext(&mojo_party_context)) {
return false;
}
+ base::Optional<std::set<net::SchemefulSite>> party_context;
+ if (mojo_party_context.has_value()) {
+ party_context = std::set<net::SchemefulSite>(mojo_party_context->begin(),
+ mojo_party_context->end());
+ if (party_context->size() != mojo_party_context->size())
+ return false;
+ }
+
base::Optional<net::IsolationInfo> isolation_info =
- net::IsolationInfo::CreateIfConsistent(request_type, top_frame_origin,
- frame_origin, site_for_cookies,
- data.opaque_and_non_transient());
+ net::IsolationInfo::CreateIfConsistent(
+ request_type, top_frame_origin, frame_origin, site_for_cookies,
+ data.opaque_and_non_transient(), std::move(party_context));
if (!isolation_info) {
network::debug::SetDeserializationCrashKeyString("isolation_inconsistent");
return false;
diff --git a/chromium/services/network/public/cpp/isolation_info_mojom_traits.h b/chromium/services/network/public/cpp/isolation_info_mojom_traits.h
index 44a123f8e8a..c9a5a323eb5 100644
--- a/chromium/services/network/public/cpp/isolation_info_mojom_traits.h
+++ b/chromium/services/network/public/cpp/isolation_info_mojom_traits.h
@@ -9,6 +9,7 @@
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/base/isolation_info.h"
#include "net/cookies/site_for_cookies.h"
+#include "services/network/public/cpp/schemeful_site_mojom_traits.h"
#include "services/network/public/mojom/isolation_info.mojom-shared.h"
#include "url/mojom/origin_mojom_traits.h"
#include "url/origin.h"
@@ -52,6 +53,11 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
return input.site_for_cookies();
}
+ static const base::Optional<std::set<net::SchemefulSite>> party_context(
+ const net::IsolationInfo& input) {
+ return input.party_context_;
+ }
+
static bool Read(network::mojom::IsolationInfoDataView data,
net::IsolationInfo* out);
};
diff --git a/chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc
index 7e2b034d1ce..f4260564cd5 100644
--- a/chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/isolation_info_mojom_traits_unittest.cc
@@ -20,21 +20,34 @@ namespace mojo {
TEST(IsolationInfoMojomTraitsTest, SerializeAndDeserialize) {
const url::Origin kOrigin1 = url::Origin::Create(GURL("https://a.test/"));
const url::Origin kOrigin2 = url::Origin::Create(GURL("https://b.test/"));
+
+ const base::Optional<std::set<net::SchemefulSite>> kPartyContext1 =
+ base::nullopt;
+ const base::Optional<std::set<net::SchemefulSite>> kPartyContext2 =
+ std::set<net::SchemefulSite>();
+ const base::Optional<std::set<net::SchemefulSite>> kPartyContext3 =
+ std::set<net::SchemefulSite>{
+ net::SchemefulSite(url::Origin::Create(GURL("https://c.test/")))};
+
std::vector<net::IsolationInfo> keys = {
net::IsolationInfo(),
net::IsolationInfo::CreateTransient(),
net::IsolationInfo::CreateOpaqueAndNonTransient(),
- net::IsolationInfo::Create(net::IsolationInfo::RequestType::kMainFrame,
- kOrigin1, kOrigin1,
- net::SiteForCookies::FromOrigin(kOrigin1)),
+ net::IsolationInfo::Create(
+ net::IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin1,
+ net::SiteForCookies::FromOrigin(kOrigin1), kPartyContext2),
+ net::IsolationInfo::Create(
+ net::IsolationInfo::RequestType::kSubFrame, kOrigin1, kOrigin2,
+ net::SiteForCookies::FromOrigin(kOrigin1), kPartyContext2),
net::IsolationInfo::Create(net::IsolationInfo::RequestType::kSubFrame,
- kOrigin1, kOrigin2,
- net::SiteForCookies::FromOrigin(kOrigin1)),
- net::IsolationInfo::Create(net::IsolationInfo::RequestType::kSubFrame,
- kOrigin1, kOrigin2, net::SiteForCookies()),
+ kOrigin1, kOrigin2, net::SiteForCookies(),
+ kPartyContext3),
+ net::IsolationInfo::Create(
+ net::IsolationInfo::RequestType::kOther, kOrigin1, kOrigin1,
+ net::SiteForCookies::FromOrigin(kOrigin1), kPartyContext1),
net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
- kOrigin1, kOrigin1,
- net::SiteForCookies::FromOrigin(kOrigin1)),
+ url::Origin(), url::Origin(),
+ net::SiteForCookies(), kPartyContext1),
net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
url::Origin(), url::Origin(),
net::SiteForCookies()),
@@ -44,7 +57,7 @@ TEST(IsolationInfoMojomTraitsTest, SerializeAndDeserialize) {
net::IsolationInfo copied;
EXPECT_TRUE(
mojo::test::SerializeAndDeserialize<network::mojom::IsolationInfo>(
- &original, &copied));
+ original, copied));
EXPECT_TRUE(original.IsEqualForTesting(copied));
}
}
diff --git a/chromium/services/network/public/cpp/isolation_opt_in_hints.cc b/chromium/services/network/public/cpp/isolation_opt_in_hints.cc
deleted file mode 100644
index 8453fcaabe6..00000000000
--- a/chromium/services/network/public/cpp/isolation_opt_in_hints.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/public/cpp/isolation_opt_in_hints.h"
-
-#include <type_traits>
-
-namespace network {
-
-IsolationOptInHints GetIsolationOptInHintFromString(
- const std::string& hint_str) {
- if (hint_str == "prefer_isolated_event_loop")
- return IsolationOptInHints::PREFER_ISOLATED_EVENT_LOOP;
- if (hint_str == "prefer_isolated_memory")
- return IsolationOptInHints::PREFER_ISOLATED_MEMORY;
- if (hint_str == "for_side_channel_protection")
- return IsolationOptInHints::FOR_SIDE_CHANNEL_PROTECTION;
- if (hint_str == "for_memory_measurement")
- return IsolationOptInHints::FOR_MEMORY_ISOLATION;
- return IsolationOptInHints::NO_HINTS;
-}
-
-IsolationOptInHints& operator|=(IsolationOptInHints& lhs,
- IsolationOptInHints& rhs) {
- lhs = static_cast<IsolationOptInHints>(
- static_cast<std::underlying_type<IsolationOptInHints>::type>(lhs) |
- static_cast<std::underlying_type<IsolationOptInHints>::type>(rhs));
- return lhs;
-}
-
-IsolationOptInHints& operator&(IsolationOptInHints& lhs,
- IsolationOptInHints& rhs) {
- lhs = static_cast<IsolationOptInHints>(
- static_cast<std::underlying_type<IsolationOptInHints>::type>(lhs) &
- static_cast<std::underlying_type<IsolationOptInHints>::type>(rhs));
- return lhs;
-}
-
-} // namespace network
diff --git a/chromium/services/network/public/cpp/isolation_opt_in_hints.h b/chromium/services/network/public/cpp/isolation_opt_in_hints.h
deleted file mode 100644
index 62ccf974275..00000000000
--- a/chromium/services/network/public/cpp/isolation_opt_in_hints.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_NETWORK_PUBLIC_CPP_ISOLATION_OPT_IN_HINTS_H_
-#define SERVICES_NETWORK_PUBLIC_CPP_ISOLATION_OPT_IN_HINTS_H_
-
-#include <string>
-
-#include "base/component_export.h"
-
-namespace network {
-
-// The following definitions correspond to the draft spec found here:
-// https://github.com/domenic/origin-isolation#proposed-hints.
-enum class IsolationOptInHints : unsigned {
- NO_HINTS = 0x0,
- PREFER_ISOLATED_EVENT_LOOP = 0x1,
- PREFER_ISOLATED_MEMORY = 0x2,
- FOR_SIDE_CHANNEL_PROTECTION = 0x4,
- FOR_MEMORY_ISOLATION = 0x8,
- ALL_HINTS_ACTIVE = 0xF
-};
-
-// Converts hint strings into their corresponding IsolationOptInHints values.
-// The hint strings are specified at
-// https://github.com/domenic/origin-isolation#proposed-hints.
-COMPONENT_EXPORT(NETWORK_CPP_BASE)
-IsolationOptInHints GetIsolationOptInHintFromString(
- const std::string& hint_str);
-
-COMPONENT_EXPORT(NETWORK_CPP_BASE)
-IsolationOptInHints& operator|=(IsolationOptInHints& lhs,
- IsolationOptInHints& rhs);
-
-COMPONENT_EXPORT(NETWORK_CPP_BASE)
-IsolationOptInHints& operator&(IsolationOptInHints& lhs,
- IsolationOptInHints& rhs);
-
-} // namespace network
-#endif // SERVICES_NETWORK_PUBLIC_CPP_ISOLATION_OPT_IN_HINTS_H_
diff --git a/chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc b/chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc
index 9039014d7f8..67ec1220638 100644
--- a/chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc
@@ -34,6 +34,8 @@ bool StructTraits<network::mojom::LoadTimingInfoDataView, net::LoadTimingInfo>::
data.ReadSendEnd(&out->send_end) &&
data.ReadReceiveHeadersStart(&out->receive_headers_start) &&
data.ReadReceiveHeadersEnd(&out->receive_headers_end) &&
+ data.ReadReceiveNonInformationalHeadersStart(
+ &out->receive_non_informational_headers_start) &&
data.ReadFirstEarlyHintsTime(&out->first_early_hints_time) &&
data.ReadPushStart(&out->push_start) &&
data.ReadPushEnd(&out->push_end) &&
diff --git a/chromium/services/network/public/cpp/load_timing_info_mojom_traits.h b/chromium/services/network/public/cpp/load_timing_info_mojom_traits.h
index 0bec1dbc1b5..64d69a622ce 100644
--- a/chromium/services/network/public/cpp/load_timing_info_mojom_traits.h
+++ b/chromium/services/network/public/cpp/load_timing_info_mojom_traits.h
@@ -96,6 +96,11 @@ struct StructTraits<network::mojom::LoadTimingInfoDataView,
return obj.receive_headers_end;
}
+ static base::TimeTicks receive_non_informational_headers_start(
+ const net::LoadTimingInfo& obj) {
+ return obj.receive_non_informational_headers_start;
+ }
+
static base::TimeTicks first_early_hints_time(
const net::LoadTimingInfo& obj) {
return obj.first_early_hints_time;
diff --git a/chromium/services/network/public/cpp/net_ipc_param_traits.cc b/chromium/services/network/public/cpp/net_ipc_param_traits.cc
index 9567cfd9c8e..f7f7db1f7c2 100644
--- a/chromium/services/network/public/cpp/net_ipc_param_traits.cc
+++ b/chromium/services/network/public/cpp/net_ipc_param_traits.cc
@@ -11,30 +11,6 @@
namespace IPC {
-void ParamTraits<net::AuthChallengeInfo>::Write(base::Pickle* m,
- const param_type& p) {
- WriteParam(m, p.is_proxy);
- WriteParam(m, p.challenger);
- WriteParam(m, p.scheme);
- WriteParam(m, p.realm);
- WriteParam(m, p.challenge);
- WriteParam(m, p.path);
-}
-
-bool ParamTraits<net::AuthChallengeInfo>::Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r) {
- return ReadParam(m, iter, &r->is_proxy) &&
- ReadParam(m, iter, &r->challenger) && ReadParam(m, iter, &r->scheme) &&
- ReadParam(m, iter, &r->realm) && ReadParam(m, iter, &r->challenge) &&
- ReadParam(m, iter, &r->path);
-}
-
-void ParamTraits<net::AuthChallengeInfo>::Log(const param_type& p,
- std::string* l) {
- l->append("<AuthChallengeInfo>");
-}
-
void ParamTraits<net::AuthCredentials>::Write(base::Pickle* m,
const param_type& p) {
WriteParam(m, p.username());
@@ -472,6 +448,7 @@ void ParamTraits<net::LoadTimingInfo>::Write(base::Pickle* m,
WriteParam(m, p.send_end);
WriteParam(m, p.receive_headers_start);
WriteParam(m, p.receive_headers_end);
+ WriteParam(m, p.receive_non_informational_headers_start);
WriteParam(m, p.first_early_hints_time);
WriteParam(m, p.push_start);
WriteParam(m, p.push_end);
@@ -503,6 +480,7 @@ bool ParamTraits<net::LoadTimingInfo>::Read(const base::Pickle* m,
ReadParam(m, iter, &r->send_end) &&
ReadParam(m, iter, &r->receive_headers_start) &&
ReadParam(m, iter, &r->receive_headers_end) &&
+ ReadParam(m, iter, &r->receive_non_informational_headers_start) &&
ReadParam(m, iter, &r->first_early_hints_time) &&
ReadParam(m, iter, &r->push_start) && ReadParam(m, iter, &r->push_end);
}
@@ -542,6 +520,8 @@ void ParamTraits<net::LoadTimingInfo>::Log(const param_type& p,
l->append(", ");
LogParam(p.receive_headers_end, l);
l->append(", ");
+ LogParam(p.receive_non_informational_headers_start, l);
+ l->append(", ");
LogParam(p.first_early_hints_time, l);
l->append(", ");
LogParam(p.push_start, l);
@@ -552,23 +532,19 @@ void ParamTraits<net::LoadTimingInfo>::Log(const param_type& p,
void ParamTraits<net::SiteForCookies>::Write(base::Pickle* m,
const param_type& p) {
- WriteParam(m, p.scheme());
- WriteParam(m, p.registrable_domain());
+ WriteParam(m, p.site());
WriteParam(m, p.schemefully_same());
}
bool ParamTraits<net::SiteForCookies>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
- std::string scheme, registrable_domain;
+ net::SchemefulSite site;
bool schemefully_same;
- if (!ReadParam(m, iter, &scheme) ||
- !ReadParam(m, iter, &registrable_domain) ||
- !ReadParam(m, iter, &schemefully_same))
+ if (!ReadParam(m, iter, &site) || !ReadParam(m, iter, &schemefully_same))
return false;
- return net::SiteForCookies::FromWire(scheme, registrable_domain,
- schemefully_same, r);
+ return net::SiteForCookies::FromWire(site, schemefully_same, r);
}
void ParamTraits<net::SiteForCookies>::Log(const param_type& p,
@@ -618,6 +594,26 @@ void ParamTraits<url::Origin>::Log(const url::Origin& p, std::string* l) {
l->append(p.Serialize());
}
+void ParamTraits<net::SchemefulSite>::Write(base::Pickle* m,
+ const net::SchemefulSite& p) {
+ WriteParam(m, p.site_as_origin_);
+}
+
+bool ParamTraits<net::SchemefulSite>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ net::SchemefulSite* p) {
+ url::Origin site_as_origin;
+ if (!ReadParam(m, iter, &site_as_origin))
+ return false;
+
+ return net::SchemefulSite::FromWire(site_as_origin, p);
+}
+
+void ParamTraits<net::SchemefulSite>::Log(const net::SchemefulSite& p,
+ std::string* l) {
+ l->append(p.Serialize());
+}
+
} // namespace IPC
// Generation of IPC definitions.
diff --git a/chromium/services/network/public/cpp/net_ipc_param_traits.h b/chromium/services/network/public/cpp/net_ipc_param_traits.h
index 53f744155be..5af4b3dabc0 100644
--- a/chromium/services/network/public/cpp/net_ipc_param_traits.h
+++ b/chromium/services/network/public/cpp/net_ipc_param_traits.h
@@ -19,6 +19,7 @@
#include "net/base/load_timing_info.h"
#include "net/base/proxy_server.h"
#include "net/base/request_priority.h"
+#include "net/base/schemeful_site.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/ct_policy_status.h"
#include "net/cert/signed_certificate_timestamp.h"
@@ -51,16 +52,6 @@
namespace IPC {
template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::AuthChallengeInfo> {
- typedef net::AuthChallengeInfo param_type;
- static void Write(base::Pickle* m, const param_type& p);
- static bool Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::AuthCredentials> {
typedef net::AuthCredentials param_type;
static void Write(base::Pickle* m, const param_type& p);
@@ -244,6 +235,16 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<url::Origin> {
static void Log(const param_type& p, std::string* l);
};
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::SchemefulSite> {
+ typedef net::SchemefulSite param_type;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
+ static void Log(const param_type& p, std::string* l);
+};
+
} // namespace IPC
#endif // INTERNAL_SERVICES_NETWORK_PUBLIC_CPP_NET_IPC_PARAM_TRAITS_H_
diff --git a/chromium/services/network/public/cpp/network_ipc_param_traits.cc b/chromium/services/network/public/cpp/network_ipc_param_traits.cc
index edab086e7d1..eb3522eebf7 100644
--- a/chromium/services/network/public/cpp/network_ipc_param_traits.cc
+++ b/chromium/services/network/public/cpp/network_ipc_param_traits.cc
@@ -9,161 +9,6 @@
#include "ipc/ipc_platform_file.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/http/http_util.h"
-#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
-#include "services/network/public/mojom/data_pipe_getter.mojom.h"
-#include "services/network/public/mojom/url_loader.mojom-shared.h"
-
-namespace IPC {
-
-void ParamTraits<network::DataElement>::Write(base::Pickle* m,
- const param_type& p) {
- WriteParam(m, static_cast<int>(p.type()));
- switch (p.type()) {
- case network::mojom::DataElementType::kBytes: {
- m->WriteData(p.bytes(), static_cast<int>(p.length()));
- break;
- }
- case network::mojom::DataElementType::kFile: {
- WriteParam(m, p.path());
- WriteParam(m, p.offset());
- WriteParam(m, p.length());
- WriteParam(m, p.expected_modification_time());
- break;
- }
- case network::mojom::DataElementType::kDataPipe: {
- WriteParam(m, p.CloneDataPipeGetter().PassPipe().release());
- break;
- }
- case network::mojom::DataElementType::kChunkedDataPipe: {
- WriteParam(m, const_cast<network::DataElement&>(p)
- .ReleaseChunkedDataPipeGetter()
- .PassPipe()
- .release());
- break;
- }
- case network::mojom::DataElementType::kReadOnceStream:
- case network::mojom::DataElementType::kUnknown: {
- NOTREACHED();
- break;
- }
- }
-}
-
-bool ParamTraits<network::DataElement>::Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r) {
- int type;
- if (!ReadParam(m, iter, &type))
- return false;
- switch (static_cast<network::mojom::DataElementType>(type)) {
- case network::mojom::DataElementType::kBytes: {
- const char* data;
- int len;
- if (!iter->ReadData(&data, &len))
- return false;
- r->SetToBytes(data, len);
- return true;
- }
- case network::mojom::DataElementType::kFile: {
- base::FilePath file_path;
- uint64_t offset, length;
- base::Time expected_modification_time;
- if (!ReadParam(m, iter, &file_path))
- return false;
- if (!ReadParam(m, iter, &offset))
- return false;
- if (!ReadParam(m, iter, &length))
- return false;
- if (!ReadParam(m, iter, &expected_modification_time))
- return false;
- r->SetToFilePathRange(file_path, offset, length,
- expected_modification_time);
- return true;
- }
- case network::mojom::DataElementType::kDataPipe: {
- mojo::MessagePipeHandle message_pipe;
- if (!ReadParam(m, iter, &message_pipe))
- return false;
- mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter(
- mojo::ScopedMessagePipeHandle(message_pipe), 0u);
- r->SetToDataPipe(std::move(data_pipe_getter));
- return true;
- }
- case network::mojom::DataElementType::kChunkedDataPipe: {
- mojo::MessagePipeHandle message_pipe;
- if (!ReadParam(m, iter, &message_pipe))
- return false;
- mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter(mojo::ScopedMessagePipeHandle(message_pipe),
- 0u);
-
- r->SetToChunkedDataPipe(std::move(chunked_data_pipe_getter));
- return true;
- }
- case network::mojom::DataElementType::kReadOnceStream:
- case network::mojom::DataElementType::kUnknown: {
- NOTREACHED();
- return false;
- }
- }
- return false;
-}
-
-void ParamTraits<network::DataElement>::Log(const param_type& p,
- std::string* l) {
- l->append("<network::DataElement>");
-}
-
-void ParamTraits<scoped_refptr<network::ResourceRequestBody>>::Write(
- base::Pickle* m,
- const param_type& p) {
- WriteParam(m, p.get() != nullptr);
- if (p.get()) {
- WriteParam(m, *p->elements());
- WriteParam(m, p->identifier());
- WriteParam(m, p->contains_sensitive_info());
- }
-}
-
-bool ParamTraits<scoped_refptr<network::ResourceRequestBody>>::Read(
- const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r) {
- bool has_object;
- if (!ReadParam(m, iter, &has_object))
- return false;
- if (!has_object)
- return true;
- std::vector<network::DataElement> elements;
- if (!ReadParam(m, iter, &elements))
- return false;
- // A chunked element is only allowed if it's the only one element.
- if (elements.size() > 1) {
- for (const auto& element : elements) {
- if (element.type() == network::mojom::DataElementType::kChunkedDataPipe)
- return false;
- }
- }
- int64_t identifier;
- if (!ReadParam(m, iter, &identifier))
- return false;
- bool contains_sensitive_info;
- if (!ReadParam(m, iter, &contains_sensitive_info))
- return false;
- *r = new network::ResourceRequestBody;
- (*r)->swap_elements(&elements);
- (*r)->set_identifier(identifier);
- (*r)->set_contains_sensitive_info(contains_sensitive_info);
- return true;
-}
-
-void ParamTraits<scoped_refptr<network::ResourceRequestBody>>::Log(
- const param_type& p,
- std::string* l) {
- l->append("<ResourceRequestBody>");
-}
-
-} // namespace IPC
// Generation of IPC definitions.
diff --git a/chromium/services/network/public/cpp/network_ipc_param_traits.h b/chromium/services/network/public/cpp/network_ipc_param_traits.h
index a898d3f7ad7..25260fbb5a0 100644
--- a/chromium/services/network/public/cpp/network_ipc_param_traits.h
+++ b/chromium/services/network/public/cpp/network_ipc_param_traits.h
@@ -25,10 +25,8 @@
#include "net/nqe/effective_connection_type.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_info.h"
-#include "services/network/public/cpp/isolation_opt_in_hints.h"
#include "services/network/public/cpp/net_ipc_param_traits.h"
#include "services/network/public/cpp/origin_policy.h"
-#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/blocked_by_response_reason.mojom-shared.h"
#include "services/network/public/mojom/cors.mojom-shared.h"
@@ -41,43 +39,6 @@
// This file defines IPC::ParamTraits for network:: classes / structs.
// For IPC::ParamTraits for net:: class / structs, see net_ipc_param_traits.h.
-#ifndef INTERNAL_SERVICES_NETWORK_PUBLIC_CPP_NETWORK_IPC_PARAM_TRAITS_H_
-#define INTERNAL_SERVICES_NETWORK_PUBLIC_CPP_NETWORK_IPC_PARAM_TRAITS_H_
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT COMPONENT_EXPORT(NETWORK_CPP_BASE)
-
-namespace IPC {
-
-// TODO(Richard): Remove this traits after usage of
-// content::mojom::OpenURLParams disappears.
-template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<network::DataElement> {
- typedef network::DataElement param_type;
- static void Write(base::Pickle* m, const param_type& p);
- static bool Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-// TODO(Richard): Remove this traits after usage of OpenURLParams struct
-// disappears.
-template <>
-struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
- ParamTraits<scoped_refptr<network::ResourceRequestBody>> {
- typedef scoped_refptr<network::ResourceRequestBody> param_type;
- static void Write(base::Pickle* m, const param_type& p);
- static bool Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-} // namespace IPC
-
-#endif // INTERNAL_SERVICES_NETWORK_PUBLIC_CPP_NETWORK_IPC_PARAM_TRAITS_H_
-
IPC_ENUM_TRAITS_MAX_VALUE(network::mojom::CorsError,
network::mojom::CorsError::kMaxValue)
@@ -132,15 +93,11 @@ IPC_ENUM_TRAITS_MAX_VALUE(network::mojom::TrustTokenOperationStatus,
IPC_ENUM_TRAITS_MAX_VALUE(network::OriginPolicyState,
network::OriginPolicyState::kMaxValue)
-IPC_ENUM_TRAITS_MAX_VALUE(network::IsolationOptInHints,
- network::IsolationOptInHints::ALL_HINTS_ACTIVE)
-
IPC_STRUCT_TRAITS_BEGIN(network::OriginPolicyContents)
IPC_STRUCT_TRAITS_MEMBER(ids)
IPC_STRUCT_TRAITS_MEMBER(feature_policy)
IPC_STRUCT_TRAITS_MEMBER(content_security_policies)
IPC_STRUCT_TRAITS_MEMBER(content_security_policies_report_only)
- IPC_STRUCT_TRAITS_MEMBER(isolation_optin_hints)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(network::OriginPolicy)
diff --git a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc
index e0e75a8009b..7b139feb984 100644
--- a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "services/network/public/cpp/network_isolation_key_mojom_traits.h"
+
#include "net/base/features.h"
namespace mojo {
@@ -11,7 +12,7 @@ bool StructTraits<network::mojom::NetworkIsolationKeyDataView,
net::NetworkIsolationKey>::
Read(network::mojom::NetworkIsolationKeyDataView data,
net::NetworkIsolationKey* out) {
- base::Optional<url::Origin> top_frame_site, frame_site;
+ base::Optional<net::SchemefulSite> top_frame_site, frame_site;
if (!data.ReadTopFrameSite(&top_frame_site))
return false;
if (!data.ReadFrameSite(&frame_site))
@@ -25,9 +26,10 @@ bool StructTraits<network::mojom::NetworkIsolationKeyDataView,
if (!frame_site.has_value()) {
DCHECK(!base::FeatureList::IsEnabled(
net::features::kAppendFrameOriginToNetworkIsolationKey));
- frame_site = url::Origin();
+ frame_site = net::SchemefulSite();
}
- *out = net::NetworkIsolationKey(top_frame_site.value(), frame_site.value());
+ *out = net::NetworkIsolationKey(std::move(top_frame_site.value()),
+ std::move(frame_site.value()));
} else {
*out = net::NetworkIsolationKey();
}
diff --git a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h
index 80043f328e3..c6e554e0674 100644
--- a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h
+++ b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits.h
@@ -7,9 +7,9 @@
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/base/network_isolation_key.h"
+#include "net/base/schemeful_site.h"
+#include "services/network/public/cpp/schemeful_site_mojom_traits.h"
#include "services/network/public/mojom/network_isolation_key.mojom-shared.h"
-#include "url/mojom/origin_mojom_traits.h"
-#include "url/origin.h"
namespace mojo {
@@ -17,12 +17,12 @@ template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
StructTraits<network::mojom::NetworkIsolationKeyDataView,
net::NetworkIsolationKey> {
- static const base::Optional<url::Origin>& top_frame_site(
+ static const base::Optional<net::SchemefulSite>& top_frame_site(
const net::NetworkIsolationKey& input) {
return input.GetTopFrameSite();
}
- static const base::Optional<url::Origin>& frame_site(
+ static const base::Optional<net::SchemefulSite>& frame_site(
const net::NetworkIsolationKey& input) {
return input.GetFrameSite();
}
diff --git a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc
index 4482335ea0b..65c0ff6757c 100644
--- a/chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/network_isolation_key_mojom_traits_unittest.cc
@@ -26,7 +26,7 @@ TEST(NetworkIsolationKeyMojomTraitsTest, SerializeAndDeserialize) {
SCOPED_TRACE(original.ToDebugString());
net::NetworkIsolationKey copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- network::mojom::NetworkIsolationKey>(&original, &copied));
+ network::mojom::NetworkIsolationKey>(original, copied));
EXPECT_EQ(original, copied);
}
}
@@ -57,7 +57,7 @@ TEST_F(NetworkIsolationKeyMojomTraitsWithFrameOriginTest,
SCOPED_TRACE(original.ToDebugString());
net::NetworkIsolationKey copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- network::mojom::NetworkIsolationKey>(&original, &copied));
+ network::mojom::NetworkIsolationKey>(original, copied));
EXPECT_EQ(original, copied);
EXPECT_EQ(original.GetTopFrameSite(), copied.GetTopFrameSite());
EXPECT_EQ(original.GetFrameSite(), copied.GetFrameSite());
diff --git a/chromium/services/network/public/cpp/network_param_mojom_traits.cc b/chromium/services/network/public/cpp/network_param_mojom_traits.cc
index 3ac8d893279..efc8f609dd0 100644
--- a/chromium/services/network/public/cpp/network_param_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/network_param_mojom_traits.cc
@@ -4,8 +4,23 @@
#include "services/network/public/cpp/network_param_mojom_traits.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+
namespace mojo {
+bool StructTraits<network::mojom::AuthChallengeInfoDataView,
+ net::AuthChallengeInfo>::
+ Read(network::mojom::AuthChallengeInfoDataView data,
+ net::AuthChallengeInfo* out) {
+ out->is_proxy = data.is_proxy();
+ if (!data.ReadChallenger(&out->challenger) ||
+ !data.ReadScheme(&out->scheme) || !data.ReadRealm(&out->realm) ||
+ !data.ReadChallenge(&out->challenge) || !data.ReadPath(&out->path)) {
+ return false;
+ }
+ return true;
+}
+
bool StructTraits<network::mojom::HttpVersionDataView, net::HttpVersion>::Read(
network::mojom::HttpVersionDataView data,
net::HttpVersion* out) {
diff --git a/chromium/services/network/public/cpp/network_param_mojom_traits.h b/chromium/services/network/public/cpp/network_param_mojom_traits.h
index 81e3d8223a5..7e7fcf15d1d 100644
--- a/chromium/services/network/public/cpp/network_param_mojom_traits.h
+++ b/chromium/services/network/public/cpp/network_param_mojom_traits.h
@@ -5,14 +5,51 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_NETWORK_PARAM_MOJOM_TRAITS_H_
#define SERVICES_NETWORK_PUBLIC_CPP_NETWORK_PARAM_MOJOM_TRAITS_H_
+#include "base/component_export.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "net/base/auth.h"
#include "net/http/http_version.h"
-#include "services/network/public/mojom/network_param.mojom.h"
+#include "services/network/public/mojom/network_param.mojom-shared.h"
+#include "url/mojom/origin_mojom_traits.h"
namespace mojo {
template <>
-class StructTraits<network::mojom::HttpVersionDataView, net::HttpVersion> {
+class COMPONENT_EXPORT(NETWORK_CPP_BASE)
+ StructTraits<network::mojom::AuthChallengeInfoDataView,
+ net::AuthChallengeInfo> {
+ public:
+ static bool is_proxy(const net::AuthChallengeInfo& auth_challenge_info) {
+ return auth_challenge_info.is_proxy;
+ }
+ static const url::Origin& challenger(
+ const net::AuthChallengeInfo& auth_challenge_info) {
+ return auth_challenge_info.challenger;
+ }
+ static const std::string& scheme(
+ const net::AuthChallengeInfo& auth_challenge_info) {
+ return auth_challenge_info.scheme;
+ }
+ static const std::string& realm(
+ const net::AuthChallengeInfo& auth_challenge_info) {
+ return auth_challenge_info.realm;
+ }
+ static const std::string& challenge(
+ const net::AuthChallengeInfo& auth_challenge_info) {
+ return auth_challenge_info.challenge;
+ }
+ static const std::string& path(
+ const net::AuthChallengeInfo& auth_challenge_info) {
+ return auth_challenge_info.path;
+ }
+
+ static bool Read(network::mojom::AuthChallengeInfoDataView data,
+ net::AuthChallengeInfo* out);
+};
+
+template <>
+class COMPONENT_EXPORT(NETWORK_CPP_BASE)
+ StructTraits<network::mojom::HttpVersionDataView, net::HttpVersion> {
public:
static int16_t major_value(net::HttpVersion version) {
return version.major_value();
diff --git a/chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc b/chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc
index 149e6734a6e..56516cb21d1 100644
--- a/chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc
+++ b/chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc
@@ -10,7 +10,9 @@
namespace network {
-NotImplementedURLLoaderFactory::NotImplementedURLLoaderFactory() = default;
+NotImplementedURLLoaderFactory::NotImplementedURLLoaderFactory(
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver)
+ : SelfDeletingURLLoaderFactory(std::move(factory_receiver)) {}
NotImplementedURLLoaderFactory::~NotImplementedURLLoaderFactory() = default;
@@ -29,9 +31,18 @@ void NotImplementedURLLoaderFactory::CreateLoaderAndStart(
->OnComplete(status);
}
-void NotImplementedURLLoaderFactory::Clone(
- mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
- receivers_.Add(this, std::move(receiver));
+// static
+mojo::PendingRemote<network::mojom::URLLoaderFactory>
+NotImplementedURLLoaderFactory::Create() {
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote;
+
+ // The NotImplementedURLLoaderFactory will delete itself when there are no
+ // more receivers - see the NotImplementedURLLoaderFactory::OnDisconnect
+ // method.
+ new NotImplementedURLLoaderFactory(
+ pending_remote.InitWithNewPipeAndPassReceiver());
+
+ return pending_remote;
}
} // namespace network
diff --git a/chromium/services/network/public/cpp/not_implemented_url_loader_factory.h b/chromium/services/network/public/cpp/not_implemented_url_loader_factory.h
index baca98d17a3..a630aade0bf 100644
--- a/chromium/services/network/public/cpp/not_implemented_url_loader_factory.h
+++ b/chromium/services/network/public/cpp/not_implemented_url_loader_factory.h
@@ -9,6 +9,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "services/network/public/cpp/self_deleting_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace network {
@@ -16,11 +17,18 @@ namespace network {
// A URLLoaderFactory which just fails to create a loader with
// net::ERR_NOT_IMPLEMENTED.
class COMPONENT_EXPORT(NETWORK_CPP) NotImplementedURLLoaderFactory final
- : public network::mojom::URLLoaderFactory {
+ : public SelfDeletingURLLoaderFactory {
public:
- NotImplementedURLLoaderFactory();
+ // Returns mojo::PendingRemote to a newly constructed
+ // NotImplementedURLLoaderFactory. The factory is self-owned - it will delete
+ // itself once there are no more receivers (including the receiver associated
+ // with the returned mojo::PendingRemote and the receivers bound by the Clone
+ // method).
+ static mojo::PendingRemote<network::mojom::URLLoaderFactory> Create();
+
~NotImplementedURLLoaderFactory() override;
+ private:
// network::mojom::URLLoaderFactory implementation.
void CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
@@ -32,11 +40,11 @@ class COMPONENT_EXPORT(NETWORK_CPP) NotImplementedURLLoaderFactory final
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
override;
- void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
- override;
-
- private:
- mojo::ReceiverSet<network::mojom::URLLoaderFactory> receivers_;
+ // Constructs a NotImplementedURLLoaderFactory object that will self-delete
+ // once all receivers disconnect (including |factory_receiver| below as well
+ // as receivers that connect via the Clone method).
+ explicit NotImplementedURLLoaderFactory(
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver);
DISALLOW_COPY_AND_ASSIGN(NotImplementedURLLoaderFactory);
};
diff --git a/chromium/services/network/public/cpp/opaque_response_blocking.cc b/chromium/services/network/public/cpp/opaque_response_blocking.cc
new file mode 100644
index 00000000000..442304eb8d9
--- /dev/null
+++ b/chromium/services/network/public/cpp/opaque_response_blocking.cc
@@ -0,0 +1,220 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/opaque_response_blocking.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/string_piece.h"
+#include "net/url_request/url_request.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+
+namespace network {
+
+namespace {
+
+// This corresponds to "opaque-blocklisted-never-sniffed MIME type" in ORB spec.
+bool IsOpaqueBlocklistedNeverSniffedMimeType(base::StringPiece mime_type) {
+ return CrossOriginReadBlocking::GetCanonicalMimeType(mime_type) ==
+ CrossOriginReadBlocking::MimeType::kNeverSniffed;
+}
+
+// ORB spec says that "An opaque-safelisted MIME type" is a JavaScript MIME type
+// or a MIME type whose essence is "text/css" or "image/svg+xml".
+bool IsOpaqueSafelistedMimeType(base::StringPiece mime_type) {
+ // Based on the spec: Is it a MIME type whose essence is "text/css" or
+ // "image/svg+xml"?
+ if (base::LowerCaseEqualsASCII(mime_type, "image/svg+xml") ||
+ base::LowerCaseEqualsASCII(mime_type, "text/css")) {
+ return true;
+ }
+
+ // Based on the spec: Is it a JavaScript MIME type?
+ if (CrossOriginReadBlocking::IsJavascriptMimeType(mime_type))
+ return true;
+
+ // https://github.com/annevk/orb/issues/20 tracks explicitly covering DASH
+ // mime type in the ORB algorithm.
+ if (base::LowerCaseEqualsASCII(mime_type, "application/dash+xml"))
+ return true;
+
+ return false;
+}
+
+// Return true for multimedia MIME types that
+// 1) are not explicitly covered by ORB (e.g. that do not begin with "audio/",
+// "image/", "video/" and that are not covered by
+// IsOpaqueSafelistedMimeType).
+// 2) would be recognized by sniffing from steps 6 or 7 of ORB:
+// step 6. If the image type pattern matching algorithm ...
+// step 7. If the audio or video type pattern matching algorithm ...
+bool IsSniffableMultimediaType(base::StringPiece mime_type) {
+ if (base::LowerCaseEqualsASCII(mime_type, "application/ogg"))
+ return true;
+
+ return false;
+}
+
+// This corresponds to https://fetch.spec.whatwg.org/#ok-status
+bool IsOkayHttpStatus(const mojom::URLResponseHead& response) {
+ if (!response.headers)
+ return false;
+
+ int code = response.headers->response_code();
+ return (200 <= code) && (code <= 299);
+}
+
+bool IsHttpStatus(const mojom::URLResponseHead& response,
+ int expected_status_code) {
+ if (!response.headers)
+ return false;
+
+ int code = response.headers->response_code();
+ return code == expected_status_code;
+}
+
+bool IsOpaqueResponse(const base::Optional<url::Origin>& request_initiator,
+ mojom::RequestMode request_mode,
+ const mojom::URLResponseHead& response) {
+ // ORB only applies to "no-cors" requests.
+ if (request_mode != mojom::RequestMode::kNoCors)
+ return false;
+
+ // Browser-initiated requests are never opaque.
+ if (!request_initiator.has_value())
+ return false;
+
+ // Requests from foo.example.com will consult foo.example.com's service worker
+ // first (if one has been registered). The service worker can handle requests
+ // initiated by foo.example.com even if they are cross-origin (e.g. requests
+ // for bar.example.com). This is okay, because there is no security boundary
+ // between foo.example.com and the service worker of foo.example.com + because
+ // the response data is "conjured" within the service worker of
+ // foo.example.com (rather than being fetched from bar.example.com).
+ // Therefore such responses should not be blocked by CORB, unless the
+ // initiator opted out of CORS / opted into receiving an opaque response. See
+ // also https://crbug.com/803672.
+ if (response.was_fetched_via_service_worker) {
+ switch (response.response_type) {
+ case network::mojom::FetchResponseType::kBasic:
+ case network::mojom::FetchResponseType::kCors:
+ case network::mojom::FetchResponseType::kDefault:
+ case network::mojom::FetchResponseType::kError:
+ // Non-opaque responses shouldn't be blocked.
+ return false;
+ case network::mojom::FetchResponseType::kOpaque:
+ case network::mojom::FetchResponseType::kOpaqueRedirect:
+ // Opaque responses are eligible for blocking. Continue on...
+ break;
+ }
+ }
+
+ return true;
+}
+
+ResponseHeadersHeuristicForUma CalculateResponseHeadersHeuristicForUma(
+ const GURL& request_url,
+ const base::Optional<url::Origin>& request_initiator,
+ mojom::RequestMode request_mode,
+ const mojom::URLResponseHead& response) {
+ // Exclude responses that ORB doesn't apply to.
+ if (!IsOpaqueResponse(request_initiator, request_mode, response))
+ return ResponseHeadersHeuristicForUma::kNonOpaqueResponse;
+ DCHECK(request_initiator.has_value());
+
+ // Same-origin requests are allowed (the spec doesn't explicitly deal with
+ // this).
+ url::Origin target_origin = url::Origin::Create(request_url);
+ if (request_initiator->IsSameOriginWith(target_origin))
+ return ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders;
+
+ // Presence of an "X-Content-Type-Options: nosniff" header means that ORB will
+ // reach a final decision in step 8, before reaching Javascript parsing in
+ // step 12:
+ // step 8. If nosniff is true, then return false.
+ // ...
+ // step 12. If response's body parses as JavaScript ...
+ if (CrossOriginReadBlocking::ResponseAnalyzer::HasNoSniff(response))
+ return ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders;
+
+ // If a mime type is missing then ORB will reach a final decision in step 10,
+ // before reaching Javascript parsing in step 12:
+ // step 10. If mimeType is failure, then return true.
+ // ...
+ // step 12. If response's body parses as JavaScript ...
+ std::string mime_type;
+ if (!response.headers || !response.headers->GetMimeType(&mime_type))
+ return ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders;
+
+ // Specific MIME types might make ORB reach a final decision before reaching
+ // Javascript parsing step:
+ // step 3.i. If mimeType is an opaque-safelisted MIME type, then return
+ // true.
+ // step 3.ii. If mimeType is an opaque-blocklisted-never-sniffed MIME
+ // type, then return false.
+ // ...
+ // step 11. If mimeType's essence starts with "audio/", "image/", or
+ // "video/", then return false.
+ // ...
+ // step 12. If response's body parses as JavaScript ...
+ if (IsOpaqueBlocklistedNeverSniffedMimeType(mime_type) ||
+ IsOpaqueSafelistedMimeType(mime_type) ||
+ IsSniffableMultimediaType(mime_type)) {
+ return ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders;
+ }
+ constexpr auto kCaseInsensitive = base::CompareCase::INSENSITIVE_ASCII;
+ if (base::StartsWith(mime_type, "audio/", kCaseInsensitive) ||
+ base::StartsWith(mime_type, "image/", kCaseInsensitive) ||
+ base::StartsWith(mime_type, "video/", kCaseInsensitive)) {
+ return ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders;
+ }
+
+ // If the http response indicates an error, or a 206 response, then ORB will
+ // reach a final decision before reaching Javascript parsing in step 12:
+ // step 9. If response's status is not an ok status, then return false.
+ // ...
+ // step 12. If response's body parses as JavaScript ...
+ if (!IsOkayHttpStatus(response) || IsHttpStatus(response, 206))
+ return ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders;
+
+ // Otherwise we need to parse the response body as Javascript.
+ return ResponseHeadersHeuristicForUma::kRequiresJavascriptParsing;
+}
+
+} // namespace
+
+void LogUmaForOpaqueResponseBlocking(
+ const GURL& request_url,
+ const base::Optional<url::Origin>& request_initiator,
+ mojom::RequestMode request_mode,
+ mojom::RequestDestination request_destination,
+ const mojom::URLResponseHead& response) {
+ ResponseHeadersHeuristicForUma response_headers_decision =
+ CalculateResponseHeadersHeuristicForUma(request_url, request_initiator,
+ request_mode, response);
+ base::UmaHistogramEnumeration(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.Decision",
+ response_headers_decision);
+
+ switch (response_headers_decision) {
+ case ResponseHeadersHeuristicForUma::kNonOpaqueResponse:
+ break;
+
+ case ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders:
+ base::UmaHistogramEnumeration(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.ProcessedBasedOnHeaders",
+ request_destination);
+ break;
+
+ case ResponseHeadersHeuristicForUma::kRequiresJavascriptParsing:
+ base::UmaHistogramEnumeration(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic."
+ "RequiresJavascriptParsing",
+ request_destination);
+ break;
+ }
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/opaque_response_blocking.h b/chromium/services/network/public/cpp/opaque_response_blocking.h
new file mode 100644
index 00000000000..5b622729616
--- /dev/null
+++ b/chromium/services/network/public/cpp/opaque_response_blocking.h
@@ -0,0 +1,58 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_OPAQUE_RESPONSE_BLOCKING_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_OPAQUE_RESPONSE_BLOCKING_H_
+
+#include "base/component_export.h"
+#include "base/optional.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace network {
+
+// Result of applying heuristics based on partial ORB algorithm (suitable only
+// for UMA).
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class ResponseHeadersHeuristicForUma {
+ // ORB only applies to opaque respones. The enum value below includes:
+ // - mode != no-cors (e.g. mode=navigate or mode=cors)
+ // - browser-initiated requests
+ kNonOpaqueResponse = 0,
+
+ // ORB algorithm can *surely* make a decision based on response headers. The
+ // enum value below covers all subresource requests:
+ // - scripts, images, video, etc.
+ // - both same-origin and cross-origin requests
+ kProcessedBasedOnHeaders = 1,
+
+ // ORB algorithm *might* require parsing the response body as Javascript.
+ //
+ // This might be a false positive if the response:
+ // 1) sniffs as an audio/image/video format
+ // 2) represents a valid range response for a media element
+ kRequiresJavascriptParsing = 2,
+
+ // Required enum value to support UMA macros.
+ kMaxValue = kRequiresJavascriptParsing,
+};
+
+// Logs UMA tracking expected behavior characteristics of the Opaque Response
+// Blocking algorithm (a potential successor of CORB aka Cross-Origin Read
+// Blocking). See also https://github.com/annevk/orb
+COMPONENT_EXPORT(NETWORK_CPP)
+void LogUmaForOpaqueResponseBlocking(
+ const GURL& request_url,
+ const base::Optional<url::Origin>& request_initiator,
+ mojom::RequestMode request_mode,
+ mojom::RequestDestination request_destination,
+ const mojom::URLResponseHead& response);
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_OPAQUE_RESPONSE_BLOCKING_H_
diff --git a/chromium/services/network/public/cpp/opaque_response_blocking_unittest.cc b/chromium/services/network/public/cpp/opaque_response_blocking_unittest.cc
new file mode 100644
index 00000000000..80d42e0bb94
--- /dev/null
+++ b/chromium/services/network/public/cpp/opaque_response_blocking_unittest.cc
@@ -0,0 +1,261 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/opaque_response_blocking.h"
+#include "base/strings/string_util.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/task_environment.h"
+#include "net/base/mime_sniffer.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace network {
+namespace {
+
+// ResourceType::kImage from resource_load_info.mojom
+constexpr mojom::RequestDestination kDefaultRequestDestination =
+ mojom::RequestDestination::kImage;
+
+const char kDefaultRequestUrl[] = "https://target.example.com/foo";
+
+struct TestInput {
+ GURL request_url;
+ base::Optional<url::Origin> request_initiator;
+ mojom::RequestMode request_mode;
+ mojom::RequestDestination request_destination;
+ mojom::URLResponseHeadPtr response;
+};
+
+class TestInputBuilder {
+ public:
+ TestInputBuilder() = default;
+
+ // No copy constructor or assignment operator.
+ TestInputBuilder(const TestInputBuilder&) = delete;
+ TestInputBuilder& operator=(const TestInputBuilder&) = delete;
+
+ TestInput Build() const {
+ std::string raw_headers = base::ReplaceStringPlaceholders(
+ "$1\nContent-Type: $2\n", {http_status_line_, mime_type_}, nullptr);
+ if (no_sniff_)
+ raw_headers += "X-Content-Type-Options: nosniff\n";
+
+ mojom::URLResponseHeadPtr response = mojom::URLResponseHead::New();
+ response->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(raw_headers));
+ response->was_fetched_via_service_worker = false;
+ response->response_type = mojom::FetchResponseType::kDefault;
+
+ return TestInput{
+ .request_url = request_url_,
+ .request_initiator = request_initiator_,
+ .request_mode = request_mode_,
+ .request_destination = kDefaultRequestDestination,
+ .response = std::move(response),
+ };
+ }
+
+ TestInputBuilder& WithHttpStatus(std::string status_line) {
+ http_status_line_ = status_line;
+ return *this;
+ }
+
+ TestInputBuilder& WithMimeType(std::string mime_type) {
+ mime_type_ = mime_type;
+ return *this;
+ }
+
+ TestInputBuilder& WithInitiator(
+ const base::Optional<url::Origin>& initiator) {
+ request_initiator_ = initiator;
+ return *this;
+ }
+
+ TestInputBuilder& WithMode(const mojom::RequestMode& mode) {
+ request_mode_ = mode;
+ return *this;
+ }
+
+ TestInputBuilder& WithNoSniff() {
+ no_sniff_ = true;
+ return *this;
+ }
+
+ private:
+ std::string http_status_line_ = "HTTP/1.1 200 OK";
+ std::string mime_type_ = "application/octet-stream";
+ GURL request_url_ = GURL(kDefaultRequestUrl);
+ base::Optional<url::Origin> request_initiator_ =
+ url::Origin::Create(GURL("https://initiator.example.com"));
+ mojom::RequestMode request_mode_ = mojom::RequestMode::kNoCors;
+ bool no_sniff_ = false;
+};
+
+void LogUmaForOpaqueResponseBlocking(const TestInput& test_input) {
+ network::LogUmaForOpaqueResponseBlocking(
+ test_input.request_url, test_input.request_initiator,
+ test_input.request_mode, test_input.request_destination,
+ *test_input.response);
+}
+
+void LogUmaForOpaqueResponseBlocking(
+ const TestInputBuilder& test_input_builder) {
+ LogUmaForOpaqueResponseBlocking(test_input_builder.Build());
+}
+
+void TestUma(const TestInput& test_input,
+ const ResponseHeadersHeuristicForUma& expected_uma_decision) {
+ base::HistogramTester histograms;
+ LogUmaForOpaqueResponseBlocking(test_input);
+
+ // Verify that the ...Heuristic.Decision UMA has only a single/unique bucket
+ // (for `expected_uma_decision`) and that only 1 sample has been logged for
+ // this bucket.
+ histograms.ExpectUniqueSample(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.Decision",
+ expected_uma_decision, 1 /* expected_count */);
+}
+
+void TestUma(const TestInputBuilder& test_input_builder,
+ const ResponseHeadersHeuristicForUma& expected_uma_decision) {
+ TestUma(test_input_builder.Build(), expected_uma_decision);
+}
+
+TEST(OpaqueResponseBlocking, DefaultTestInput) {
+ // Verify properties of the default test input: renderer-initiated,
+ // cross-origin, no-cors request with a successful application/octet-stream
+ // response.
+ TestInput default_test_input = TestInputBuilder().Build();
+ EXPECT_TRUE(default_test_input.request_initiator.has_value());
+ EXPECT_FALSE(default_test_input.request_initiator->IsSameOriginWith(
+ url::Origin::Create(default_test_input.request_url)));
+ EXPECT_EQ(mojom::RequestMode::kNoCors, default_test_input.request_mode);
+ EXPECT_TRUE(default_test_input.response);
+ EXPECT_TRUE(default_test_input.response->headers);
+ EXPECT_EQ(200, default_test_input.response->headers->response_code());
+ std::string mime_type;
+ EXPECT_TRUE(default_test_input.response->headers->GetMimeType(&mime_type));
+ EXPECT_EQ("application/octet-stream", mime_type);
+
+ // Verify that the right UMA is logged for the default test input.
+ TestUma(default_test_input,
+ ResponseHeadersHeuristicForUma::kRequiresJavascriptParsing);
+}
+
+TEST(OpaqueResponseBlocking, ResourceTypeUma) {
+ // RequiresJavascriptParsing case.
+ {
+ base::HistogramTester histograms;
+ TestUma(TestInputBuilder(),
+ ResponseHeadersHeuristicForUma::kRequiresJavascriptParsing);
+ histograms.ExpectTotalCount(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.ProcessedBasedOnHeaders",
+ 0);
+ histograms.ExpectUniqueSample(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.RequiresJavascriptParsing",
+ kDefaultRequestDestination,
+ 1 /* `expected_count` of `kDefaultRequestDestination` */);
+ }
+
+ // ProcessedBasedOnHeaders case.
+ {
+ base::HistogramTester histograms;
+ TestUma(TestInputBuilder().WithNoSniff(),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ histograms.ExpectUniqueSample(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.ProcessedBasedOnHeaders",
+ kDefaultRequestDestination,
+ 1 /* `expected_count` of `kDefaultRequestDestination` */);
+ histograms.ExpectTotalCount(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.RequiresJavascriptParsing",
+ 0);
+ }
+
+ // Non-opaque case..
+ {
+ base::HistogramTester histograms;
+ LogUmaForOpaqueResponseBlocking(
+ TestInputBuilder().WithInitiator(base::nullopt));
+ histograms.ExpectTotalCount(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.ProcessedBasedOnHeaders",
+ 0);
+ histograms.ExpectTotalCount(
+ "SiteIsolation.ORB.ResponseHeadersHeuristic.RequiresJavascriptParsing",
+ 0);
+ }
+
+ LogUmaForOpaqueResponseBlocking(TestInputBuilder().WithNoSniff());
+}
+
+TEST(OpaqueResponseBlocking, NonOpaqueRequests) {
+ // Browser-initiated request.
+ TestUma(TestInputBuilder().WithInitiator(base::nullopt),
+ ResponseHeadersHeuristicForUma::kNonOpaqueResponse);
+
+ // Mode != no-cors.
+ TestUma(TestInputBuilder().WithMode(mojom::RequestMode::kCors),
+ ResponseHeadersHeuristicForUma::kNonOpaqueResponse);
+ TestUma(TestInputBuilder().WithMode(mojom::RequestMode::kNavigate),
+ ResponseHeadersHeuristicForUma::kNonOpaqueResponse);
+}
+
+TEST(OpaqueResponseBlocking, SameOrigin) {
+ TestUma(TestInputBuilder().WithInitiator(
+ url::Origin::Create(GURL(kDefaultRequestUrl))),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+}
+
+TEST(OpaqueResponseBlocking, NoSniff) {
+ TestUma(TestInputBuilder().WithNoSniff(),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+}
+
+TEST(OpaqueResponseBlocking, MimeTypes) {
+ // Unrecognized type:
+ TestUma(TestInputBuilder().WithMimeType("application/octet-stream"),
+ ResponseHeadersHeuristicForUma::kRequiresJavascriptParsing);
+
+ // opaque-safelisted MIME types:
+ TestUma(TestInputBuilder().WithMimeType("application/dash+xml"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ TestUma(TestInputBuilder().WithMimeType("application/javascript"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ TestUma(TestInputBuilder().WithMimeType("image/svg+xml"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ TestUma(TestInputBuilder().WithMimeType("text/css"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+
+ // Example of a opaque-blocklisted-never-sniffed MIME type:
+ TestUma(TestInputBuilder().WithMimeType("application/pdf"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+
+ // Future multimedia types:
+ TestUma(TestInputBuilder().WithMimeType("audio/some-future-type"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ TestUma(TestInputBuilder().WithMimeType("image/some-future-type"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ TestUma(TestInputBuilder().WithMimeType("video/some-future-type"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+}
+
+TEST(OpaqueResponseBlocking, HttpStatusCodes) {
+ TestUma(TestInputBuilder().WithHttpStatus("HTTP/1.1 200 OK"),
+ ResponseHeadersHeuristicForUma::kRequiresJavascriptParsing);
+
+ TestUma(TestInputBuilder().WithHttpStatus("HTTP/1.1 206 Range"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ TestUma(TestInputBuilder().WithHttpStatus("HTTP/1.1 300 Redirect"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ TestUma(TestInputBuilder().WithHttpStatus("HTTP/1.1 400 NotFound"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+ TestUma(TestInputBuilder().WithHttpStatus("HTTP/1.1 500 ServerError"),
+ ResponseHeadersHeuristicForUma::kProcessedBasedOnHeaders);
+}
+
+} // namespace
+} // namespace network
diff --git a/chromium/services/network/public/cpp/origin_isolation_parser.cc b/chromium/services/network/public/cpp/origin_agent_cluster_parser.cc
index b324c3d01e8..af23159a5c2 100644
--- a/chromium/services/network/public/cpp/origin_isolation_parser.cc
+++ b/chromium/services/network/public/cpp/origin_agent_cluster_parser.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "services/network/public/cpp/origin_isolation_parser.h"
+#include "services/network/public/cpp/origin_agent_cluster_parser.h"
#include "net/http/structured_headers.h"
namespace network {
-bool ParseOriginIsolation(const std::string& header_value) {
+bool ParseOriginAgentCluster(const std::string& header_value) {
const auto item = net::structured_headers::ParseItem(header_value);
return item && item->item.is_boolean() && item->item.GetBoolean();
}
diff --git a/chromium/services/network/public/cpp/origin_isolation_parser.h b/chromium/services/network/public/cpp/origin_agent_cluster_parser.h
index dd4f7d7fc81..04610c5fff0 100644
--- a/chromium/services/network/public/cpp/origin_isolation_parser.h
+++ b/chromium/services/network/public/cpp/origin_agent_cluster_parser.h
@@ -2,22 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_ISOLATION_PARSER_H_
-#define SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_ISOLATION_PARSER_H_
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_AGENT_CLUSTER_PARSER_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_AGENT_CLUSTER_PARSER_H_
#include <string>
#include "base/component_export.h"
namespace network {
-// Parsing is done following the Origin-Isolation spec draft:
-// https://github.com/whatwg/html/pull/5545
+// This part of the spec specifically handles header parsing:
+// https://html.spec.whatwg.org/C/#initialise-the-document-object
//
// See the comment in network::PopulateParsedHeaders for restrictions on this
// function.
COMPONENT_EXPORT(NETWORK_CPP)
-bool ParseOriginIsolation(const std::string&);
+bool ParseOriginAgentCluster(const std::string&);
} // namespace network
-#endif // SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_ISOLATION_PARSER_H_
+#endif // SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_AGENT_CLUSTER_PARSER_H_
diff --git a/chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc b/chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc
new file mode 100644
index 00000000000..11b2c3194c4
--- /dev/null
+++ b/chromium/services/network/public/cpp/origin_agent_cluster_parser_unittest.cc
@@ -0,0 +1,31 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/origin_agent_cluster_parser.h"
+
+#include <string>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace network {
+
+TEST(OriginAgentClusterHeaderTest, Parse) {
+ EXPECT_EQ(ParseOriginAgentCluster(""), false);
+
+ EXPECT_EQ(ParseOriginAgentCluster("?1"), true);
+ EXPECT_EQ(ParseOriginAgentCluster("?0"), false);
+
+ EXPECT_EQ(ParseOriginAgentCluster("?1;param"), true);
+ EXPECT_EQ(ParseOriginAgentCluster("?1;param=value"), true);
+ EXPECT_EQ(ParseOriginAgentCluster("?1;param=value;param2=value2"), true);
+
+ EXPECT_EQ(ParseOriginAgentCluster("true"), false);
+ EXPECT_EQ(ParseOriginAgentCluster("\"?1\""), false);
+ EXPECT_EQ(ParseOriginAgentCluster("1"), false);
+ EXPECT_EQ(ParseOriginAgentCluster("?2"), false);
+ EXPECT_EQ(ParseOriginAgentCluster("(?1)"), false);
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/origin_isolation_parser_unittest.cc b/chromium/services/network/public/cpp/origin_isolation_parser_unittest.cc
deleted file mode 100644
index 0b53d3a0901..00000000000
--- a/chromium/services/network/public/cpp/origin_isolation_parser_unittest.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/public/cpp/origin_isolation_parser.h"
-
-#include <string>
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace network {
-
-TEST(OriginIsolationHeaderTest, Parse) {
- EXPECT_EQ(ParseOriginIsolation(""), false);
-
- EXPECT_EQ(ParseOriginIsolation("?1"), true);
- EXPECT_EQ(ParseOriginIsolation("?0"), false);
-
- EXPECT_EQ(ParseOriginIsolation("?1;param"), true);
- EXPECT_EQ(ParseOriginIsolation("?1;param=value"), true);
- EXPECT_EQ(ParseOriginIsolation("?1;param=value;param2=value2"), true);
-
- EXPECT_EQ(ParseOriginIsolation("true"), false);
- EXPECT_EQ(ParseOriginIsolation("\"?1\""), false);
- EXPECT_EQ(ParseOriginIsolation("1"), false);
- EXPECT_EQ(ParseOriginIsolation("?2"), false);
- EXPECT_EQ(ParseOriginIsolation("(?1)"), false);
-}
-
-} // namespace network
diff --git a/chromium/services/network/public/cpp/origin_policy.cc b/chromium/services/network/public/cpp/origin_policy.cc
index 4ecc285c174..e1d3d831764 100644
--- a/chromium/services/network/public/cpp/origin_policy.cc
+++ b/chromium/services/network/public/cpp/origin_policy.cc
@@ -26,14 +26,12 @@ OriginPolicyContents::OriginPolicyContents(
const std::vector<std::string>& ids,
const base::Optional<std::string>& feature_policy,
const std::vector<std::string>& content_security_policies,
- const std::vector<std::string>& content_security_policies_report_only,
- const base::Optional<IsolationOptInHints>& isolation_optin_hints)
+ const std::vector<std::string>& content_security_policies_report_only)
: ids(ids),
feature_policy(feature_policy),
content_security_policies(content_security_policies),
content_security_policies_report_only(
- content_security_policies_report_only),
- isolation_optin_hints(isolation_optin_hints) {}
+ content_security_policies_report_only) {}
OriginPolicyContents& OriginPolicyContents::operator=(
const OriginPolicyContents& other) = default;
@@ -42,8 +40,7 @@ bool OriginPolicyContents::operator==(const OriginPolicyContents& other) const {
return ids == other.ids && feature_policy == other.feature_policy &&
content_security_policies == other.content_security_policies &&
content_security_policies_report_only ==
- other.content_security_policies_report_only &&
- isolation_optin_hints == other.isolation_optin_hints;
+ other.content_security_policies_report_only;
}
OriginPolicyContentsPtr OriginPolicyContents::ClonePtr() {
diff --git a/chromium/services/network/public/cpp/origin_policy.h b/chromium/services/network/public/cpp/origin_policy.h
index bb4cec880b2..b1c2e08174a 100644
--- a/chromium/services/network/public/cpp/origin_policy.h
+++ b/chromium/services/network/public/cpp/origin_policy.h
@@ -10,7 +10,6 @@
#include <vector>
#include "base/optional.h"
-#include "services/network/public/cpp/isolation_opt_in_hints.h"
#include "url/gurl.h"
namespace network {
@@ -50,8 +49,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) OriginPolicyContents {
const std::vector<std::string>& ids,
const base::Optional<std::string>& feature_policy,
const std::vector<std::string>& content_security_policies,
- const std::vector<std::string>& content_security_policies_report_only,
- const base::Optional<IsolationOptInHints>& isolation_optin_hints);
+ const std::vector<std::string>& content_security_policies_report_only);
OriginPolicyContents(const OriginPolicyContents& other);
OriginPolicyContents& operator=(const OriginPolicyContents& other);
@@ -92,11 +90,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) OriginPolicyContents {
// a "report" disposition.
// https://w3c.github.io/webappsec-csp/#policy-disposition
std::vector<std::string> content_security_policies_report_only;
-
- // This field, if present, indicates that the origin is opting in to
- // origin-based isolation. The int contains zero or more flag bits indicating
- // what the origin is hoping to achieve through isolation.
- base::Optional<IsolationOptInHints> isolation_optin_hints;
};
// Native implementation of mojom::OriginPolicy. This is done so we can pass
diff --git a/chromium/services/network/public/cpp/parsed_headers.cc b/chromium/services/network/public/cpp/parsed_headers.cc
index 2fb31bb4a91..548a128ec72 100644
--- a/chromium/services/network/public/cpp/parsed_headers.cc
+++ b/chromium/services/network/public/cpp/parsed_headers.cc
@@ -10,7 +10,8 @@
#include "services/network/public/cpp/cross_origin_embedder_policy_parser.h"
#include "services/network/public/cpp/cross_origin_opener_policy_parser.h"
#include "services/network/public/cpp/features.h"
-#include "services/network/public/cpp/origin_isolation_parser.h"
+#include "services/network/public/cpp/origin_agent_cluster_parser.h"
+#include "services/network/public/cpp/x_frame_options_parser.h"
namespace network {
@@ -31,12 +32,12 @@ mojom::ParsedHeadersPtr PopulateParsedHeaders(
parsed_headers->cross_origin_opener_policy = ParseCrossOriginOpenerPolicy(
*headers, parsed_headers->cross_origin_embedder_policy);
- // TODO(https://crbug.com/1157917): we implement the change at
- // https://github.com/whatwg/html/pull/6214 but all the class and function
- // names are not yet updated.
- std::string origin_isolation;
- if (headers->GetNormalizedHeader("Origin-Agent-Cluster", &origin_isolation))
- parsed_headers->origin_isolation = ParseOriginIsolation(origin_isolation);
+ std::string origin_agent_cluster;
+ if (headers->GetNormalizedHeader("Origin-Agent-Cluster",
+ &origin_agent_cluster)) {
+ parsed_headers->origin_agent_cluster =
+ ParseOriginAgentCluster(origin_agent_cluster);
+ }
std::string accept_ch;
if (headers->GetNormalizedHeader("Accept-CH", &accept_ch))
@@ -52,6 +53,8 @@ mojom::ParsedHeadersPtr PopulateParsedHeaders(
if (headers->GetNormalizedHeader("Critical-CH", &critical_ch))
parsed_headers->critical_ch = ParseClientHintsHeader(critical_ch);
+ parsed_headers->xfo = ParseXFrameOptions(*headers);
+
return parsed_headers;
}
diff --git a/chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc
index b5ec2918e6a..ebb9d810b18 100644
--- a/chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc
@@ -22,7 +22,7 @@ bool TestProxyConfigRoundTrip(net::ProxyConfigWithAnnotation& original_config) {
net::ProxyConfigWithAnnotation copied_config;
EXPECT_TRUE(
mojo::test::SerializeAndDeserialize<mojom::ProxyConfigWithAnnotation>(
- &original_config, &copied_config));
+ original_config, copied_config));
return original_config.value().Equals(copied_config.value()) &&
original_config.traffic_annotation() ==
diff --git a/chromium/services/network/public/cpp/request_destination.cc b/chromium/services/network/public/cpp/request_destination.cc
index 38884cc4697..c61db5ed468 100644
--- a/chromium/services/network/public/cpp/request_destination.cc
+++ b/chromium/services/network/public/cpp/request_destination.cc
@@ -6,6 +6,8 @@
namespace network {
+// These strings are used in histograms, so do not change the values without
+// updating/deprecating histograms which use RequestDestination.
const char* RequestDestinationToString(
network::mojom::RequestDestination dest) {
switch (dest) {
@@ -47,6 +49,8 @@ const char* RequestDestinationToString(
return "track";
case network::mojom::RequestDestination::kVideo:
return "video";
+ case network::mojom::RequestDestination::kWebBundle:
+ return "webbundle";
case network::mojom::RequestDestination::kWorker:
return "worker";
case network::mojom::RequestDestination::kXslt:
@@ -56,4 +60,4 @@ const char* RequestDestinationToString(
return "empty";
}
-} // namespace network \ No newline at end of file
+} // namespace network
diff --git a/chromium/services/network/public/cpp/resource_request.cc b/chromium/services/network/public/cpp/resource_request.cc
index ee0150fbd6d..61a6f05d5d7 100644
--- a/chromium/services/network/public/cpp/resource_request.cc
+++ b/chromium/services/network/public/cpp/resource_request.cc
@@ -7,6 +7,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/load_flags.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
+#include "services/network/public/mojom/web_bundle_handle.mojom.h"
namespace network {
@@ -23,6 +24,19 @@ mojo::PendingRemote<mojom::CookieAccessObserver> Clone(
return new_remote;
}
+mojo::PendingRemote<mojom::AuthenticationAndCertificateObserver> Clone(
+ mojo::PendingRemote<mojom::AuthenticationAndCertificateObserver>*
+ observer) {
+ if (!*observer)
+ return mojo::NullRemote();
+ mojo::Remote<mojom::AuthenticationAndCertificateObserver> remote(
+ std::move(*observer));
+ mojo::PendingRemote<mojom::AuthenticationAndCertificateObserver> new_remote;
+ remote->Clone(new_remote.InitWithNewPipeAndPassReceiver());
+ *observer = remote.Unbind();
+ return new_remote;
+}
+
// Returns true iff either holds true:
//
// - both |lhs| and |rhs| are nullopt, or
@@ -34,6 +48,13 @@ bool OptionalTrustedParamsEqualsForTesting(
return (!lhs && !rhs) || (lhs && rhs && lhs->EqualsForTesting(*rhs));
}
+bool OptionalWebBundleTokenParamsEqualsForTesting( // IN-TEST
+ const base::Optional<ResourceRequest::WebBundleTokenParams>& lhs,
+ const base::Optional<ResourceRequest::WebBundleTokenParams>& rhs) {
+ return (!lhs && !rhs) ||
+ (lhs && rhs && lhs->EqualsForTesting(*rhs)); // IN-TEST
+}
+
} // namespace
ResourceRequest::TrustedParams::TrustedParams() = default;
@@ -51,6 +72,10 @@ ResourceRequest::TrustedParams& ResourceRequest::TrustedParams::operator=(
cookie_observer =
Clone(&const_cast<mojo::PendingRemote<mojom::CookieAccessObserver>&>(
other.cookie_observer));
+ auth_cert_observer =
+ Clone(&const_cast<
+ mojo::PendingRemote<mojom::AuthenticationAndCertificateObserver>&>(
+ other.auth_cert_observer));
client_security_state = other.client_security_state.Clone();
return *this;
}
@@ -63,6 +88,59 @@ bool ResourceRequest::TrustedParams::EqualsForTesting(
client_security_state == trusted_params.client_security_state;
}
+ResourceRequest::WebBundleTokenParams::WebBundleTokenParams() = default;
+ResourceRequest::WebBundleTokenParams::~WebBundleTokenParams() = default;
+
+ResourceRequest::WebBundleTokenParams::WebBundleTokenParams(
+ const WebBundleTokenParams& other) {
+ *this = other;
+}
+
+ResourceRequest::WebBundleTokenParams&
+ResourceRequest::WebBundleTokenParams::operator=(
+ const WebBundleTokenParams& other) {
+ bundle_url = other.bundle_url;
+ token = other.token;
+ handle = other.CloneHandle();
+ render_process_id = other.render_process_id;
+ return *this;
+}
+
+ResourceRequest::WebBundleTokenParams::WebBundleTokenParams(
+ const GURL& bundle_url,
+ const base::UnguessableToken& token,
+ mojo::PendingRemote<mojom::WebBundleHandle> handle)
+ : bundle_url(bundle_url), token(token), handle(std::move(handle)) {}
+
+ResourceRequest::WebBundleTokenParams::WebBundleTokenParams(
+ const GURL& bundle_url,
+ const base::UnguessableToken& token,
+ int32_t render_process_id)
+ : bundle_url(bundle_url),
+ token(token),
+ render_process_id(render_process_id) {}
+
+bool ResourceRequest::WebBundleTokenParams::EqualsForTesting(
+ const WebBundleTokenParams& other) const {
+ return bundle_url == other.bundle_url && token == other.token &&
+ ((handle && other.handle) || (!handle && !other.handle)) &&
+ render_process_id == other.render_process_id;
+}
+
+mojo::PendingRemote<mojom::WebBundleHandle>
+ResourceRequest::WebBundleTokenParams::CloneHandle() const {
+ if (!handle)
+ return mojo::NullRemote();
+ mojo::Remote<network::mojom::WebBundleHandle> remote(std::move(
+ const_cast<mojo::PendingRemote<network::mojom::WebBundleHandle>&>(
+ handle)));
+ mojo::PendingRemote<network::mojom::WebBundleHandle> new_remote;
+ remote->Clone(new_remote.InitWithNewPipeAndPassReceiver());
+ const_cast<mojo::PendingRemote<network::mojom::WebBundleHandle>&>(handle) =
+ remote.Unbind();
+ return new_remote;
+}
+
ResourceRequest::ResourceRequest() {}
ResourceRequest::ResourceRequest(const ResourceRequest& request) = default;
ResourceRequest::~ResourceRequest() {}
@@ -70,8 +148,6 @@ ResourceRequest::~ResourceRequest() {}
bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const {
return method == request.method && url == request.url &&
site_for_cookies.IsEquivalent(request.site_for_cookies) &&
- force_ignore_site_for_cookies ==
- request.force_ignore_site_for_cookies &&
update_first_party_url_on_redirect ==
request.update_first_party_url_on_redirect &&
request_initiator == request.request_initiator &&
@@ -91,8 +167,7 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const {
originated_from_service_worker ==
request.originated_from_service_worker &&
skip_service_worker == request.skip_service_worker &&
- corb_detachable == request.corb_detachable &&
- corb_excluded == request.corb_excluded && mode == request.mode &&
+ corb_detachable == request.corb_detachable && mode == request.mode &&
credentials_mode == request.credentials_mode &&
redirect_mode == request.redirect_mode &&
fetch_integrity == request.fetch_integrity &&
@@ -120,11 +195,14 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const {
is_signed_exchange_prefetch_cache_enabled ==
request.is_signed_exchange_prefetch_cache_enabled &&
is_fetch_like_api == request.is_fetch_like_api &&
+ is_favicon == request.is_favicon &&
obey_origin_policy == request.obey_origin_policy &&
recursive_prefetch_token == request.recursive_prefetch_token &&
OptionalTrustedParamsEqualsForTesting(trusted_params,
request.trusted_params) &&
- trust_token_params == request.trust_token_params;
+ trust_token_params == request.trust_token_params &&
+ OptionalWebBundleTokenParamsEqualsForTesting( // IN-TEST
+ web_bundle_token_params, request.web_bundle_token_params);
}
bool ResourceRequest::SendsCookies() const {
diff --git a/chromium/services/network/public/cpp/resource_request.h b/chromium/services/network/public/cpp/resource_request.h
index fb4d30c234d..6443dd62c00 100644
--- a/chromium/services/network/public/cpp/resource_request.h
+++ b/chromium/services/network/public/cpp/resource_request.h
@@ -20,12 +20,14 @@
#include "net/url_request/referrer_policy.h"
#include "services/network/public/cpp/optional_trust_token_params.h"
#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/mojom/auth_and_certificate_observer.mojom.h"
#include "services/network/public/mojom/client_security_state.mojom.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
#include "services/network/public/mojom/cors.mojom-shared.h"
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
+#include "services/network/public/mojom/web_bundle_handle.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -54,9 +56,43 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
bool disable_secure_dns = false;
bool has_user_activation = false;
mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer;
+ mojo::PendingRemote<mojom::AuthenticationAndCertificateObserver>
+ auth_cert_observer;
mojom::ClientSecurityStatePtr client_security_state;
};
+ // Typemapped to network.mojom.WebBundleTokenParams, see comments there
+ // for details of each field.
+ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) WebBundleTokenParams {
+ WebBundleTokenParams();
+ ~WebBundleTokenParams();
+ // Define a non-default copy-constructor because:
+ // 1. network::ResourceRequest has a requirement that all of
+ // the members be trivially copyable.
+ // 2. mojo::PendingRemote is non-copyable.
+ WebBundleTokenParams(const WebBundleTokenParams& params);
+ WebBundleTokenParams& operator=(const WebBundleTokenParams& other);
+
+ WebBundleTokenParams(const GURL& bundle_url,
+ const base::UnguessableToken& token,
+ mojo::PendingRemote<mojom::WebBundleHandle> handle);
+ WebBundleTokenParams(const GURL& bundle_url,
+ const base::UnguessableToken& token,
+ int32_t render_process_id);
+
+ // For testing. Regarding the equality of |handle|, |this| equals |other| if
+ // both |handle| exists, or neither exists, because we cannot test the
+ // equality of two mojo handles.
+ bool EqualsForTesting(const WebBundleTokenParams& other) const;
+
+ mojo::PendingRemote<mojom::WebBundleHandle> CloneHandle() const;
+
+ GURL bundle_url;
+ base::UnguessableToken token;
+ mojo::PendingRemote<mojom::WebBundleHandle> handle;
+ int32_t render_process_id = -1;
+ };
+
ResourceRequest();
ResourceRequest(const ResourceRequest& request);
~ResourceRequest();
@@ -70,7 +106,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
std::string method = net::HttpRequestHeaders::kGetMethod;
GURL url;
net::SiteForCookies site_for_cookies;
- bool force_ignore_site_for_cookies = false;
bool update_first_party_url_on_redirect = false;
// SECURITY NOTE: |request_initiator| is a security-sensitive field. Please
@@ -92,7 +127,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
bool originated_from_service_worker = false;
bool skip_service_worker = false;
bool corb_detachable = false;
- bool corb_excluded = false;
mojom::RequestMode mode = mojom::RequestMode::kNoCors;
mojom::CredentialsMode credentials_mode = mojom::CredentialsMode::kInclude;
mojom::RedirectMode redirect_mode = mojom::RedirectMode::kFollow;
@@ -119,6 +153,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
base::Optional<std::string> devtools_stack_id;
bool is_signed_exchange_prefetch_cache_enabled = false;
bool is_fetch_like_api = false;
+ bool is_favicon = false;
bool obey_origin_policy = false;
base::Optional<base::UnguessableToken> recursive_prefetch_token;
base::Optional<TrustedParams> trusted_params;
@@ -126,6 +161,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
// field trivially copyable; see OptionalTrustTokenParams's definition for
// more context.
OptionalTrustTokenParams trust_token_params;
+ base::Optional<WebBundleTokenParams> web_bundle_token_params;
};
// This does not accept |kDefault| referrer policy.
diff --git a/chromium/services/network/public/cpp/resource_request_body.cc b/chromium/services/network/public/cpp/resource_request_body.cc
index 59c1b3566ff..c8e7b4e1472 100644
--- a/chromium/services/network/public/cpp/resource_request_body.cc
+++ b/chromium/services/network/public/cpp/resource_request_body.cc
@@ -24,16 +24,14 @@ scoped_refptr<ResourceRequestBody> ResourceRequestBody::CreateFromBytes(
bool ResourceRequestBody::EnableToAppendElement() const {
return elements_.empty() ||
(elements_.front().type() !=
- mojom::DataElementType::kChunkedDataPipe &&
- elements_.front().type() != mojom::DataElementType::kReadOnceStream);
+ mojom::DataElementDataView::Tag::kChunkedDataPipe);
}
void ResourceRequestBody::AppendBytes(std::vector<uint8_t> bytes) {
DCHECK(EnableToAppendElement());
if (bytes.size() > 0) {
- elements_.push_back(DataElement());
- elements_.back().SetToBytes(std::move(bytes));
+ elements_.emplace_back(DataElementBytes(std::move(bytes)));
}
}
@@ -52,42 +50,34 @@ void ResourceRequestBody::AppendFileRange(
const base::Time& expected_modification_time) {
DCHECK(EnableToAppendElement());
- elements_.push_back(DataElement());
- elements_.back().SetToFilePathRange(file_path, offset, length,
- expected_modification_time);
+ elements_.emplace_back(
+ DataElementFile(file_path, offset, length, expected_modification_time));
}
void ResourceRequestBody::AppendDataPipe(
mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter) {
DCHECK(EnableToAppendElement());
+ DCHECK(data_pipe_getter);
- elements_.push_back(DataElement());
- elements_.back().SetToDataPipe(std::move(data_pipe_getter));
+ elements_.emplace_back(DataElementDataPipe(std::move(data_pipe_getter)));
}
void ResourceRequestBody::SetToChunkedDataPipe(
- mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter) {
+ mojo::PendingRemote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter,
+ ReadOnlyOnce read_only_once) {
DCHECK(elements_.empty());
+ DCHECK(chunked_data_pipe_getter);
- elements_.push_back(DataElement());
- elements_.back().SetToChunkedDataPipe(std::move(chunked_data_pipe_getter));
-}
-
-void ResourceRequestBody::SetToReadOnceStream(
- mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter) {
- DCHECK(elements_.empty());
-
- elements_.push_back(DataElement());
- elements_.back().SetToReadOnceStream(std::move(chunked_data_pipe_getter));
+ elements_.emplace_back(DataElementChunkedDataPipe(
+ std::move(chunked_data_pipe_getter), read_only_once));
}
std::vector<base::FilePath> ResourceRequestBody::GetReferencedFiles() const {
std::vector<base::FilePath> result;
for (const auto& element : *elements()) {
- if (element.type() == mojom::DataElementType::kFile)
- result.push_back(element.path());
+ if (element.type() == mojom::DataElementDataView::Tag::kFile) {
+ result.push_back(element.As<DataElementFile>().path());
+ }
}
return result;
}
diff --git a/chromium/services/network/public/cpp/resource_request_body.h b/chromium/services/network/public/cpp/resource_request_body.h
index 8c8517369f9..410e83c1fcc 100644
--- a/chromium/services/network/public/cpp/resource_request_body.h
+++ b/chromium/services/network/public/cpp/resource_request_body.h
@@ -32,6 +32,8 @@ namespace network {
class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
: public base::RefCountedThreadSafe<ResourceRequestBody> {
public:
+ using ReadOnlyOnce = DataElementChunkedDataPipe::ReadOnlyOnce;
+
ResourceRequestBody();
// Creates ResourceRequestBody that holds a copy of |bytes|.
@@ -59,7 +61,8 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
// method should only be used when talking to servers that are are known to
// support chunked uploads.
void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter);
+ chunked_data_pipe_getter,
+ ReadOnlyOnce read_only_once);
// Almost same as above except |chunked_data_pipe_getter| is read only once
// and you must talk with a server supporting chunked upload.
void SetToReadOnceStream(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
@@ -84,7 +87,7 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
int64_t identifier() const { return identifier_; }
// Returns paths referred to by |elements| of type
- // network::mojom::DataElementType::kFile.
+ // network::mojom::DataElementDataView::Tag::kFile.
std::vector<base::FilePath> GetReferencedFiles() const;
// Sets the flag which indicates whether the post data contains sensitive
diff --git a/chromium/services/network/public/cpp/schemeful_site_mojom_traits.cc b/chromium/services/network/public/cpp/schemeful_site_mojom_traits.cc
index fb0a0957876..675f23f2ef3 100644
--- a/chromium/services/network/public/cpp/schemeful_site_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/schemeful_site_mojom_traits.cc
@@ -14,16 +14,7 @@ bool StructTraits<network::mojom::SchemefulSiteDataView, net::SchemefulSite>::
if (!data.ReadSiteAsOrigin(&site_as_origin))
return false;
- // The origin passed into this constructor may not match the
- // `site_as_origin_` used as the internal representation of the schemeful
- // site. However, a valid SchemefulSite's internal origin should result in a
- // match if used to construct another SchemefulSite. Thus, if there is a
- // mismatch here, we must indicate a failure.
- net::SchemefulSite ss(site_as_origin);
- bool success = site_as_origin == ss.site_as_origin_;
- if (success)
- *out = std::move(ss);
- return success;
+ return net::SchemefulSite::FromWire(site_as_origin, out);
}
} // namespace mojo
diff --git a/chromium/services/network/public/cpp/schemeful_site_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/schemeful_site_mojom_traits_unittest.cc
index 135c92a8c2b..3515073c48d 100644
--- a/chromium/services/network/public/cpp/schemeful_site_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/schemeful_site_mojom_traits_unittest.cc
@@ -38,7 +38,7 @@ TEST(SchemefulSiteMojomTraitsTest, SerializeAndDeserialize) {
for (auto original : keys) {
net::SchemefulSite copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SchemefulSite>(
- &original, &copied));
+ original, copied));
EXPECT_EQ(original, copied);
}
}
diff --git a/chromium/services/network/public/cpp/self_deleting_url_loader_factory.cc b/chromium/services/network/public/cpp/self_deleting_url_loader_factory.cc
new file mode 100644
index 00000000000..c624b751b21
--- /dev/null
+++ b/chromium/services/network/public/cpp/self_deleting_url_loader_factory.cc
@@ -0,0 +1,52 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/self_deleting_url_loader_factory.h"
+
+#include <utility>
+
+namespace network {
+
+SelfDeletingURLLoaderFactory::SelfDeletingURLLoaderFactory(
+ mojo::PendingReceiver<mojom::URLLoaderFactory> factory_receiver) {
+ receivers_.set_disconnect_handler(base::BindRepeating(
+ &SelfDeletingURLLoaderFactory::OnDisconnect, base::Unretained(this)));
+ receivers_.Add(this, std::move(factory_receiver));
+}
+
+SelfDeletingURLLoaderFactory::~SelfDeletingURLLoaderFactory() = default;
+
+void SelfDeletingURLLoaderFactory::DisconnectReceiversAndDestroy() {
+ // Clear |receivers_| to explicitly make sure that no further method
+ // invocations or disconnection notifications will happen. (per the
+ // comment of mojo::ReceiverSet::Clear)
+ receivers_.Clear();
+
+ // Similarly to OnDisconnect, if there are no more |receivers_|, then no
+ // instance methods of |this| can be called in the future (mojo methods Clone
+ // and CreateLoaderAndStart should be the only public entrypoints).
+ // Therefore, it is safe to delete |this| at this point.
+ delete this;
+}
+
+void SelfDeletingURLLoaderFactory::Clone(
+ mojo::PendingReceiver<mojom::URLLoaderFactory> loader) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ receivers_.Add(this, std::move(loader));
+}
+
+void SelfDeletingURLLoaderFactory::OnDisconnect() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (receivers_.empty()) {
+ // If there are no more |receivers_|, then no instance methods of |this| can
+ // be called in the future (mojo methods Clone and CreateLoaderAndStart
+ // should be the only public entrypoints). Therefore, it is safe to delete
+ // |this| at this point.
+ delete this;
+ }
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/self_deleting_url_loader_factory.h b/chromium/services/network/public/cpp/self_deleting_url_loader_factory.h
new file mode 100644
index 00000000000..8e84590e58d
--- /dev/null
+++ b/chromium/services/network/public/cpp/self_deleting_url_loader_factory.h
@@ -0,0 +1,60 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_SELF_DELETING_URL_LOADER_FACTORY_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_SELF_DELETING_URL_LOADER_FACTORY_H_
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace network {
+
+// A base class for URLLoaderFactory implementations that takes care of the
+// managing the lifetime of the URLLoaderFactory implementation
+// which should be owned by the set of its receivers.
+class COMPONENT_EXPORT(NETWORK_CPP) SelfDeletingURLLoaderFactory
+ : public mojom::URLLoaderFactory {
+ protected:
+ // Constructs SelfDeletingURLLoaderFactory object that will self-delete
+ // once all receivers disconnect (including |factory_receiver| below as well
+ // as receivers that connect via the Clone method).
+ explicit SelfDeletingURLLoaderFactory(
+ mojo::PendingReceiver<mojom::URLLoaderFactory> factory_receiver);
+
+ ~SelfDeletingURLLoaderFactory() override;
+
+ // Sometimes a derived class can no longer function, even when the set of
+ // |receivers_| is still non-empty. This should be rare (typically the
+ // lifetime of users of mojo::Remote<mojom::URLLoaderFactory> should
+ // be shorter than whatever the factory depends on), but may happen in some
+ // corner cases (e.g. in a race between 1) BrowserContext destruction and 2)
+ // CreateLoaderAndStart mojo call).
+ //
+ // When a derived class gets notified that its dependencies got destroyed, it
+ // should call DisconnectReceiversAndDestroy to prevent any future calls to
+ // CreateLoaderAndStart.
+ void DisconnectReceiversAndDestroy();
+
+ THREAD_CHECKER(thread_checker_);
+
+ private:
+ // The override below is marked as |final| to make sure derived classes do not
+ // accidentally side-step lifetime management.
+ void Clone(mojo::PendingReceiver<mojom::URLLoaderFactory> loader) final;
+
+ void OnDisconnect();
+
+ mojo::ReceiverSet<mojom::URLLoaderFactory> receivers_;
+
+ DISALLOW_COPY_AND_ASSIGN(SelfDeletingURLLoaderFactory);
+};
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_SELF_DELETING_URL_LOADER_FACTORY_H_
diff --git a/chromium/services/network/public/cpp/simple_url_loader.cc b/chromium/services/network/public/cpp/simple_url_loader.cc
index 779be1f9b97..d7380996ff2 100644
--- a/chromium/services/network/public/cpp/simple_url_loader.cc
+++ b/chromium/services/network/public/cpp/simple_url_loader.cc
@@ -1135,6 +1135,10 @@ class DownloadAsStreamBodyHandler : public BodyHandler,
weak_ptr_factory_.GetWeakPtr()));
return;
}
+ if (!body_reader_) {
+ // If Resume was delayed, body_reader_ could have been deleted.
+ return;
+ }
body_reader_->Resume();
}
@@ -1168,8 +1172,8 @@ SimpleURLLoaderImpl::SimpleURLLoaderImpl(
// Bytes should be attached with AttachStringForUpload to allow
// streaming of large byte buffers to the network process when uploading.
- DCHECK(element.type() != mojom::DataElementType::kFile &&
- element.type() != mojom::DataElementType::kBytes);
+ DCHECK(element.type() != mojom::DataElementDataView::Tag::kFile &&
+ element.type() != mojom::DataElementDataView::Tag::kBytes);
}
}
#endif // DCHECK_IS_ON()
@@ -1357,7 +1361,7 @@ void SimpleURLLoaderImpl::SetRetryOptions(int max_retries, int retry_mode) {
// pipe.
// TODO(mmenke): Data pipes can be Cloned(), though, so maybe update code
// to do that?
- DCHECK(element.type() != mojom::DataElementType::kDataPipe);
+ DCHECK(element.type() != mojom::DataElementDataView::Tag::kDataPipe);
}
}
#endif // DCHECK_IS_ON()
diff --git a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
index 2b9a8a21413..2ee17dfa065 100644
--- a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -251,6 +251,17 @@ class SimpleLoaderTestHelper : public SimpleURLLoaderStreamConsumer {
download_to_stream_async_resume_ = download_to_stream_async_resume;
}
+ // Sets whether the resume-reading closure should be captured and later
+ // available in TakeCapturedStreamResume()
+ void set_download_to_stream_capture_resume(
+ bool download_to_stream_capture_resume) {
+ download_to_stream_capture_resume_ = download_to_stream_capture_resume;
+ }
+
+ base::OnceClosure TakeCapturedStreamResume() {
+ return std::move(captured_stream_resume_);
+ }
+
// Sets whether the helper should destroy the SimpleURLLoader in
// OnDataReceived.
void set_download_to_stream_destroy_on_data_received(
@@ -417,6 +428,14 @@ class SimpleLoaderTestHelper : public SimpleURLLoaderStreamConsumer {
return;
}
+ if (download_to_stream_capture_resume_) {
+ if (captured_stream_resume_) {
+ std::move(captured_stream_resume_).Run();
+ }
+ captured_stream_resume_ = std::move(resume);
+ return;
+ }
+
if (download_to_stream_async_resume_) {
base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
std::move(resume));
@@ -496,6 +515,8 @@ class SimpleLoaderTestHelper : public SimpleURLLoaderStreamConsumer {
bool download_to_stream_destroy_on_data_received_ = false;
bool download_to_stream_async_retry_ = false;
bool download_to_stream_destroy_on_retry_ = false;
+ bool download_to_stream_capture_resume_ = false;
+ base::OnceClosure captured_stream_resume_;
bool destroy_loader_on_complete_ = false;
@@ -1966,9 +1987,10 @@ class MockURLLoader : public network::mojom::URLLoader {
test_events_(std::move(test_events)) {
if (request_body && request_body->elements()->size() == 1 &&
(*request_body->elements())[0].type() ==
- network::mojom::DataElementType::kDataPipe) {
- data_pipe_getter_.Bind(
- (*request_body->elements())[0].CloneDataPipeGetter());
+ network::mojom::DataElementDataView::Tag::kDataPipe) {
+ const auto& element =
+ (*request_body->elements())[0].As<network::DataElementDataPipe>();
+ data_pipe_getter_.Bind(element.CloneDataPipeGetter());
DCHECK(data_pipe_getter_);
}
}
@@ -1981,13 +2003,15 @@ class MockURLLoader : public network::mojom::URLLoader {
upload_data_pipe_.reset();
weak_factory_for_data_pipe_callbacks_.InvalidateWeakPtrs();
read_run_loop_ = std::make_unique<base::RunLoop>();
- mojo::DataPipe data_pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ ASSERT_EQ(
+ mojo::CreateDataPipe(nullptr, producer_handle, upload_data_pipe_),
+ MOJO_RESULT_OK);
data_pipe_getter_->Read(
- std::move(data_pipe.producer_handle),
+ std::move(producer_handle),
base::BindOnce(
&MockURLLoader::OnReadComplete,
weak_factory_for_data_pipe_callbacks_.GetWeakPtr()));
- upload_data_pipe_ = std::move(data_pipe.consumer_handle);
// Continue instead of break, to avoid spinning the message loop -
// only wait for the response if next step indicates to do so.
continue;
@@ -2091,10 +2115,10 @@ class MockURLLoader : public network::mojom::URLLoader {
break;
}
case TestLoaderEvent::kBodyBufferReceived: {
- mojo::DataPipe data_pipe(1024);
- body_stream_ = std::move(data_pipe.producer_handle);
- client_->OnStartLoadingResponseBody(
- std::move(data_pipe.consumer_handle));
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(1024, body_stream_, consumer_handle),
+ MOJO_RESULT_OK);
+ client_->OnStartLoadingResponseBody(std::move(consumer_handle));
break;
}
case TestLoaderEvent::kBodyDataRead: {
@@ -3420,6 +3444,17 @@ class SimpleURLLoaderMockTimeTest : public testing::Test {
SimpleLoaderTestHelper::DownloadType::TO_STRING);
}
+ std::unique_ptr<SimpleLoaderTestHelper> CreateStreamHelper() {
+ std::unique_ptr<network::ResourceRequest> resource_request =
+ std::make_unique<network::ResourceRequest>();
+ resource_request->url = GURL("foo://bar/");
+ resource_request->method = "GET";
+ resource_request->enable_upload_progress = true;
+ return std::make_unique<SimpleLoaderTestHelper>(
+ std::move(resource_request),
+ SimpleLoaderTestHelper::DownloadType::AS_STREAM);
+ }
+
protected:
base::test::TaskEnvironment task_environment_;
std::unique_ptr<base::ScopedDisallowBlocking> disallow_blocking_;
@@ -3443,6 +3478,32 @@ TEST_F(SimpleURLLoaderMockTimeTest, TimeoutTriggered) {
EXPECT_FALSE(test_helper->simple_url_loader()->CompletionStatus());
}
+// Request fails with a timeout like in TimeoutTriggered, and the stream resume
+// closure is called after the timeout. The loader is alive throughout.
+TEST_F(SimpleURLLoaderMockTimeTest, StreamResumeAfterTimeout) {
+ MockURLLoaderFactory loader_factory(&task_environment_);
+ loader_factory.AddEvents(
+ {TestLoaderEvent::kReceivedResponse, TestLoaderEvent::kBodyBufferReceived,
+ TestLoaderEvent::kBodyDataRead, TestLoaderEvent::kAdvanceOneSecond,
+ TestLoaderEvent::kResponseComplete, TestLoaderEvent::kBodyBufferClosed});
+ std::unique_ptr<SimpleLoaderTestHelper> test_helper = CreateStreamHelper();
+ test_helper->simple_url_loader()->SetTimeoutDuration(
+ base::TimeDelta::FromSeconds(1));
+ test_helper->set_download_to_stream_capture_resume(true);
+
+ loader_factory.RunTest(test_helper.get());
+
+ EXPECT_EQ(net::ERR_TIMED_OUT, test_helper->simple_url_loader()->NetError());
+ EXPECT_FALSE(test_helper->simple_url_loader()->CompletionStatus());
+
+ base::OnceClosure captured_resume = test_helper->TakeCapturedStreamResume();
+ ASSERT_TRUE(captured_resume);
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ std::move(captured_resume));
+ // Make sure no pending task results in a crash.
+ base::RunLoop().RunUntilIdle();
+}
+
// Less time is simulated passing than the timeout value, so this request should
// succeed normally.
TEST_F(SimpleURLLoaderMockTimeTest, TimeoutNotTriggered) {
diff --git a/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc b/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc
index 282d0ef1e08..48968f3e5ea 100644
--- a/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "services/network/public/cpp/site_for_cookies_mojom_traits.h"
-#include "net/base/features.h"
+
#include "services/network/public/cpp/crash_keys.h"
namespace mojo {
@@ -11,16 +11,13 @@ namespace mojo {
bool StructTraits<network::mojom::SiteForCookiesDataView, net::SiteForCookies>::
Read(network::mojom::SiteForCookiesDataView data,
net::SiteForCookies* out) {
- std::string scheme, registrable_domain;
- if (!data.ReadScheme(&scheme)) {
- return false;
- }
- if (!data.ReadRegistrableDomain(&registrable_domain)) {
+ net::SchemefulSite site;
+ if (!data.ReadSite(&site)) {
return false;
}
- bool result = net::SiteForCookies::FromWire(scheme, registrable_domain,
- data.schemefully_same(), out);
+ bool result =
+ net::SiteForCookies::FromWire(site, data.schemefully_same(), out);
if (!result) {
network::debug::SetDeserializationCrashKeyString("site_for_cookie");
}
diff --git a/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h b/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h
index 2663f74a784..de504f69ee2 100644
--- a/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h
+++ b/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h
@@ -5,10 +5,10 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_SITE_FOR_COOKIES_MOJOM_TRAITS_H_
#define SERVICES_NETWORK_PUBLIC_CPP_SITE_FOR_COOKIES_MOJOM_TRAITS_H_
-#include <string>
-
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "net/base/schemeful_site.h"
#include "net/cookies/site_for_cookies.h"
+#include "services/network/public/cpp/schemeful_site_mojom_traits.h"
#include "services/network/public/mojom/site_for_cookies.mojom-shared.h"
namespace mojo {
@@ -16,13 +16,8 @@ namespace mojo {
template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
StructTraits<network::mojom::SiteForCookiesDataView, net::SiteForCookies> {
- static const std::string& scheme(const net::SiteForCookies& input) {
- return input.scheme();
- }
-
- static const std::string& registrable_domain(
- const net::SiteForCookies& input) {
- return input.registrable_domain();
+ static const net::SchemefulSite& site(const net::SiteForCookies& input) {
+ return input.site();
}
static bool schemefully_same(const net::SiteForCookies& input) {
diff --git a/chromium/services/network/public/cpp/site_for_cookies_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/site_for_cookies_mojom_traits_unittest.cc
index 65603ccea97..61111db742b 100644
--- a/chromium/services/network/public/cpp/site_for_cookies_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/site_for_cookies_mojom_traits_unittest.cc
@@ -22,7 +22,7 @@ TEST(SiteForCookiesMojomTraitsTest, SerializeAndDeserialize) {
net::SiteForCookies copied;
EXPECT_TRUE(
mojo::test::SerializeAndDeserialize<network::mojom::SiteForCookies>(
- &original, &copied));
+ original, copied));
EXPECT_TRUE(original.IsEquivalent(copied));
EXPECT_EQ(original.schemefully_same(), copied.schemefully_same());
}
diff --git a/chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc b/chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
index 6fcac5fc307..60d154e9cea 100644
--- a/chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
+++ b/chromium/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
@@ -58,9 +58,8 @@ class SourceStreamToDataPipeTest
sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1,
GetParam().pipe_capacity};
mojo::ScopedDataPipeProducerHandle producer_end;
- CHECK_EQ(MOJO_RESULT_OK,
- mojo::CreateDataPipe(&data_pipe_options, &producer_end,
- &consumer_end_));
+ CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&data_pipe_options,
+ producer_end, consumer_end_));
adapter_ = std::make_unique<SourceStreamToDataPipe>(
std::move(source), std::move(producer_end));
diff --git a/chromium/services/network/public/cpp/trust_token_http_headers.h b/chromium/services/network/public/cpp/trust_token_http_headers.h
index ed6fcfb78f5..6906478b311 100644
--- a/chromium/services/network/public/cpp/trust_token_http_headers.h
+++ b/chromium/services/network/public/cpp/trust_token_http_headers.h
@@ -40,7 +40,7 @@ constexpr char kTrustTokensRequestHeaderSecTime[] = "Sec-Time";
// collection of headers; and, optionally, the request's body).
constexpr char kTrustTokensRequestHeaderSecSignature[] = "Sec-Signature";
-// As a request header, provides aRedemption Record obtained from a prior
+// As a request header, provides a Redemption Record obtained from a prior
// issuance-and-redemption flow.
constexpr char kTrustTokensRequestHeaderSecRedemptionRecord[] =
"Sec-Redemption-Record";
diff --git a/chromium/services/network/public/cpp/url_loader_completion_status.h b/chromium/services/network/public/cpp/url_loader_completion_status.h
index 8d7d40c4fc3..4c3b678b6b0 100644
--- a/chromium/services/network/public/cpp/url_loader_completion_status.h
+++ b/chromium/services/network/public/cpp/url_loader_completion_status.h
@@ -87,7 +87,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) URLLoaderCompletionStatus {
base::Optional<net::SSLInfo> ssl_info;
// More detailed reason for failing the response with
- // ERR_net::ERR_BLOCKED_BY_RESPONSE |error_code|.
+ // net::ERR_BLOCKED_BY_RESPONSE |error_code|.
base::Optional<mojom::BlockedByResponseReason> blocked_by_response_reason;
// Set when response blocked by CORB needs to be reported to the DevTools
diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits.cc b/chromium/services/network/public/cpp/url_request_mojom_traits.cc
index 8626ff6086f..402daf03291 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/debug/dump_without_crashing.h"
+#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "mojo/public/cpp/base/file_mojom_traits.h"
#include "mojo/public/cpp/base/file_path_mojom_traits.h"
@@ -20,6 +21,7 @@
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/public/mojom/url_loader.mojom-shared.h"
+#include "services/network/public/mojom/web_bundle_handle.mojom.h"
#include "url/mojom/origin_mojom_traits.h"
#include "url/mojom/url_gurl_mojom_traits.h"
@@ -156,12 +158,30 @@ bool StructTraits<network::mojom::TrustedUrlRequestParamsDataView,
out->has_user_activation = data.has_user_activation();
out->cookie_observer = data.TakeCookieObserver<
mojo::PendingRemote<network::mojom::CookieAccessObserver>>();
+ out->auth_cert_observer = data.TakeAuthCertObserver<mojo::PendingRemote<
+ network::mojom::AuthenticationAndCertificateObserver>>();
if (!data.ReadClientSecurityState(&out->client_security_state)) {
return false;
}
return true;
}
+bool StructTraits<network::mojom::WebBundleTokenParamsDataView,
+ network::ResourceRequest::WebBundleTokenParams>::
+ Read(network::mojom::WebBundleTokenParamsDataView data,
+ network::ResourceRequest::WebBundleTokenParams* out) {
+ if (!data.ReadBundleUrl(&out->bundle_url)) {
+ return false;
+ }
+ if (!data.ReadToken(&out->token)) {
+ return false;
+ }
+ out->handle = data.TakeWebBundleHandle<
+ mojo::PendingRemote<network::mojom::WebBundleHandle>>();
+ out->render_process_id = data.render_process_id();
+ return true;
+}
+
bool StructTraits<
network::mojom::URLRequestDataView,
network::ResourceRequest>::Read(network::mojom::URLRequestDataView data,
@@ -203,7 +223,8 @@ bool StructTraits<
!data.ReadFetchWindowId(&out->fetch_window_id) ||
!data.ReadDevtoolsRequestId(&out->devtools_request_id) ||
!data.ReadDevtoolsStackId(&out->devtools_stack_id) ||
- !data.ReadRecursivePrefetchToken(&out->recursive_prefetch_token)) {
+ !data.ReadRecursivePrefetchToken(&out->recursive_prefetch_token) ||
+ !data.ReadWebBundleTokenParams(&out->web_bundle_token_params)) {
// Note that data.ReadTrustTokenParams is temporarily handled below.
return false;
}
@@ -216,7 +237,6 @@ bool StructTraits<
base::debug::DumpWithoutCrashing();
}
- out->force_ignore_site_for_cookies = data.force_ignore_site_for_cookies();
out->update_first_party_url_on_redirect =
data.update_first_party_url_on_redirect();
out->load_flags = data.load_flags();
@@ -226,7 +246,6 @@ bool StructTraits<
out->originated_from_service_worker = data.originated_from_service_worker();
out->skip_service_worker = data.skip_service_worker();
out->corb_detachable = data.corb_detachable();
- out->corb_excluded = data.corb_excluded();
out->destination = data.destination();
out->keepalive = data.keepalive();
out->has_user_gesture = data.has_user_gesture();
@@ -243,6 +262,7 @@ bool StructTraits<
out->is_signed_exchange_prefetch_cache_enabled =
data.is_signed_exchange_prefetch_cache_enabled();
out->is_fetch_like_api = data.is_fetch_like_api();
+ out->is_favicon = data.is_favicon();
out->obey_origin_policy = data.obey_origin_policy();
return true;
}
@@ -262,35 +282,100 @@ bool StructTraits<network::mojom::URLRequestBodyDataView,
return true;
}
-bool StructTraits<network::mojom::DataElementDataView, network::DataElement>::
- Read(network::mojom::DataElementDataView data, network::DataElement* out) {
- if (!data.ReadPath(&out->path_)) {
- network::debug::SetDeserializationCrashKeyString("data_element_path");
+bool StructTraits<network::mojom::DataElementBytesDataView,
+ network::DataElementBytes>::
+ Read(network::mojom::DataElementBytesDataView data,
+ network::DataElementBytes* out) {
+ mojo_base::BigBufferView big_buffer_view;
+ if (!data.ReadData(&big_buffer_view)) {
return false;
}
- if (!data.ReadExpectedModificationTime(&out->expected_modification_time_)) {
+ *out = network::DataElementBytes(std::vector<uint8_t>(
+ big_buffer_view.data().begin(), big_buffer_view.data().end()));
+ return true;
+}
+
+bool StructTraits<network::mojom::DataElementDataPipeDataView,
+ network::DataElementDataPipe>::
+ Read(network::mojom::DataElementDataPipeDataView data,
+ network::DataElementDataPipe* out) {
+ auto data_pipe_getter = data.TakeDataPipeGetter<
+ mojo::PendingRemote<network::mojom::DataPipeGetter>>();
+ *out = network::DataElementDataPipe(std::move(data_pipe_getter));
+ return true;
+}
+
+bool StructTraits<network::mojom::DataElementChunkedDataPipeDataView,
+ network::DataElementChunkedDataPipe>::
+ Read(network::mojom::DataElementChunkedDataPipeDataView data,
+ network::DataElementChunkedDataPipe* out) {
+ auto data_pipe_getter = data.TakeDataPipeGetter<
+ mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>>();
+ UMA_HISTOGRAM_BOOLEAN("NetworkService.StreamingUploadDataPipeGetterValidity",
+ data_pipe_getter.is_valid());
+ *out = network::DataElementChunkedDataPipe(
+ std::move(data_pipe_getter),
+ network::DataElementChunkedDataPipe::ReadOnlyOnce(data.read_only_once()));
+ return true;
+}
+
+bool StructTraits<network::mojom::DataElementFileDataView,
+ network::DataElementFile>::
+ Read(network::mojom::DataElementFileDataView data,
+ network::DataElementFile* out) {
+ base::FilePath path;
+ if (!data.ReadPath(&path)) {
return false;
}
- if (data.type() == network::mojom::DataElementType::kBytes) {
- mojo_base::BigBufferView big_buffer;
- if (!data.ReadBuf(&big_buffer))
- return false;
- // TODO(yoichio): Fix DataElementDataView::ReadBuf issue
- // (crbug.com/1152664).
- if (data.length() != big_buffer.data().size())
- return false;
- out->buf_.clear();
- out->buf_.insert(out->buf_.end(), big_buffer.data().begin(),
- big_buffer.data().end());
+ base::Time expected_modification_time;
+ if (!data.ReadExpectedModificationTime(&expected_modification_time)) {
+ return false;
}
- out->type_ = data.type();
- out->data_pipe_getter_ = data.TakeDataPipeGetter<
- mojo::PendingRemote<network::mojom::DataPipeGetter>>();
- out->chunked_data_pipe_getter_ = data.TakeChunkedDataPipeGetter<
- mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>>();
- out->offset_ = data.offset();
- out->length_ = data.length();
+ *out = network::DataElementFile(path, data.offset(), data.length(),
+ expected_modification_time);
return true;
}
+bool UnionTraits<network::mojom::DataElementDataView, network::DataElement>::
+ Read(network::mojom::DataElementDataView data, network::DataElement* out) {
+ using Tag = network::mojom::DataElementDataView::Tag;
+ DCHECK(!data.is_null());
+
+ switch (data.tag()) {
+ case Tag::kBytes: {
+ network::DataElementBytes bytes;
+ if (!data.ReadBytes(&bytes)) {
+ return false;
+ }
+ *out = network::DataElement(std::move(bytes));
+ return true;
+ }
+ case Tag::kDataPipe: {
+ network::DataElementDataPipe data_pipe;
+ if (!data.ReadDataPipe(&data_pipe)) {
+ return false;
+ }
+ *out = network::DataElement(std::move(data_pipe));
+ return true;
+ }
+ case Tag::kChunkedDataPipe: {
+ network::DataElementChunkedDataPipe chunked_data_pipe;
+ if (!data.ReadChunkedDataPipe(&chunked_data_pipe)) {
+ return false;
+ }
+ *out = network::DataElement(std::move(chunked_data_pipe));
+ return true;
+ }
+ case Tag::kFile: {
+ network::DataElementFile file;
+ if (!data.ReadFile(&file)) {
+ return false;
+ }
+ *out = network::DataElement(std::move(file));
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace mojo
diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits.h b/chromium/services/network/public/cpp/url_request_mojom_traits.h
index 2568ed5e70e..e8266469f6f 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits.h
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits.h
@@ -17,6 +17,7 @@
#include "mojo/public/cpp/bindings/enum_traits.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "mojo/public/cpp/bindings/union_traits.h"
#include "net/base/request_priority.h"
#include "net/url_request/referrer_policy.h"
#include "services/network/public/cpp/data_element.h"
@@ -24,12 +25,14 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/cpp/site_for_cookies_mojom_traits.h"
+#include "services/network/public/mojom/auth_and_certificate_observer.mojom.h"
#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
#include "services/network/public/mojom/client_security_state.mojom-forward.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
#include "services/network/public/mojom/data_pipe_getter.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/public/mojom/url_loader.mojom-shared.h"
+#include "services/network/public/mojom/web_bundle_handle.mojom-shared.h"
#include "url/mojom/url_gurl_mojom_traits.h"
namespace mojo {
@@ -76,6 +79,16 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
const_cast<network::ResourceRequest::TrustedParams&>(trusted_params)
.cookie_observer);
}
+ static mojo::PendingRemote<
+ network::mojom::AuthenticationAndCertificateObserver>
+ auth_cert_observer(
+ const network::ResourceRequest::TrustedParams& trusted_params) {
+ if (!trusted_params.auth_cert_observer)
+ return mojo::NullRemote();
+ return std::move(
+ const_cast<network::ResourceRequest::TrustedParams&>(trusted_params)
+ .auth_cert_observer);
+ }
static const network::mojom::ClientSecurityStatePtr& client_security_state(
const network::ResourceRequest::TrustedParams& trusted_params) {
return trusted_params.client_security_state;
@@ -87,6 +100,35 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+ StructTraits<network::mojom::WebBundleTokenParamsDataView,
+ network::ResourceRequest::WebBundleTokenParams> {
+ static const GURL& bundle_url(
+ const network::ResourceRequest::WebBundleTokenParams& params) {
+ return params.bundle_url;
+ }
+ static const base::UnguessableToken& token(
+ const network::ResourceRequest::WebBundleTokenParams& params) {
+ return params.token;
+ }
+ static mojo::PendingRemote<network::mojom::WebBundleHandle> web_bundle_handle(
+ const network::ResourceRequest::WebBundleTokenParams& params) {
+ if (!params.handle)
+ return mojo::NullRemote();
+ return std::move(
+ const_cast<network::ResourceRequest::WebBundleTokenParams&>(params)
+ .handle);
+ }
+ static int32_t render_process_id(
+ const network::ResourceRequest::WebBundleTokenParams& params) {
+ return params.render_process_id;
+ }
+
+ static bool Read(network::mojom::WebBundleTokenParamsDataView data,
+ network::ResourceRequest::WebBundleTokenParams* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
StructTraits<network::mojom::URLRequestDataView, network::ResourceRequest> {
static const std::string& method(const network::ResourceRequest& request) {
return request.method;
@@ -98,10 +140,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
const network::ResourceRequest& request) {
return request.site_for_cookies;
}
- static bool force_ignore_site_for_cookies(
- const network::ResourceRequest& request) {
- return request.force_ignore_site_for_cookies;
- }
static bool update_first_party_url_on_redirect(
const network::ResourceRequest& request) {
return request.update_first_party_url_on_redirect;
@@ -159,9 +197,6 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
static bool corb_detachable(const network::ResourceRequest& request) {
return request.corb_detachable;
}
- static bool corb_excluded(const network::ResourceRequest& request) {
- return request.corb_excluded;
- }
static network::mojom::RequestMode mode(
const network::ResourceRequest& request) {
return request.mode;
@@ -253,6 +288,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
static bool is_fetch_like_api(const network::ResourceRequest& request) {
return request.is_fetch_like_api;
}
+ static bool is_favicon(const network::ResourceRequest& request) {
+ return request.is_favicon;
+ }
static bool obey_origin_policy(const network::ResourceRequest& request) {
return request.obey_origin_policy;
}
@@ -268,6 +306,10 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
const network::ResourceRequest& request) {
return request.trust_token_params.as_ptr();
}
+ static const base::Optional<network::ResourceRequest::WebBundleTokenParams>&
+ web_bundle_token_params(const network::ResourceRequest& request) {
+ return request.web_bundle_token_params;
+ }
static bool Read(network::mojom::URLRequestDataView data,
network::ResourceRequest* out);
@@ -311,40 +353,91 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
- StructTraits<network::mojom::DataElementDataView, network::DataElement> {
- static const network::mojom::DataElementType& type(
- const network::DataElement& element) {
- return element.type_;
- }
- static mojo_base::BigBufferView buf(const network::DataElement& element) {
- return mojo_base::BigBufferView(element.buf_);
- }
- static const base::FilePath& path(const network::DataElement& element) {
- return element.path_;
+ StructTraits<network::mojom::DataElementBytesDataView,
+ network::DataElementBytes> {
+ static mojo_base::BigBufferView data(const network::DataElementBytes& data) {
+ return mojo_base::BigBufferView(data.bytes());
}
+
+ static bool Read(network::mojom::DataElementBytesDataView data,
+ network::DataElementBytes* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+ StructTraits<network::mojom::DataElementDataPipeDataView,
+ network::DataElementDataPipe> {
static mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter(
- const network::DataElement& element) {
- if (element.type_ != network::mojom::DataElementType::kDataPipe)
- return mojo::NullRemote();
- return element.CloneDataPipeGetter();
+ const network::DataElementDataPipe& data) {
+ return data.CloneDataPipeGetter();
}
+
+ static bool Read(network::mojom::DataElementDataPipeDataView data,
+ network::DataElementDataPipe* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+ StructTraits<network::mojom::DataElementChunkedDataPipeDataView,
+ network::DataElementChunkedDataPipe> {
static mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
- chunked_data_pipe_getter(const network::DataElement& element) {
- if (element.type_ != network::mojom::DataElementType::kChunkedDataPipe &&
- element.type_ != network::mojom::DataElementType::kReadOnceStream)
- return mojo::NullRemote();
- return const_cast<network::DataElement&>(element)
+ data_pipe_getter(const network::DataElementChunkedDataPipe& data) {
+ return const_cast<network::DataElementChunkedDataPipe&>(data)
.ReleaseChunkedDataPipeGetter();
}
- static uint64_t offset(const network::DataElement& element) {
- return element.offset_;
+ static bool read_only_once(const network::DataElementChunkedDataPipe& data) {
+ return static_cast<bool>(data.read_only_once());
+ }
+
+ static bool Read(network::mojom::DataElementChunkedDataPipeDataView data,
+ network::DataElementChunkedDataPipe* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+ StructTraits<network::mojom::DataElementFileDataView,
+ network::DataElementFile> {
+ static base::FilePath path(const network::DataElementFile& data) {
+ return data.path();
+ }
+ static uint64_t offset(const network::DataElementFile& data) {
+ return data.offset();
+ }
+ static uint64_t length(const network::DataElementFile& data) {
+ return data.length();
+ }
+ static base::Time expected_modification_time(
+ const network::DataElementFile& data) {
+ return data.expected_modification_time();
+ }
+
+ static bool Read(network::mojom::DataElementFileDataView data,
+ network::DataElementFile* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+ UnionTraits<network::mojom::DataElementDataView, network::DataElement> {
+ static network::mojom::DataElementDataView::Tag GetTag(
+ const network::DataElement& data) {
+ return data.type();
+ }
+
+ static const network::DataElementBytes& bytes(
+ const network::DataElement& data) {
+ return data.As<network::DataElementBytes>();
+ }
+ static const network::DataElementDataPipe& data_pipe(
+ const network::DataElement& data) {
+ return data.As<network::DataElementDataPipe>();
}
- static uint64_t length(const network::DataElement& element) {
- return element.length_;
+ static const network::DataElementChunkedDataPipe& chunked_data_pipe(
+ const network::DataElement& data) {
+ return data.As<network::DataElementChunkedDataPipe>();
}
- static const base::Time& expected_modification_time(
- const network::DataElement& element) {
- return element.expected_modification_time_;
+ static const network::DataElementFile& file(
+ const network::DataElement& data) {
+ return data.As<network::DataElementFile>();
}
static bool Read(network::mojom::DataElementDataView data,
diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc
index abbd67bdd87..cbf992e29d5 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc
@@ -4,7 +4,9 @@
#include "services/network/public/cpp/url_request_mojom_traits.h"
+#include "base/optional.h"
#include "base/test/gtest_util.h"
+#include "base/test/task_environment.h"
#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/base/isolation_info.h"
@@ -47,7 +49,6 @@ TEST(URLRequestMojomTraitsTest, Roundtrips_ResourceRequest) {
original.url = GURL("https://example.com/resources/dummy.xml");
original.site_for_cookies =
net::SiteForCookies::FromUrl(GURL("https://example.com/index.html"));
- original.force_ignore_site_for_cookies = true;
original.update_first_party_url_on_redirect = false;
original.request_initiator = url::Origin::Create(original.url);
original.isolated_world_origin =
@@ -102,12 +103,104 @@ TEST(URLRequestMojomTraitsTest, Roundtrips_ResourceRequest) {
mojom::TrustTokenSignRequestData::kInclude;
original.trust_token_params->additional_signed_headers.push_back(
"some_header");
+ original.web_bundle_token_params =
+ base::make_optional(ResourceRequest::WebBundleTokenParams(
+ GURL("https://bundle.test/"), base::UnguessableToken::Create(),
+ mojo::PendingRemote<network::mojom::WebBundleHandle>()));
network::ResourceRequest copied;
- EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::URLRequest>(&original,
- &copied));
+ EXPECT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::URLRequest>(original, copied));
EXPECT_TRUE(original.EqualsForTesting(copied));
}
+class DataElementDeserializationTest : public testing::Test {
+ protected:
+ base::test::TaskEnvironment task_environment_;
+};
+
+TEST_F(DataElementDeserializationTest, DataPipe) {
+ mojo::PendingRemote<mojom::DataPipeGetter> pending_remote;
+ auto pending_receiver = pending_remote.InitWithNewPipeAndPassReceiver();
+ DataElement src{DataElementDataPipe(std::move(pending_remote))};
+
+ DataElement dest;
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::DataElement>(src, dest));
+ ASSERT_EQ(dest.type(), network::DataElement::Tag::kDataPipe);
+
+ mojo::Remote<mojom::DataPipeGetter> remote(
+ dest.As<DataElementDataPipe>().ReleaseDataPipeGetter());
+
+ // Make sure that `remote` and `pending_receiver` is connected to each other.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(remote.is_bound());
+ EXPECT_TRUE(remote.is_connected());
+
+ pending_receiver.reset();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(remote.is_bound());
+ EXPECT_FALSE(remote.is_connected());
+}
+
+TEST_F(DataElementDeserializationTest, ChunkedDataPipe) {
+ mojo::PendingRemote<mojom::ChunkedDataPipeGetter> pending_remote;
+ auto pending_receiver = pending_remote.InitWithNewPipeAndPassReceiver();
+ DataElement src(DataElementChunkedDataPipe(
+ std::move(pending_remote),
+ DataElementChunkedDataPipe::ReadOnlyOnce(true)));
+ DataElement dest;
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::DataElement>(src, dest));
+ ASSERT_EQ(dest.type(), network::DataElement::Tag::kChunkedDataPipe);
+ EXPECT_TRUE(dest.As<DataElementChunkedDataPipe>().read_only_once());
+ mojo::Remote<mojom::ChunkedDataPipeGetter> remote(
+ dest.As<DataElementChunkedDataPipe>().ReleaseChunkedDataPipeGetter());
+
+ // Make sure that `remote` and `pending_receiver` is connected to each other.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(remote.is_bound());
+ EXPECT_TRUE(remote.is_connected());
+
+ pending_receiver.reset();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(remote.is_bound());
+ EXPECT_FALSE(remote.is_connected());
+}
+
+TEST_F(DataElementDeserializationTest, Bytes) {
+ const std::vector<uint8_t> kData = {8, 1, 9};
+ DataElement src{DataElementBytes(kData)};
+ DataElement dest;
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::DataElement>(src, dest));
+ ASSERT_EQ(mojom::DataElementDataView::Tag::kBytes, dest.type());
+ EXPECT_EQ(kData, dest.As<DataElementBytes>().bytes());
+}
+
+TEST_F(DataElementDeserializationTest, File) {
+ const base::FilePath kPath = base::FilePath::FromUTF8Unsafe("foobar");
+ DataElement src(DataElementFile(
+ kPath, /*offset=*/3, /*length=*/8,
+ base::Time::UnixEpoch() + base::TimeDelta::FromMinutes(2)));
+ DataElement dest;
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::DataElement>(src, dest));
+ ASSERT_EQ(mojom::DataElementDataView::Tag::kFile, dest.type());
+
+ const auto& src_file = src.As<DataElementFile>();
+ const auto& dest_file = dest.As<DataElementFile>();
+
+ EXPECT_EQ(src_file.path(), dest_file.path());
+ EXPECT_EQ(src_file.offset(), dest_file.offset());
+ EXPECT_EQ(src_file.length(), dest_file.length());
+ EXPECT_EQ(src_file.expected_modification_time(),
+ dest_file.expected_modification_time());
+}
+
} // namespace
} // namespace network
diff --git a/chromium/services/network/public/cpp/x_frame_options.dict b/chromium/services/network/public/cpp/x_frame_options.dict
new file mode 100644
index 00000000000..444b1778646
--- /dev/null
+++ b/chromium/services/network/public/cpp/x_frame_options.dict
@@ -0,0 +1,11 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+" "
+","
+"DENY"
+"SAMEORIGIN"
+"ALLOWALL"
+"ALLOW-FROM"
+"https://www.example.com/"
diff --git a/chromium/services/network/public/cpp/x_frame_options_parser.cc b/chromium/services/network/public/cpp/x_frame_options_parser.cc
new file mode 100644
index 00000000000..e288d200989
--- /dev/null
+++ b/chromium/services/network/public/cpp/x_frame_options_parser.cc
@@ -0,0 +1,46 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/x_frame_options_parser.h"
+
+#include <string>
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "net/http/http_response_headers.h"
+#include "services/network/public/mojom/x_frame_options.mojom-shared.h"
+
+namespace network {
+
+mojom::XFrameOptionsValue ParseXFrameOptions(
+ const net::HttpResponseHeaders& headers) {
+ // Process the 'X-Frame-Options' header:
+ // https://html.spec.whatwg.org/multipage/browsing-the-web.html#the-x-frame-options-header
+ //
+ // Note that we do not support the 'ALLOW-FROM' value defined in RFC7034.
+ mojom::XFrameOptionsValue result = mojom::XFrameOptionsValue::kNone;
+ size_t iter = 0;
+ std::string value;
+ while (headers.EnumerateHeader(&iter, "x-frame-options", &value)) {
+ mojom::XFrameOptionsValue current = mojom::XFrameOptionsValue::kInvalid;
+
+ base::StringPiece trimmed =
+ base::TrimWhitespaceASCII(value, base::TRIM_ALL);
+
+ if (base::LowerCaseEqualsASCII(trimmed, "deny"))
+ current = mojom::XFrameOptionsValue::kDeny;
+ else if (base::LowerCaseEqualsASCII(trimmed, "allowall"))
+ current = mojom::XFrameOptionsValue::kAllowAll;
+ else if (base::LowerCaseEqualsASCII(trimmed, "sameorigin"))
+ current = mojom::XFrameOptionsValue::kSameOrigin;
+
+ if (result == mojom::XFrameOptionsValue::kNone)
+ result = current;
+ else if (result != current)
+ result = mojom::XFrameOptionsValue::kConflict;
+ }
+
+ return result;
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/x_frame_options_parser.h b/chromium/services/network/public/cpp/x_frame_options_parser.h
new file mode 100644
index 00000000000..793c0651584
--- /dev/null
+++ b/chromium/services/network/public/cpp/x_frame_options_parser.h
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_X_FRAME_OPTIONS_PARSER_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_X_FRAME_OPTIONS_PARSER_H_
+
+#include "base/component_export.h"
+#include "services/network/public/mojom/x_frame_options.mojom-forward.h"
+
+namespace net {
+class HttpResponseHeaders;
+}
+
+namespace network {
+
+COMPONENT_EXPORT(NETWORK_CPP)
+mojom::XFrameOptionsValue ParseXFrameOptions(const net::HttpResponseHeaders&);
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_X_FRAME_OPTIONS_PARSER_H_
diff --git a/chromium/services/network/public/cpp/x_frame_options_parser_fuzzer.cc b/chromium/services/network/public/cpp/x_frame_options_parser_fuzzer.cc
new file mode 100644
index 00000000000..234f673aa43
--- /dev/null
+++ b/chromium/services/network/public/cpp/x_frame_options_parser_fuzzer.cc
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/x_frame_options_parser.h"
+
+#include <string>
+#include "net/http/http_response_headers.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ const std::string test_data(reinterpret_cast<const char*>(data), size);
+ std::string header_string("HTTP/1.1 200 OK\nX-Frame-Options: ");
+ header_string += test_data;
+ header_string += "\n\n";
+
+ std::replace(header_string.begin(), header_string.end(), '\n', '\0');
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ new net::HttpResponseHeaders(header_string);
+
+ network::ParseXFrameOptions(*headers);
+ return 0;
+}
diff --git a/chromium/services/network/public/cpp/x_frame_options_parser_unittest.cc b/chromium/services/network/public/cpp/x_frame_options_parser_unittest.cc
new file mode 100644
index 00000000000..bad0364383a
--- /dev/null
+++ b/chromium/services/network/public/cpp/x_frame_options_parser_unittest.cc
@@ -0,0 +1,81 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/x_frame_options_parser.h"
+
+#include <string>
+#include "net/http/http_response_headers.h"
+#include "services/network/public/mojom/x_frame_options.mojom-shared.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+net::HttpResponseHeaders* ConstructHeader(const char* value) {
+ std::string header_string("HTTP/1.1 200 OK");
+ if (value) {
+ header_string += "\nX-Frame-Options: ";
+ header_string += value;
+ }
+ header_string += "\n\n";
+
+ std::replace(header_string.begin(), header_string.end(), '\n', '\0');
+ net::HttpResponseHeaders* headers =
+ new net::HttpResponseHeaders(header_string);
+
+ return headers;
+}
+
+} // namespace
+
+namespace network {
+
+TEST(XFrameOptionsTest, Parse) {
+ struct TestCase {
+ const char* header;
+ mojom::XFrameOptionsValue expected;
+ } cases[] = {
+ // Single values:
+ {nullptr, mojom::XFrameOptionsValue::kNone},
+ {"DENY", mojom::XFrameOptionsValue::kDeny},
+ {"SAMEORIGIN", mojom::XFrameOptionsValue::kSameOrigin},
+ {"ALLOWALL", mojom::XFrameOptionsValue::kAllowAll},
+ {"NOT-A-VALUE", mojom::XFrameOptionsValue::kInvalid},
+ {"DeNy", mojom::XFrameOptionsValue::kDeny},
+ {"SaMeOrIgIn", mojom::XFrameOptionsValue::kSameOrigin},
+ {"AllOWaLL", mojom::XFrameOptionsValue::kAllowAll},
+
+ // Repeated values:
+ {"DENY,DENY", mojom::XFrameOptionsValue::kDeny},
+ {"SAMEORIGIN,SAMEORIGIN", mojom::XFrameOptionsValue::kSameOrigin},
+ {"ALLOWALL,ALLOWALL", mojom::XFrameOptionsValue::kAllowAll},
+ {"DENY,DeNy", mojom::XFrameOptionsValue::kDeny},
+ {"SAMEORIGIN,SaMeOrIgIn", mojom::XFrameOptionsValue::kSameOrigin},
+ {"ALLOWALL,AllOWaLL", mojom::XFrameOptionsValue::kAllowAll},
+ {"INVALID,INVALID", mojom::XFrameOptionsValue::kInvalid},
+ {"INVALID,DIFFERENTLY-INVALID", mojom::XFrameOptionsValue::kInvalid},
+
+ // Conflicting values:
+ {"ALLOWALL,DENY", mojom::XFrameOptionsValue::kConflict},
+ {"ALLOWALL,SAMEORIGIN", mojom::XFrameOptionsValue::kConflict},
+ {"ALLOWALL,INVALID", mojom::XFrameOptionsValue::kConflict},
+ {"DENY,ALLOWALL", mojom::XFrameOptionsValue::kConflict},
+ {"DENY,SAMEORIGIN", mojom::XFrameOptionsValue::kConflict},
+ {"DENY,INVALID", mojom::XFrameOptionsValue::kConflict},
+ {"SAMEORIGIN,ALLOWALL", mojom::XFrameOptionsValue::kConflict},
+ {"SAMEORIGIN,DENY", mojom::XFrameOptionsValue::kConflict},
+ {"SAMEORIGIN,INVALID", mojom::XFrameOptionsValue::kConflict},
+ {"INVALID,DENY", mojom::XFrameOptionsValue::kConflict},
+ {"INVALID,SAMEORIGIN", mojom::XFrameOptionsValue::kConflict},
+ {"INVALID,ALLOWALL", mojom::XFrameOptionsValue::kConflict},
+ };
+
+ for (const auto& test : cases) {
+ SCOPED_TRACE(test.header);
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ ConstructHeader(test.header);
+ EXPECT_EQ(test.expected, ParseXFrameOptions(*headers));
+ }
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/mojom/BUILD.gn b/chromium/services/network/public/mojom/BUILD.gn
index ada2742a9a1..e36a90c3cc0 100644
--- a/chromium/services/network/public/mojom/BUILD.gn
+++ b/chromium/services/network/public/mojom/BUILD.gn
@@ -123,7 +123,10 @@ mojom("mojom_network_isolation_key") {
generate_java = true
sources = [ "network_isolation_key.mojom" ]
- public_deps = [ "//url/mojom:url_mojom_origin" ]
+ public_deps = [
+ ":mojom_schemeful_site",
+ "//url/mojom:url_mojom_origin",
+ ]
if (!is_ios) {
export_class_attribute_blink = "BLINK_PLATFORM_EXPORT"
@@ -153,6 +156,7 @@ mojom("mojom_network_isolation_key") {
mojom("url_loader_base") {
generate_java = true
sources = [
+ "auth_and_certificate_observer.mojom",
"chunked_data_pipe_getter.mojom",
"client_security_state.mojom",
"cross_origin_embedder_policy.mojom",
@@ -162,9 +166,11 @@ mojom("url_loader_base") {
"mutable_network_traffic_annotation_tag.mojom",
"mutable_partial_network_traffic_annotation_tag.mojom",
"trust_tokens.mojom",
+ "web_bundle_handle.mojom",
]
public_deps = [
+ ":mojom_network_param",
"//mojo/public/mojom/base",
"//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
@@ -247,19 +253,12 @@ mojom("mojom_schemeful_site") {
]
}
-# This target is split from "mojom" target as the lazy serialization may
-# cause problems. See https://crbug.com/822732.
-mojom("websocket_mojom") {
+mojom("mojom_network_param") {
generate_java = true
- sources = [
- "network_param.mojom",
- "websocket.mojom",
- ]
+ sources = [ "network_param.mojom" ]
public_deps = [
- ":mojom_ip_address",
"//mojo/public/mojom/base",
- "//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
]
@@ -269,13 +268,25 @@ mojom("websocket_mojom") {
export_header_blink = "third_party/blink/public/platform/web_common.h"
}
- cpp_typemaps = [
+ # Typemaps which apply to both Blink and non-Blink bindings.
+ shared_cpp_typemaps = [
{
types = [
{
mojom = "network.mojom.AuthChallengeInfo"
cpp = "::net::AuthChallengeInfo"
},
+ ]
+ traits_headers =
+ [ "//services/network/public/cpp/network_param_mojom_traits.h" ]
+ traits_public_deps =
+ [ "//services/network/public/cpp:network_param_mojom_support" ]
+ },
+ ]
+
+ cpp_typemaps = [
+ {
+ types = [
{
mojom = "network.mojom.AuthCredentials"
cpp = "::net::AuthCredentials"
@@ -320,15 +331,34 @@ mojom("websocket_mojom") {
"//services/network/public/cpp/net_ipc_param_traits.h",
"//services/network/public/cpp/network_param_mojom_traits.h",
]
- traits_sources =
- [ "//services/network/public/cpp/network_param_mojom_traits.cc" ]
- traits_public_deps = [
- "//ipc",
- "//net",
- "//services/network/public/cpp:cpp_base",
- ]
+ traits_public_deps =
+ [ "//services/network/public/cpp:network_param_mojom_support" ]
},
]
+ cpp_typemaps += shared_cpp_typemaps
+ blink_cpp_typemaps = []
+ blink_cpp_typemaps += shared_cpp_typemaps
+}
+
+# This target is split from "mojom" target as the lazy serialization may
+# cause problems. See https://crbug.com/822732.
+mojom("websocket_mojom") {
+ generate_java = true
+ sources = [ "websocket.mojom" ]
+
+ if (!is_ios) {
+ export_class_attribute_blink = "BLINK_PLATFORM_EXPORT"
+ export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1"
+ export_header_blink = "third_party/blink/public/platform/web_common.h"
+ }
+
+ public_deps = [
+ ":mojom_ip_address",
+ ":mojom_network_param",
+ "//mojo/public/mojom/base",
+ "//url/mojom:url_mojom_gurl",
+ "//url/mojom:url_mojom_origin",
+ ]
}
mojom("cookies_mojom") {
@@ -511,12 +541,14 @@ mojom("mojom") {
"url_response_head.mojom",
"web_client_hints_types.mojom",
"web_sandbox_flags.mojom",
+ "x_frame_options.mojom",
]
public_deps = [
":cookies_mojom",
":mojom_ip_address",
":mojom_network_isolation_key",
+ ":mojom_network_param",
":mojom_schemeful_site",
":url_loader_base",
":websocket_mojom",
@@ -545,11 +577,11 @@ mojom("mojom") {
# This is only needed on desktop linux, but the defines make this difficult
# because IS_CHROMECAST is not available in build/build_config.h.
- if (is_linux || is_lacros) {
+ if (is_linux || is_chromeos_lacros) {
enabled_features += [ "needs_crypt_config" ]
}
- if (is_android || is_ash) {
+ if (is_android || is_chromeos_ash) {
enabled_features += [ "network_change_notifier_in_browser" ]
}
@@ -580,6 +612,10 @@ mojom("mojom") {
cpp = "::network::ResourceRequest::TrustedParams"
},
{
+ mojom = "network.mojom.WebBundleTokenParams"
+ cpp = "::network::ResourceRequest::WebBundleTokenParams"
+ },
+ {
mojom = "network.mojom.URLRequest"
cpp = "::network::ResourceRequest"
},
@@ -598,6 +634,26 @@ mojom("mojom") {
cpp = "::net::RequestPriority"
},
{
+ mojom = "network.mojom.DataElementBytes"
+ cpp = "::network::DataElementBytes"
+ move_only = true
+ },
+ {
+ mojom = "network.mojom.DataElementDataPipe"
+ cpp = "::network::DataElementDataPipe"
+ move_only = true
+ },
+ {
+ mojom = "network.mojom.DataElementChunkedDataPipe"
+ cpp = "::network::DataElementChunkedDataPipe"
+ move_only = true
+ },
+ {
+ mojom = "network.mojom.DataElementFile"
+ cpp = "::network::DataElementFile"
+ move_only = true
+ },
+ {
mojom = "network.mojom.DataElement"
cpp = "::network::DataElement"
move_only = true
diff --git a/chromium/services/network/public/mojom/address_list.mojom b/chromium/services/network/public/mojom/address_list.mojom
index 9af17c47bd2..ca4b8394437 100644
--- a/chromium/services/network/public/mojom/address_list.mojom
+++ b/chromium/services/network/public/mojom/address_list.mojom
@@ -9,5 +9,8 @@ import "services/network/public/mojom/ip_endpoint.mojom";
// Mirror of net::AddressList.
struct AddressList {
array<IPEndPoint> addresses;
- string canonical_name;
+ // The first entry of `dns_aliases`, if it exists, is the canonical name.
+ // The alias chain is preserved in reverse order, from canonical name (i.e.
+ // address record name) through to query name.
+ array<string> dns_aliases;
};
diff --git a/chromium/services/network/public/mojom/auth_and_certificate_observer.mojom b/chromium/services/network/public/mojom/auth_and_certificate_observer.mojom
new file mode 100644
index 00000000000..0192f6b3cf6
--- /dev/null
+++ b/chromium/services/network/public/mojom/auth_and_certificate_observer.mojom
@@ -0,0 +1,120 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module network.mojom;
+
+import "mojo/public/mojom/base/unguessable_token.mojom";
+import "services/network/public/mojom/network_param.mojom";
+import "url/mojom/url.mojom";
+
+// This interface enables the UI to send client certificate selections back to
+// the network service.
+//
+// Defining an interface for this purpose, rather than using a union in the
+// response of OnCertificateRequested, enables the NetworkServiceClient to learn
+// of the URLLoader destruction via the connection error handler.
+interface ClientCertificateResponder {
+ // Use the selected certificate and continue the URLRequest.
+ //
+ // - |provider_name| corresponds to the return value of
+ // net::SSLPrivateKey::GetProviderName().
+ // - |algorithm_preferences| corresponds to the return value of
+ // net::SSLPrivateKey::GetAlgorithmPreferences().
+ ContinueWithCertificate(network.mojom.X509Certificate x509_certificate,
+ string provider_name,
+ array<uint16> algorithm_preferences,
+ pending_remote<SSLPrivateKey> ssl_private_key);
+
+ // Affirmatively select no certificate (this is cached and can affect future
+ // URLRequests). Does not cancel the URLRequest.
+ //
+ // The connection is continued with no client cert.
+ // net::URLRequest::ContinueWithCertificate(nullptr, nullptr) needs to be
+ // called.
+ ContinueWithoutCertificate();
+
+ // Cancel the URLRequest. The request is aborted.
+ // net::URLRequest::CancelWithError() needs to be called.
+ CancelRequest();
+};
+
+// The content/browser implementation of this SSLPrivateKey interface wraps the
+// scoped_refptr<net::SSLPrivateKey> that is received from
+// SSLClientAuthDelegate::ContinueWithCertificate(), and this mojo interface is
+// sent from content/browser to services/network so that services/network can
+// have its own net::SSLPrivateKey implementation that internally uses this mojo
+// interface.
+// The |algorithm| and |input| parameters correspond to the |algorithm| and
+// |input| parameters in net::SSLPrivateKey::Sign().
+// The |net_error| and |signature| parameters correspond to the parameters in
+// net::SSLPrivateKey::SignCallback.
+interface SSLPrivateKey {
+ // Sign |input| using the private key and |algorithm|.
+ Sign(uint16 algorithm,
+ array<uint8> input) => (int32 net_error, array<uint8> signature);
+};
+
+// The |credentials| output parameter is given to URLRequest::SetAuth()
+// through this mojo interface. It is not set when URLRequest::CancelAuth()
+// needs to be called.
+interface AuthChallengeResponder {
+ // Called in response to an authentication request. See
+ // AuthenticationAndCertificateObserver::OnAuthRequired.
+ OnAuthCredentials(AuthCredentials? credentials);
+};
+
+// This interface is used by an URLLoaderFactory to provide notification
+// of authentication and certificate events. This is typically implemented
+// by a trusted process such as the browser process.
+interface AuthenticationAndCertificateObserver {
+ // Called when an SSL certificate is encountered.
+ // The callback argument is a net::ERROR value. If it's net::OK, then the
+ // request is resumed. Otherwise it's cancelled with the given error.
+ OnSSLCertificateError(url.mojom.Url url,
+ int32 net_error,
+ SSLInfo ssl_info,
+ bool fatal) => (int32 net_error);
+
+ // Called when an SSL certificate requested message is received for client
+ // authentication.
+ //
+ // Rather than using one response for multiple purposes, the caller expects
+ // exactly one response (or disconnect) to be sent back via |cert_responder|.
+ //
+ // |window_id| indicates the frame making the request, see
+ // network::ResourceRequest::fetch_window_id. This parameter is only set
+ // when the request is from a service worker to identify the origin window.
+ // The is not needed for frame based requests because they have their own
+ // URLLoaderFactory and a unique AuthenticationAndCertificateObserver for each
+ // frame.
+ OnCertificateRequested(
+ mojo_base.mojom.UnguessableToken? window_id,
+ network.mojom.SSLCertRequestInfo cert_info,
+ pending_remote<ClientCertificateResponder> cert_responder);
+
+ // Called when we receive an authentication failure.
+ // The |auth_challenge_responder| will respond to auth challenge with
+ // credentials. |head_headers| can provide response headers for the response
+ // which has elicited this auth request, if applicable.
+ //
+ // |window_id| indicates the frame making the request, see
+ // network::ResourceRequest::fetch_window_id. This parameter is only set
+ // when the request is from a service worker to identify the origin window.
+ // The is not needed for frame based requests because they have their own
+ // URLLoaderFactory and a unique AuthenticationAndCertificateObserver for each
+ // frame.
+ OnAuthRequired(
+ mojo_base.mojom.UnguessableToken? window_id,
+ uint32 request_id,
+ url.mojom.Url url,
+ bool first_auth_attempt,
+ AuthChallengeInfo auth_info,
+ HttpResponseHeaders? head_headers,
+ pending_remote<AuthChallengeResponder> auth_challenge_responder);
+
+ // Used by the NetworkService to create a copy of this observer.
+ // (e.g. when creating an observer for URLLoader from URLLoaderFactory's
+ // observer).
+ Clone(pending_receiver<AuthenticationAndCertificateObserver> listener);
+}; \ No newline at end of file
diff --git a/chromium/services/network/public/mojom/client_security_state.mojom b/chromium/services/network/public/mojom/client_security_state.mojom
index 283446a3fcb..38c70befdfc 100644
--- a/chromium/services/network/public/mojom/client_security_state.mojom
+++ b/chromium/services/network/public/mojom/client_security_state.mojom
@@ -20,6 +20,10 @@ enum PrivateNetworkRequestPolicy {
// Forbid requests to more-private address spaces than that of the initiator,
// when the initiator is not in a secure context.
kBlockFromInsecureToMorePrivate,
+
+ // Warn about requests to more-private address spaces than that of the
+ // initiator when the initiator is not in a secure context.
+ kWarnFromInsecureToMorePrivate,
};
struct ClientSecurityState {
diff --git a/chromium/services/network/public/mojom/content_security_policy.mojom b/chromium/services/network/public/mojom/content_security_policy.mojom
index 1651aaecc6e..4f41490b5c9 100644
--- a/chromium/services/network/public/mojom/content_security_policy.mojom
+++ b/chromium/services/network/public/mojom/content_security_policy.mojom
@@ -64,14 +64,15 @@ struct CSPSource {
};
enum CSPHashAlgorithm {
- SHA256,
- SHA384,
- SHA512,
+ None = 0,
+ SHA256 = 1,
+ SHA384 = 2,
+ SHA512 = 4,
};
struct CSPHashSource {
CSPHashAlgorithm algorithm;
- string value;
+ array<uint8> value;
};
struct CSPSourceList {
@@ -109,7 +110,6 @@ enum CSPDirectiveName {
MediaSrc,
NavigateTo,
ObjectSrc,
- PluginTypes,
PrefetchSrc,
ReportTo,
ReportURI,
@@ -127,7 +127,35 @@ enum CSPDirectiveName {
WorkerSrc,
};
+enum CSPRequireTrustedTypesFor {
+ None = 0,
+ Script = 1,
+};
+
+// The parsed value of the CSP directive 'trusted-types'.
+// https://w3c.github.io/webappsec-trusted-types/dist/spec/#trusted-types-csp-directive
+struct CSPTrustedTypes {
+ // The list of policies allowed by the 'trusted-types' directive.
+ array<string> list;
+
+ // This is true if the directive value contains the wildcard * (meaning all
+ // policy names are allowed).
+ bool allow_any = false;
+
+ // This is true if the directive value contains the keyword 'allow-duplicates'
+ // (which allows creating policies with a name that was already used).
+ bool allow_duplicates = false;
+};
+
struct ContentSecurityPolicy {
+ // The origin used for matching the 'self' keyword.
+ // https://w3c.github.io/webappsec-csp/#framework-policy
+ CSPSource self_origin;
+
+ // The raw, unparsed values of the specified CSP directives. Needed for
+ // reporting.
+ map<CSPDirectiveName, string> raw_directives;
+
map<CSPDirectiveName, CSPSourceList> directives;
// Spec: https://www.w3.org/TR/upgrade-insecure-requests/
@@ -141,6 +169,9 @@ struct ContentSecurityPolicy {
// https://wicg.github.io/cors-rfc1918/#csp
bool treat_as_public_address = false;
+ // https://www.w3.org/TR/mixed-content/#strict-opt-in
+ bool block_all_mixed_content = false;
+
// https://www.w3.org/TR/CSP3/#directive-sandbox
// This uses the convention: kNone means "nothing is disallowed".
WebSandboxFlags sandbox = WebSandboxFlags.kNone;
@@ -154,11 +185,18 @@ struct ContentSecurityPolicy {
// Set of reporting endpoints to which violation reports are sent.
array<string> report_endpoints;
- // Plugin types specified by the CSP. If `null`, no plugin-types directive is
- // specified and hence all types are allowed. If an empty array, then the
- // plugin-types directive is specified with no types, hence no types are
- // allowed.
- array<string>? plugin_types;
+ // The parsed value of the directive 'require-trusted-types-for'.
+ // https://w3c.github.io/webappsec-trusted-types/dist/spec/#require-trusted-types-for-csp-directive
+ CSPRequireTrustedTypesFor require_trusted_types_for =
+ CSPRequireTrustedTypesFor.None;
+
+ // The parsed value of the directive 'trusted-types'.
+ // https://w3c.github.io/webappsec-trusted-types/dist/spec/#trusted-types-csp-directive
+ // Note: If this is null, the directive was not present. On the other side, if
+ // this is a default CSPTrustedTypes struct with empty list, it means that the
+ // directive was present with empty value, so policies may not be created and
+ // no DOM XSS injection sinks can be used at all.
+ CSPTrustedTypes? trusted_types;
// An array containing a set of errors occurred while parsing the CSP header.
array<string> parsing_errors;
diff --git a/chromium/services/network/public/mojom/cookie_access_observer.mojom b/chromium/services/network/public/mojom/cookie_access_observer.mojom
index 04dc1ae40b2..b151023fae6 100644
--- a/chromium/services/network/public/mojom/cookie_access_observer.mojom
+++ b/chromium/services/network/public/mojom/cookie_access_observer.mojom
@@ -23,7 +23,12 @@ struct CookieAccessDetails {
url.mojom.Url url;
SiteForCookies site_for_cookies;
- array<CookieWithAccessResult> cookie_list;
+ // Each element of the `cookie_list` array includes a CookieInclusionStatus
+ // and a CanonicalCookie if one was successfully constructed; if we were
+ // unable to create the CanonicalCookie, then we use the cookie string
+ // instead. Note that this means we always get a CanonicalCookie for reads,
+ // but may get a cookie string on writes.
+ array<CookieOrLineWithAccessResult> cookie_list;
// |devtools_request_id| contains the DevTools request id of the request
// that triggered the cookie change, if the read was triggered by a request.
diff --git a/chromium/services/network/public/mojom/cookie_manager.mojom b/chromium/services/network/public/mojom/cookie_manager.mojom
index c95b843fc7f..3efaabbf59b 100644
--- a/chromium/services/network/public/mojom/cookie_manager.mojom
+++ b/chromium/services/network/public/mojom/cookie_manager.mojom
@@ -6,7 +6,6 @@ module network.mojom;
import "components/content_settings/core/common/content_settings.mojom";
import "mojo/public/mojom/base/time.mojom";
-import "services/network/public/mojom/schemeful_site.mojom";
import "url/mojom/url.mojom";
// Parameters for constructing a cookie manager.
@@ -52,6 +51,8 @@ enum CookieAccessDelegateType {
USE_CONTENT_SETTINGS,
// Always returns Legacy access semantics.
ALWAYS_LEGACY,
+ // Always returns Non-Legacy access semantics.
+ ALWAYS_NONLEGACY,
};
enum CookiePriority {
@@ -100,6 +101,16 @@ struct CookieSameSiteContext {
ContextType schemeful_context = CROSS_SITE;
};
+// Computed for every cookie access attempt but is only relevant for SameParty
+// cookies.
+enum SamePartyCookieContextType {
+ // The opposite to kSameParty. Should be the default value.
+ kCrossParty,
+ // If the request URL is in the same First-Party Sets as the top-frame site
+ // and each member of the isolation_info.party_context.
+ kSameParty,
+};
+
// What rules to apply when determining whether access to a particular cookie is
// allowed.
// Keep in sync with net/cookies/cookie_constants.h.
@@ -115,7 +126,12 @@ struct CookieOptions {
CookieSameSiteContext same_site_cookie_context;
bool update_access_time = true;
bool return_excluded_cookies = false;
- array<SchemefulSite>? full_party_context;
+ SamePartyCookieContextType same_party_cookie_context_type = kCrossParty;
+ // The size of the isolation_info.party_context plus the top-frame site for
+ // logging purposes.
+ uint32 full_party_context_size = 0;
+ // Whether the site is a member of a nontrivial First-Party Set.
+ bool is_in_nontrivial_first_party_set = false;
};
// See net/cookies/canonical_cookie.{h,cc} for documentation.
@@ -154,10 +170,22 @@ struct CookieAndLineWithAccessResult {
CookieAccessResult access_result;
};
+union CookieOrLine {
+ CanonicalCookie cookie;
+ string cookie_string;
+};
+
+struct CookieOrLineWithAccessResult {
+ CookieOrLine cookie_or_line;
+ CookieAccessResult access_result;
+};
+
+// See net/cookies/cookie_access_result.{cc,h} for documentation.
struct CookieAccessResult {
CookieEffectiveSameSite effective_same_site;
CookieAccessSemantics access_semantics;
CookieInclusionStatus status;
+ bool is_allowed_to_access_secure_cookies;
};
struct CookieWithAccessResult {
diff --git a/chromium/services/network/public/mojom/fetch_api.mojom b/chromium/services/network/public/mojom/fetch_api.mojom
index 8b3f2f16df1..c65304ac830 100644
--- a/chromium/services/network/public/mojom/fetch_api.mojom
+++ b/chromium/services/network/public/mojom/fetch_api.mojom
@@ -27,28 +27,39 @@ enum RequestMode {
//
// Note: if destination is kDocument it should be a main
// resource request for main frames, except for Portals cases.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
enum RequestDestination {
- kEmpty,
- kAudio,
- kAudioWorklet,
- kDocument,
- kEmbed,
- kFont,
- kFrame,
- kIframe,
- kImage,
- kManifest,
- kObject,
- kPaintWorklet,
- kReport,
- kScript,
- kServiceWorker,
- kSharedWorker,
- kStyle,
- kTrack,
- kVideo,
- kWorker,
- kXslt,
+ kEmpty = 0,
+ kAudio = 1,
+ kAudioWorklet = 2,
+ kDocument = 3,
+ kEmbed = 4,
+ kFont = 5,
+ kFrame = 6,
+ kIframe = 7,
+ kImage = 8,
+ kManifest = 9,
+ kObject = 10,
+ kPaintWorklet = 11,
+ kReport = 12,
+ kScript = 13,
+ kServiceWorker = 14,
+ kSharedWorker = 15,
+ kStyle = 16,
+ kTrack = 17,
+ kVideo = 18,
+ // kWebBundle represents a request for a WebBundle. A <link> element whose
+ // rel is "webbundle" uses this destination.
+ //
+ // e.g. <link rel=webbundle href="example.com/foo.wbn" resources="...">
+ //
+ // Fetch specifiction does not define this destination yet.
+ // Tracking issue: https://github.com/whatwg/fetch/issues/1120
+ kWebBundle = 19,
+ kWorker = 20,
+ kXslt = 21,
};
// Corresponds to Fetch request's "redirect mode":
diff --git a/chromium/services/network/public/mojom/isolation_info.mojom b/chromium/services/network/public/mojom/isolation_info.mojom
index cc2571066b6..575d016c90c 100644
--- a/chromium/services/network/public/mojom/isolation_info.mojom
+++ b/chromium/services/network/public/mojom/isolation_info.mojom
@@ -5,6 +5,7 @@
module network.mojom;
import "services/network/public/mojom/site_for_cookies.mojom";
+import "services/network/public/mojom/schemeful_site.mojom";
import "url/mojom/origin.mojom";
// Mapped to net::IsolationInfo::RequestType, which is what consumers should
@@ -24,4 +25,5 @@ struct IsolationInfo {
url.mojom.Origin? frame_origin;
bool opaque_and_non_transient;
SiteForCookies site_for_cookies;
+ array<SchemefulSite>? party_context;
};
diff --git a/chromium/services/network/public/mojom/load_timing_info.mojom b/chromium/services/network/public/mojom/load_timing_info.mojom
index c8a6db8697e..a9a1b50be63 100644
--- a/chromium/services/network/public/mojom/load_timing_info.mojom
+++ b/chromium/services/network/public/mojom/load_timing_info.mojom
@@ -29,6 +29,7 @@ struct LoadTimingInfo {
mojo_base.mojom.TimeTicks send_end;
mojo_base.mojom.TimeTicks receive_headers_start;
mojo_base.mojom.TimeTicks receive_headers_end;
+ mojo_base.mojom.TimeTicks receive_non_informational_headers_start;
mojo_base.mojom.TimeTicks first_early_hints_time;
mojo_base.mojom.TimeTicks push_start;
mojo_base.mojom.TimeTicks push_end;
diff --git a/chromium/services/network/public/mojom/network_context.mojom b/chromium/services/network/public/mojom/network_context.mojom
index 0a09398cf50..5aca8515f5c 100644
--- a/chromium/services/network/public/mojom/network_context.mojom
+++ b/chromium/services/network/public/mojom/network_context.mojom
@@ -11,6 +11,7 @@ import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "mojo/public/mojom/base/values.mojom";
import "services/network/public/mojom/address_list.mojom";
+import "services/network/public/mojom/auth_and_certificate_observer.mojom";
import "services/network/public/mojom/cert_verifier_service.mojom";
import "services/network/public/mojom/client_security_state.mojom";
import "services/network/public/mojom/cookie_access_observer.mojom";
@@ -58,9 +59,6 @@ import "services/network/public/mojom/dhcp_wpad_url_client.mojom";
[EnableIf=is_ct_supported]
import "services/network/public/mojom/ct_log_info.mojom";
-[EnableIf=is_trial_comparison_cert_verifier_supported]
-import "services/network/public/mojom/trial_comparison_cert_verifier.mojom";
-
const uint32 kWebSocketOptionNone = 0;
// Disallow the request from sending cookies. Disallow the response from writing
// cookies.
@@ -73,9 +71,7 @@ const uint32 kWebSocketOptionBlockThirdPartyCookies = 2;
// The browser can provide a CustomProxyConfig to a CustomProxyConfigClient
// running in the network service. The network service will use the given proxy
// configuration if a request matches the proxy rules and all the other
-// criteria contained within it. This configuration allows the browser to
-// direct the network service to set headers on requests to the given proxies
-// before and/or after the caching layer.
+// criteria contained within it.
struct CustomProxyConfig {
// The custom proxy rules to use. Note that ftp:// requests are not
// supported.
@@ -97,32 +93,19 @@ struct CustomProxyConfig {
HttpRequestHeaders connect_tunnel_headers;
};
-// Parameters to specify how the net::CertVerifier and net::CertVerifyProc
-// objects should be instantiated.
-struct CertVerifierCreationParams {
- // Specifies the path to the directory where NSS will store its database.
- [EnableIf=is_chromeos]
- mojo_base.mojom.FilePath? nss_path;
-
- // This is used in combination with nss_path, to ensure that the NSS database
- // isn't opened multiple times for NetworkContexts in the same profie.
- [EnableIf=is_chromeos]
- string username_hash;
-
- // Specifies which cert verifier implementation to use.
- // kDefault - Decided by base::Feature
- // kBuiltin - Use CertVerifyProcBuiltin
- // kSystem - Use the system CertVerifyProc implementation
- [EnableIf=is_builtin_cert_verifier_feature_supported]
- enum CertVerifierImpl {kDefault, kBuiltin, kSystem};
- [EnableIf=is_builtin_cert_verifier_feature_supported]
- CertVerifierImpl use_builtin_cert_verifier = kDefault;
-
- // Parameters for the cert verifier comparison trial. This is a temporary
- // interface and embedders should not use it.
- // See https://crbug.com/649026
- [EnableIf=is_trial_comparison_cert_verifier_supported]
- TrialComparisonCertVerifierParams? trial_comparison_cert_verifier_params;
+// Observer of custom proxy connections, especially for when errors occur.
+interface CustomProxyConnectionObserver {
+ // Called when use of |bad_proxy| fails due to |net_error|. |net_error| is the
+ // network error encountered, if any, and OK if the fallback was for a reason
+ // other than a network error (e.g. the proxy service was explicitly directed
+ // to skip a proxy).
+ OnFallback(proxy_resolver.mojom.ProxyServer bad_proxy, int32 net_error);
+
+ // Called when the response headers for the proxy tunnel request have been
+ // received.
+ OnTunnelHeadersReceived(
+ proxy_resolver.mojom.ProxyServer proxy_server,
+ HttpResponseHeaders response_headers);
};
// Includes a pipe to a CertVerifierService for usage by the
@@ -133,13 +116,6 @@ struct CertVerifierServiceRemoteParams {
cert_verifier_service;
};
-// Contains the parameters necessary to either connect to a CertVerifierService
-// or create a net::CertVerifier in the network service itself.
-union CertVerifierParams {
- CertVerifierServiceRemoteParams remote_params;
- CertVerifierCreationParams creation_params;
-};
-
// Client to update the custom proxy config.
interface CustomProxyConfigClient {
OnCustomProxyConfigUpdated(CustomProxyConfig proxy_config);
@@ -335,6 +311,12 @@ struct NetworkContextParams {
pending_receiver<CustomProxyConfigClient>?
custom_proxy_config_client_receiver;
+ // If |initial_custom_proxy_config| or |custom_proxy_config_client_receiver|
+ // is set, information about custom proxy connections will be reported to this
+ // observer.
+ pending_remote<CustomProxyConnectionObserver>?
+ custom_proxy_connection_observer_remote;
+
// If |proxy_config_client_request| is non-null, this is called during
// periods of network activity, and can be used as a signal for polling-based
// logic to determine the proxy config.
@@ -398,9 +380,8 @@ struct NetworkContextParams {
[EnableIf=is_ct_supported]
mojo_base.mojom.Time ct_log_update_time;
- // Contains either a pipe to a CertVerifierService, or parameters used to
- // instantiate a net::CertVerifier in-process.
- CertVerifierParams? cert_verifier_params;
+ // Contains a pipe to a CertVerifierService.
+ CertVerifierServiceRemoteParams cert_verifier_params;
// Initial additional certificates that will be used for certificate
// validation.
@@ -630,11 +611,6 @@ struct URLLoaderFactoryParams {
// impact because of the extra process hops, so use should be minimized.
pending_remote<TrustedURLLoaderHeaderClient>? header_client;
- // |factory_bound_access_patterns| are used for CORS checks in addition to
- // the per-context allow patterns that is managed via NetworkContext
- // interface. This still respects the per-context block lists.
- CorsOriginAccessPatterns? factory_bound_access_patterns;
-
// Information used restrict access to identity information (like SameSite
// cookies) and to shard network resources, like the cache. If set, takes
// precedence over ResourceRequest::TrustedParams::IsolationInfo field
@@ -675,6 +651,9 @@ struct URLLoaderFactoryParams {
// Used to notify clients about cookie reads or writes.
pending_remote<CookieAccessObserver>? cookie_observer;
+ // Used to notify clients about authentication and certificate events.
+ pending_remote<AuthenticationAndCertificateObserver>? auth_cert_observer;
+
// If this equals kForbid, the context to which this loader is bound does not
// allow any Trust Tokens (https://github.com/wicg/trust-token-api)
// redemption or signing operations.
@@ -697,59 +676,10 @@ struct URLLoaderFactoryParams {
// trusted source, it would be good to set this depending on the headers'
// values, too.
TrustTokenRedemptionPolicy trust_token_redemption_policy = kPotentiallyPermit;
-};
-
-// The |credentials| output parameter is given to URLRequest::SetAuth()
-// through this mojo interface. It is not set when URLRequest::CancelAuth()
-// needs to be called.
-interface AuthChallengeResponder {
- OnAuthCredentials(AuthCredentials? credentials);
-};
-
-// This interface enables the UI to send client certificate selections back to
-// the network service.
-//
-// Defining an interface for this purpose, rather than using a union in the
-// response of OnCertificateRequested, enables the NetworkServiceClient to learn
-// of the URLLoader destruction via the connection error handler.
-interface ClientCertificateResponder {
- // Use the selected certificate and continue the URLRequest.
- //
- // - |provider_name| corresponds to the return value of
- // net::SSLPrivateKey::GetProviderName().
- // - |algorithm_preferences| corresponds to the return value of
- // net::SSLPrivateKey::GetAlgorithmPreferences().
- ContinueWithCertificate(network.mojom.X509Certificate x509_certificate,
- string provider_name,
- array<uint16> algorithm_preferences,
- pending_remote<SSLPrivateKey> ssl_private_key);
-
- // Affirmatively select no certificate (this is cached and can affect future
- // URLRequests). Does not cancel the URLRequest.
- //
- // The connection is continued with no client cert.
- // net::URLRequest::ContinueWithCertificate(nullptr, nullptr) needs to be
- // called.
- ContinueWithoutCertificate();
-
- // Cancel the URLRequest. The request is aborted.
- // net::URLRequest::CancelWithError() needs to be called.
- CancelRequest();
-};
-// The content/browser implementation of this SSLPrivateKey interface wraps the
-// scoped_refptr<net::SSLPrivateKey> that is received from
-// SSLClientAuthDelegate::ContinueWithCertificate(), and this mojo interface is
-// sent from content/browser to services/network so that services/network can
-// have its own net::SSLPrivateKey implementation that internally uses this mojo
-// interface.
-// The |algorithm| and |input| parameters correspond to the |algorithm| and
-// |input| parameters in net::SSLPrivateKey::Sign().
-// The |net_error| and |signature| parameters correspond to the parameters in
-// net::SSLPrivateKey::SignCallback.
-interface SSLPrivateKey {
- Sign(uint16 algorithm,
- array<uint8> input) => (int32 net_error, array<uint8> signature);
+ // TODO(lukasza): https://crbug.com/1151008: Consider removing this
+ // diagnostic aid once the bug is understood.
+ string debug_tag = "";
};
// Callback interface for NetworkContext when routing identifiers aren't
@@ -758,51 +688,6 @@ interface SSLPrivateKey {
//
// Implemented by the browser process.
interface NetworkContextClient {
- // Called when we receive an authentication failure.
- // The |auth_challenge_responder| will respond to auth challenge with
- // credentials. |head| can provide response headers for the response
- // which has elicited this auth request, if applicable.
- //
- // |window_id| or else |process_id| and |routing_id| indicates
- // the frame making the request, see
- // network::ResourceRequest::fetch_window_id.
- OnAuthRequired(
- mojo_base.mojom.UnguessableToken? window_id,
- int32 process_id,
- int32 routing_id,
- uint32 request_id,
- url.mojom.Url url,
- bool first_auth_attempt,
- AuthChallengeInfo auth_info,
- URLResponseHead? head,
- pending_remote<AuthChallengeResponder> auth_challenge_responder);
-
- // Called when an SSL certificate requested message is received for client
- // authentication.
- //
- // Rather than using one response for multiple purposes, the caller expects
- // exactly one response (or disconnect) to be sent back via |cert_responder|.
- //
- // |window_id| or else |process_id| and |routing_id| indicates the frame
- // making the request, see network::ResourceRequest::fetch_window_id.
- OnCertificateRequested(
- mojo_base.mojom.UnguessableToken? window_id,
- int32 process_id,
- int32 routing_id,
- uint32 request_id,
- network.mojom.SSLCertRequestInfo cert_info,
- pending_remote<ClientCertificateResponder> cert_responder);
-
- // Called when an SSL certificate is encountered.
- // The callback argument is a net::ERROR value. If it's net::OK, then the
- // request is resumed. Otherwise it's cancelled with the given error.
- OnSSLCertificateError(int32 process_id,
- int32 routing_id,
- url.mojom.Url url,
- int32 net_error,
- SSLInfo ssl_info,
- bool fatal) => (int32 net_error);
-
// Called when file uploading was requested.
// If the process that requested the uploads has permission to read all of
// the files referenced by |file_paths|, the callback arguments will be
@@ -884,12 +769,14 @@ interface NetworkContext {
// Gets a RestrictedCookieManager scoped to a given origin, and applying
// settings configured on the CookieManager associated with this domain.
//
- // |site_for_cookies| represents which domains (perhaps none) the cookie
- // manager should consider to be first-party, for purposes of SameSite cookies
- // and any third-party cookie blocking the embedder may implement.
+ // |origin| represents the domain for which the RestrictedCookieManager can
+ // access cookies. It could either be a frame origin when |role| is
+ // RestrictedCookieManagerRole::SCRIPT (a script scoped to a particular
+ // document's frame)), or a request origin when |role| is
+ // RestrictedCookieManagerRole::NETWORK (a network request).
//
- // |top_frame_origin| represents the domain for top-level frame, and can be
- // used to look up preferences that are dependent on that.
+ // |isolation_info| contains info for SameSite and SameParty cookie queries.
+ // Must be fully populated.
//
// If |role| == SCRIPT, this interface can be safely handed out to a process
// that is known to represent the given origin, such as a renderer process.
@@ -900,8 +787,7 @@ interface NetworkContext {
pending_receiver<RestrictedCookieManager> restricted_cookie_manager,
RestrictedCookieManagerRole role,
url.mojom.Origin origin,
- SiteForCookies site_for_cookies,
- url.mojom.Origin top_frame_origin,
+ IsolationInfo isolation_info,
pending_remote<CookieAccessObserver>? cookie_observer);
// Provides a HasTrustTokensAnswerer scoped to the given top-frame origin
@@ -928,6 +814,10 @@ interface NetworkContext {
// A null |filter| indicates that all Trust Tokens data should be cleared.
ClearTrustTokenData(ClearDataFilter? filter) => ();
+ // Returns the number of signed-but-not-spent Trust Tokens.
+ GetStoredTrustTokenCounts()
+ => (array<StoredTrustTokensForIssuer> tokens);
+
// Clears network objects with implicit URL history information. Data related
// to events that happened prior to |start_time| and after |end_time| may be
// retained. Only applies to network objects without more specific methods
@@ -1219,19 +1109,19 @@ interface NetworkContext {
// the connection is established, and due to message ordering uncertainty we
// cannot know what happened.
CreateWebSocket(
- url.mojom.Url url,
- array<string> requested_protocols,
- SiteForCookies site_for_cookies,
- IsolationInfo isolation_info,
- array<HttpHeader> additional_headers,
- int32 process_id,
- int32 render_frame_id,
- url.mojom.Origin origin,
- uint32 options,
- MutableNetworkTrafficAnnotationTag traffic_annotation,
- pending_remote<WebSocketHandshakeClient> handshake_client,
- pending_remote<AuthenticationHandler>? auth_handler,
- pending_remote<TrustedHeaderClient>? header_client);
+ url.mojom.Url url,
+ array<string> requested_protocols,
+ SiteForCookies site_for_cookies,
+ IsolationInfo isolation_info,
+ array<HttpHeader> additional_headers,
+ int32 process_id,
+ url.mojom.Origin origin,
+ uint32 options,
+ MutableNetworkTrafficAnnotationTag traffic_annotation,
+ pending_remote<WebSocketHandshakeClient> handshake_client,
+ pending_remote<AuthenticationAndCertificateObserver>? auth_cert_observer,
+ pending_remote<WebSocketAuthenticationHandler>? auth_handler,
+ pending_remote<TrustedHeaderClient>? header_client);
// Creates a QuicTransport connection to |url|. |origin| is used for the
// client indication - see
diff --git a/chromium/services/network/public/mojom/network_isolation_key.mojom b/chromium/services/network/public/mojom/network_isolation_key.mojom
index 9b85e28e681..0a26d119a7c 100644
--- a/chromium/services/network/public/mojom/network_isolation_key.mojom
+++ b/chromium/services/network/public/mojom/network_isolation_key.mojom
@@ -4,17 +4,14 @@
module network.mojom;
-import "url/mojom/origin.mojom";
+import "services/network/public/mojom/schemeful_site.mojom";
// Mapped to net::NetworkIsolationKey.
struct NetworkIsolationKey {
- // These are not true origins, but rather schemeful sites | origins, depending
- // on scheme.
- //
// Keeping optional to allow clients that do not populate top frame origin.
// TODO(crbug.com/910721): This will eventually always be populated.
- url.mojom.Origin? top_frame_site;
- url.mojom.Origin? frame_site;
+ SchemefulSite? top_frame_site;
+ SchemefulSite? frame_site;
bool opaque_and_non_transient;
};
diff --git a/chromium/services/network/public/mojom/network_param.mojom b/chromium/services/network/public/mojom/network_param.mojom
index 8f9f5d0be6f..8808e4cc963 100644
--- a/chromium/services/network/public/mojom/network_param.mojom
+++ b/chromium/services/network/public/mojom/network_param.mojom
@@ -4,8 +4,24 @@
module network.mojom;
-[Native]
-struct AuthChallengeInfo;
+import "url/mojom/origin.mojom";
+
+// Information related to an authentication challenge in an HTTP response.
+// Typemapped to net::AuthChallengeInfo.
+struct AuthChallengeInfo {
+ // True if the challenge was for proxy authentication.
+ bool is_proxy;
+ // The service issuing the challenge.
+ url.mojom.Origin challenger;
+ // The authentication scheme used, such as "basic" or "digest".
+ string scheme;
+ // The realm of the authentication challenge. May be empty.
+ string realm;
+ // The authentication challenge.
+ string challenge;
+ // The path on which authentication was requested.
+ string path;
+};
[Native]
struct AuthCredentials;
diff --git a/chromium/services/network/public/mojom/network_service.mojom b/chromium/services/network/public/mojom/network_service.mojom
index 0c7e1a852d1..2c1eddc5fc4 100644
--- a/chromium/services/network/public/mojom/network_service.mojom
+++ b/chromium/services/network/public/mojom/network_service.mojom
@@ -19,6 +19,7 @@ import "services/network/public/mojom/mutable_network_traffic_annotation_tag.moj
import "services/network/public/mojom/net_log.mojom";
import "services/network/public/mojom/network_change_manager.mojom";
import "services/network/public/mojom/network_context.mojom";
+import "services/network/public/mojom/ip_address_space.mojom";
import "services/network/public/mojom/network_interface.mojom";
import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/network_quality_estimator_manager.mojom";
@@ -27,6 +28,7 @@ import "services/network/public/mojom/trust_tokens.mojom";
import "services/network/public/mojom/url_loader.mojom";
import "services/network/public/mojom/url_loader_factory.mojom";
import "services/network/public/mojom/url_response_head.mojom";
+import "services/network/public/mojom/client_security_state.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
@@ -66,7 +68,8 @@ interface NetworkServiceClient {
int32 routing_id,
string devtool_request_id,
array<CookieWithAccessResult> cookies_with_access_result,
- array<HttpRawHeaderPair> headers);
+ array<HttpRawHeaderPair> headers,
+ ClientSecurityState? client_security_state);
// Called to send information about the cookies blocked from storage from a
// received response. Only called when |devtool_request_id| is available to
@@ -77,7 +80,23 @@ interface NetworkServiceClient {
string devtool_request_id,
array<CookieAndLineWithAccessResult> cookies_with_access_result,
array<HttpRawHeaderPair> headers,
- string? raw_response_headers);
+ string? raw_response_headers,
+ IPAddressSpace resource_address_space);
+
+ // Called to send information about a private network request that was blocked
+ // (then |is_warning| is false), or will be blocked in the future (then
+ // |is_warning| is true). It is possible to share sensitive information with
+ // DevTools as this is handled in the browser process. Called even when
+ // |devtool_request_id| is not available to the URLLoader to ensure the
+ // information can be recorded even when DevTools is closed.
+ OnPrivateNetworkRequest(
+ int32 process_id,
+ int32 routing_id,
+ string? devtool_request_id,
+ url.mojom.Url url,
+ bool is_warning,
+ IPAddressSpace resource_address_space,
+ ClientSecurityState client_security_state);
// Called to send the CORS preflight request information. Only called when
// |devtool_request_id| is available on the original request.
@@ -86,7 +105,8 @@ interface NetworkServiceClient {
int32 render_frame_id,
mojo_base.mojom.UnguessableToken devtool_request_id,
URLRequest request,
- url.mojom.Url initiator_url);
+ url.mojom.Url initiator_url,
+ string initiator_devtool_request_id);
// Called to send the CORS preflight response information. Only called when
// |devtool_request_id| is available on the original request.
@@ -104,6 +124,15 @@ interface NetworkServiceClient {
int32 render_frame_id,
mojo_base.mojom.UnguessableToken devtool_request_id,
URLLoaderCompletionStatus status);
+
+ // Called to send the result of a successful or failed Trust Token
+ // operation. Only called when |devtools_request_id| is available on the
+ // original request.
+ OnTrustTokenOperationDone(
+ int32 process_id,
+ int32 routing_id,
+ string devtool_request_id,
+ TrustTokenOperationResult result);
};
// Values for configuring HTTP authentication that can only be set once.
@@ -327,11 +356,6 @@ interface NetworkService {
// this call, will use the same CRLSet.
UpdateCRLSet(mojo_base.mojom.ReadOnlyBuffer crl_set) => ();
- // Updates the configuration used for determining if a site should have legacy
- // TLS warnings suppressed. Configs that cannot be parsed as a
- // LegacyTLSExperimentConfig (protobuf) will be ignored.
- UpdateLegacyTLSConfig(mojo_base.mojom.ReadOnlyBuffer config) => ();
-
// Notification that the certificate database has been modified.
OnCertDBChanged();
@@ -348,15 +372,6 @@ interface NetworkService {
[EnableIf=is_win]
SetEncryptionKey(string encryption_key);
- // Notifies CORB (Cross-Origin Read Blocking) that |process_id| is proxying
- // requests on behalf of a universal-access plugin and therefore CORB should
- // stop blocking requests marked as ResourceType::kPluginResource.
- //
- // TODO(lukasza, laforge): https://crbug.com/702995: Remove the ...ForPlugin
- // methods once Flash support is removed from Chromium (probably around 2020
- // - see https://www.chromium.org/flash-roadmap).
- AddCorbExceptionForPlugin(int32 process_id);
-
// Notifies |request_initiator_origin_lock| enforcement code that |process_id|
// is proxying requests on behalf of a plugin from
// |allowed_request_initiator| origin.
@@ -367,7 +382,7 @@ interface NetworkService {
int32 process_id,
url.mojom.Origin allowed_request_initiator);
- // Reverts AddCorbExceptionForPlugin and AddAllowedRequestInitiatorForPlugin.
+ // Reverts AddAllowedRequestInitiatorForPlugin.
RemoveSecurityExceptionsForPlugin(int32 process_id);
// Called when the system is low on memory.
diff --git a/chromium/services/network/public/mojom/network_service_test.mojom b/chromium/services/network/public/mojom/network_service_test.mojom
index e7a99de8784..f1dff9d8ae8 100644
--- a/chromium/services/network/public/mojom/network_service_test.mojom
+++ b/chromium/services/network/public/mojom/network_service_test.mojom
@@ -18,12 +18,15 @@ enum ResolverType {
kResolverTypeDirectLookup,
};
+// `dns_aliases` is a list of aliases read from DNS records, e.g. CNAME
+// aliases, and is intended to preserve the alias chain in reverse, from
+// canonical name (i.e. address record name) through to query name.
struct Rule {
ResolverType resolver_type;
string host_pattern;
string replacement;
int32 host_resolver_flags;
- string canonical_name;
+ array<string> dns_aliases;
};
// Testing interface to the network service.
@@ -118,8 +121,8 @@ interface NetworkServiceTest {
[Sync]
SetEVPolicy(array<uint8, 32> fingerprint_sha256, string policy_oid) => ();
- // Gets the current count of entries in the preloaded First-Party sets
- // mapping. Note that each entry is a registered domain mapped to its owner.
+ // Gets the current count of entries in the First-Party sets mapping. Note
+ // that each entry is a registered domain mapped to its owner.
[Sync]
- GetPreloadedFirstPartySetEntriesCount() => (int64 entries);
+ GetFirstPartySetEntriesCount() => (int64 entries);
};
diff --git a/chromium/services/network/public/mojom/parsed_headers.mojom b/chromium/services/network/public/mojom/parsed_headers.mojom
index 6bba67b26b7..5eb06997257 100644
--- a/chromium/services/network/public/mojom/parsed_headers.mojom
+++ b/chromium/services/network/public/mojom/parsed_headers.mojom
@@ -9,6 +9,7 @@ import "services/network/public/mojom/content_security_policy.mojom";
import "services/network/public/mojom/cross_origin_embedder_policy.mojom";
import "services/network/public/mojom/cross_origin_opener_policy.mojom";
import "services/network/public/mojom/web_client_hints_types.mojom";
+import "services/network/public/mojom/x_frame_options.mojom";
// Holds the parsed representation of several security related HTTP headers.
// This struct should only be populated by network::PopulateParsedHeaders()
@@ -27,8 +28,8 @@ struct ParsedHeaders {
// Cross-Origin-opener-Policy-Report-Only headers.
CrossOriginOpenerPolicy cross_origin_opener_policy;
- // The parsed value of the Origin-Isolation header.
- bool origin_isolation = false;
+ // The parsed value of the Origin-Agent-Cluster header.
+ bool origin_agent_cluster = false;
// The parsed Accept-CH from response headers.
//
@@ -62,4 +63,7 @@ struct ParsedHeaders {
// For more information, see:
// https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability#section-3
array<WebClientHintsType>? critical_ch;
+
+ // The parsed value of the X-Frame-Options header.
+ XFrameOptionsValue xfo = XFrameOptionsValue.kNone;
};
diff --git a/chromium/services/network/public/mojom/quic_transport.mojom b/chromium/services/network/public/mojom/quic_transport.mojom
index e8b4de15421..6a629537ba2 100644
--- a/chromium/services/network/public/mojom/quic_transport.mojom
+++ b/chromium/services/network/public/mojom/quic_transport.mojom
@@ -5,6 +5,7 @@
module network.mojom;
import "mojo/public/mojom/base/read_only_buffer.mojom";
+import "mojo/public/mojom/base/time.mojom";
import "url/mojom/url.mojom";
// Represents a QuicTransport error.
@@ -65,6 +66,10 @@ interface QuicTransport {
// Aborts the stream for |stream_id|.
AbortStream(uint32 stream_id, uint64 code);
+
+ // Sets the duration which determines whether an outgoing datagram should be
+ // discarded due to being in the queue for too long.
+ SetOutgoingDatagramExpirationDuration(mojo_base.mojom.TimeDelta duration);
};
// A mojo interface for the client of QuicTransport.
diff --git a/chromium/services/network/public/mojom/site_for_cookies.mojom b/chromium/services/network/public/mojom/site_for_cookies.mojom
index 2de2d571e57..1cee8c51b7c 100644
--- a/chromium/services/network/public/mojom/site_for_cookies.mojom
+++ b/chromium/services/network/public/mojom/site_for_cookies.mojom
@@ -4,11 +4,12 @@
module network.mojom;
+import "services/network/public/mojom/schemeful_site.mojom";
+
// Mapped to net::SiteForCookies.
struct SiteForCookies {
// These fields should not be used directly, but rather through the mapped
// net::SiteForCookies.
- string scheme;
- string registrable_domain;
+ SchemefulSite site;
bool schemefully_same;
};
diff --git a/chromium/services/network/public/mojom/trust_tokens.mojom b/chromium/services/network/public/mojom/trust_tokens.mojom
index c9df1b062f0..9e98ddfd0ad 100644
--- a/chromium/services/network/public/mojom/trust_tokens.mojom
+++ b/chromium/services/network/public/mojom/trust_tokens.mojom
@@ -205,19 +205,19 @@ struct TrustTokenKeyCommitmentResult {
// one operating system, issuers could benefit from a couple different
// fallback behaviors depending on their particular requirements.
//
- // |unavailable_local_issuance_fallback|'s value specifies what action to take
- // when both of the following hold simultaneously:
+ // |unavailable_local_operation_fallback|'s value specifies what action to
+ // take when both of the following hold simultaneously:
// (1) local issuance is specified on at least one OS (i.e.
// |request_issuance_locally_on| is nonempty) and
// (2) we're not on any of the specified OSes.
- enum UnavailableLocalIssuanceFallback {
+ enum UnavailableLocalOperationFallback {
// If we're not on a matching OS, instead attempt a standard web
// issuance request against the issuance request's destination URL.
kWebIssuance,
// If we're not on a matching OS, just fail the issuance request.
kReturnWithError,
};
- UnavailableLocalIssuanceFallback unavailable_local_issuance_fallback;
+ UnavailableLocalOperationFallback unavailable_local_operation_fallback;
};
// Struct FulfillTrustTokenIssuanceRequest represents a Trust Tokens issuance
@@ -247,6 +247,8 @@ struct FulfillTrustTokenIssuanceRequest {
// because the Java bindings append the suffix "Response" when generating
// callback names.
struct FulfillTrustTokenIssuanceAnswer {
+ // WARNING: Since these values are committed to histograms, please do not
+ // remove or reorder entries.
enum Status {
kOk,
// It wasn't possible to route the issuance operation to the specified
@@ -262,3 +264,25 @@ struct FulfillTrustTokenIssuanceAnswer {
// response header. Otherwise, its value is indeterminate.
string response;
};
+
+// TrustTokenOperationResult contains all the information required by
+// DevTools. Which fields are set depend on |type| and |status|.
+struct TrustTokenOperationResult {
+ // Required.
+ TrustTokenOperationType type;
+ TrustTokenOperationStatus status;
+
+ // Shared among the different operation types.
+ url.mojom.Origin? issuer;
+ url.mojom.Origin? top_level_origin;
+
+ // In case of TrustTokenOperationType::kIssuance.
+ int32 issued_token_count = 0;
+};
+
+// Struct StoredTrustTokensForIssuer is used by DevTools to inspect
+// the current state of the Trust Token store.
+struct StoredTrustTokensForIssuer {
+ url.mojom.Origin issuer;
+ int32 count;
+};
diff --git a/chromium/services/network/public/mojom/url_loader.mojom b/chromium/services/network/public/mojom/url_loader.mojom
index 8f1834ec677..9fbe2d0aa94 100644
--- a/chromium/services/network/public/mojom/url_loader.mojom
+++ b/chromium/services/network/public/mojom/url_loader.mojom
@@ -8,6 +8,7 @@ import "mojo/public/mojom/base/big_buffer.mojom";
import "mojo/public/mojom/base/file_path.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
+import "services/network/public/mojom/auth_and_certificate_observer.mojom";
import "services/network/public/mojom/client_security_state.mojom";
import "services/network/public/mojom/cors.mojom";
import "services/network/public/mojom/cookie_access_observer.mojom";
@@ -20,6 +21,7 @@ import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/site_for_cookies.mojom";
import "services/network/public/mojom/trust_tokens.mojom";
import "services/network/public/mojom/url_response_head.mojom";
+import "services/network/public/mojom/web_bundle_handle.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
@@ -54,20 +56,6 @@ enum URLRequestReferrerPolicy {
kNoReferrer
};
-// Used for represents the type of the internal contents of
-// network::DataElement.
-enum DataElementType {
- kUnknown = -1,
-
- kDataPipe,
- kChunkedDataPipe,
- kReadOnceStream,
- kBytes,
-
- // TODO(https://crbug.com/1132362): Remove this.
- kFile,
-};
-
// Options that may only be set on URLRequests passed to a URLLoaderFactory
// created with |is_trusted| set to true.
struct TrustedUrlRequestParams {
@@ -88,6 +76,11 @@ struct TrustedUrlRequestParams {
// URLLoaderFactory will be ignored.
pending_remote<CookieAccessObserver>? cookie_observer;
+ // Observer which should be notified when this URLRequest has authentication
+ // and certificate events. If this is set to non-null, the observer passed to
+ // URLLoaderFactory will be ignored.
+ pending_remote<AuthenticationAndCertificateObserver>? auth_cert_observer;
+
// Specifies the security state of the client, for cases when the
// URLLoaderFactory is shared among multiple clients.
//
@@ -97,6 +90,23 @@ struct TrustedUrlRequestParams {
ClientSecurityState? client_security_state;
};
+// Options that may only be set on URLRequests which are related to WebBundle.
+struct WebBundleTokenParams {
+ // The URL of the WebBundle.
+ url.mojom.Url bundle_url;
+ // Unique token to identify a WebBundle.
+ mojo_base.mojom.UnguessableToken token;
+ // Handle for the WebBundle-related communication between the network process
+ // and the renderer. This is also used as a 'keep-alive' handle. We clean up
+ // the WebBundle data in the network process when the renderer-side endpoint
+ // is deleted.
+ pending_remote<WebBundleHandle>? web_bundle_handle;
+ // Renderer process ID of the request initiator frame. Set by the browser
+ // process, for subframe navigation requests to bundled resources. Not used
+ // for subresource requests sent by renderer processes.
+ int32 render_process_id;
+};
+
// Typemapped to network::ResourceRequest.
struct URLRequest {
// The request method: GET, POST, etc.
@@ -121,12 +131,6 @@ struct URLRequest {
// landed.
SiteForCookies site_for_cookies;
- // Boolean indicating whether SameSite cookies should be indiscriminately
- // attached to the request, bypassing the usual site_for_cookies checks.
- // Setting this param to true causes SameSite cookies to be included on
- // cross-site requests (or requests that "look" cross-site).
- bool force_ignore_site_for_cookies;
-
// First-party URL redirect policy: During server redirects, the first-party
// URL for cookies normally doesn't change. However, if this is true, the
// the first-party URL should be updated to the URL on every redirect.
@@ -255,11 +259,6 @@ struct URLRequest {
// If true then the request continues even if it's blocked by CORB.
bool corb_detachable = false;
- // TODO(lukasza): https://crbug.com/846339: Remove the field below and instead
- // make plugins use a separate URLoaderFactory. Note requests of this type are
- // only excluded if mode is kNoCors.
- bool corb_excluded = false;
-
// https://fetch.spec.whatwg.org/#concept-request-mode
// Used mainly by CORS handling (out-of-blink CORS), CORB, Service Worker.
// CORS handling needs a proper origin (including a unique opaque origin).
@@ -390,6 +389,9 @@ struct URLRequest {
// True for XHR, Fetch, and EventSource.
bool is_fetch_like_api;
+ // True for favicon.
+ bool is_favicon;
+
// If set, the network service will attempt to retrieve the appropriate origin
// policy, if necessary, and attach it to the ResourceResponseHead.
// Spec: https://wicg.github.io/origin-policy/
@@ -408,12 +410,17 @@ struct URLRequest {
// and the request has set the trustToken Fetch parameter, denoting that it
// wishes to execute a Trust Tokens protocol operation.
TrustTokenParams? trust_token_params;
+
+ // Set for WebBundle related requests. See the comment of WebBundleTokenParams
+ // for details.
+ WebBundleTokenParams? web_bundle_token_params;
};
// URLRequestBody represents body (i.e. upload data) of a HTTP request.
// Typemapped to network::ResourceRequestBody
struct URLRequestBody {
- // Store upload bodies
+ // The body contents. DataElementChunkedDataPipe can be used in `elements`
+ // only if `elements` consists of one element.
array<DataElement> elements;
// Identifies a particular upload instance, which is used by the cache to
@@ -429,26 +436,42 @@ struct URLRequestBody {
bool allow_http1_for_streaming_upload;
};
-// Represents part of an upload body. This could be either one of bytes, file or
-// a data pipe.
-// Typemapped to network::DataElement
-struct DataElement {
- DataElementType type;
+// Represents part of an upload body consisting of bytes.
+struct DataElementBytes {
+ mojo_base.mojom.BigBuffer data;
+};
- // For kBytes.
- mojo_base.mojom.BigBuffer buf;
- // For kFile
+// Represents part of an upload body consisting of (part of) a file.
+struct DataElementFile {
mojo_base.mojom.FilePath path;
- // For kDataPipe
- pending_remote<network.mojom.DataPipeGetter>? data_pipe_getter;
- // For kChunkedDataPipe
- pending_remote<network.mojom.ChunkedDataPipeGetter>? chunked_data_pipe_getter;
-
uint64 offset;
uint64 length;
mojo_base.mojom.Time expected_modification_time;
};
+// Represents part of an upload body consisting of a data pipe with a known
+// size.
+struct DataElementDataPipe {
+ pending_remote<network.mojom.DataPipeGetter> data_pipe_getter;
+};
+
+// Represents part of an upload body consisting of a data pipe without a known
+// size.
+struct DataElementChunkedDataPipe {
+ pending_remote<network.mojom.ChunkedDataPipeGetter> data_pipe_getter;
+ // When true, a data pipe can be gotten from `chunked_data_pipe_getter` only
+ // once.
+ bool read_only_once;
+};
+
+// Represents part of an upload body.
+union DataElement {
+ DataElementBytes bytes;
+ DataElementFile file;
+ DataElementDataPipe data_pipe;
+ DataElementChunkedDataPipe chunked_data_pipe;
+};
+
// URLLoader is an interface for performing a single request to a URL.
//
// Destroying a URLLoader will cancel the associated request.
diff --git a/chromium/services/network/public/mojom/url_loader_factory.mojom b/chromium/services/network/public/mojom/url_loader_factory.mojom
index b141eff3d63..e8bb8cfea7b 100644
--- a/chromium/services/network/public/mojom/url_loader_factory.mojom
+++ b/chromium/services/network/public/mojom/url_loader_factory.mojom
@@ -18,8 +18,11 @@ const uint32 kURLLoadOptionSniffMimeType = 2;
// Indicates that execution is blocking on the completion of the request.
const uint32 kURLLoadOptionSynchronous = 4;
-// Sends the net::SSLInfo struct in OnComplete when the connection had a major
-// certificate error.
+// Sends the net::SSLInfo on request completion when the connection had a major
+// certificate error. The SSLInfo can be retrieved from the OnComplete struct
+// when the connection failed due to the certificate error, or from the
+// OnReceiveResponse struct if the connection proceeded despite the certificate
+// error.
const uint32 kURLLoadOptionSendSSLInfoForCertificateError = 8;
// Uses the header client set in URLLoaderFactoryParams for this request.
diff --git a/chromium/services/network/public/mojom/url_response_head.mojom b/chromium/services/network/public/mojom/url_response_head.mojom
index fa737edd89d..c37bbd02370 100644
--- a/chromium/services/network/public/mojom/url_response_head.mojom
+++ b/chromium/services/network/public/mojom/url_response_head.mojom
@@ -134,6 +134,12 @@ struct URLResponseHead {
// https://fetch.spec.whatwg.org/#concept-response-type
FetchResponseType response_type = FetchResponseType.kDefault;
+ // Pre-computed padding. This should only be non-zero when |response_type|
+ // is set to kOpaque. Note, this is not set by network service, but will be
+ // populated if the response was provided by a service worker FetchEvent
+ // handler.
+ int64 padding = 0;
+
// The cache name of the CacheStorage from where the response is served via
// the ServiceWorker. Empty if the response isn't from the CacheStorage.
string cache_storage_cache_name;
@@ -219,4 +225,14 @@ struct URLResponseHead {
// is propagated to the renderer and set on recursive prefetch requests
// (see corresponding documentation in url_loader.mojom).
mojo_base.mojom.UnguessableToken? recursive_prefetch_token;
+
+ // Aliases, if any, for the destination URL, as read from DNS CNAME records.
+ // The first entry of `dns_aliases`, if it exists, is the canonical name.
+ // The alias chain is preserved in reverse order, from canonical name (i.e.
+ // address record name) through to query name.
+ array<string> dns_aliases;
+
+ // The URL of WebBundle this response was loaded from. This value is only
+ // populated for resources loaded from a WebBundle.
+ url.mojom.Url web_bundle_url;
};
diff --git a/chromium/services/network/public/mojom/web_bundle_handle.mojom b/chromium/services/network/public/mojom/web_bundle_handle.mojom
new file mode 100644
index 00000000000..d142d37d1fa
--- /dev/null
+++ b/chromium/services/network/public/mojom/web_bundle_handle.mojom
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module network.mojom;
+
+enum WebBundleErrorType {
+ kMetadataParseError,
+ kResponseParseError,
+ kResourceNotFound,
+ kMemoryQuotaExceeded,
+ kServingConstraintsNotMet,
+};
+
+// A handle to a WebBundle instance in the Network Service. Created by a
+// renderer, and its remote endpoint is passed to the Network Service. The
+// receiving endpoint is held in the renderer and closed to tell the Network
+// Service that the Bundle is no longer needed.
+interface WebBundleHandle {
+ // Used to create a copy of this handle.
+ Clone(pending_receiver<WebBundleHandle> receiver);
+
+ // Report errors to the renderer.
+ OnWebBundleError(WebBundleErrorType type, string message);
+
+ // Report to the renderer whether successfully loaded the data or failed.
+ OnWebBundleLoadFinished(bool success);
+};
diff --git a/chromium/services/network/public/mojom/websocket.mojom b/chromium/services/network/public/mojom/websocket.mojom
index 3b38ab47b1a..004228d90b9 100644
--- a/chromium/services/network/public/mojom/websocket.mojom
+++ b/chromium/services/network/public/mojom/websocket.mojom
@@ -45,7 +45,7 @@ struct WebSocketHandshakeResponse {
};
// This interface is for HTTP Authentication.
-interface AuthenticationHandler {
+interface WebSocketAuthenticationHandler {
// Returns null credentials when it wants to cancel authentication, and
// returns a non-null credentials when it wants to use the credentials for
// authentication.
@@ -127,11 +127,6 @@ interface WebSocketClient {
// The interface for the server side of WebSocket. Implemented by the network
// service. Used to send out data to the network service.
interface WebSocket {
- // The client side may observe the following disconnection reason from the
- // service side:
- const uint32 kInsufficientResources = 1;
- const uint32 kInternalFailure = 2;
-
// Sends a message via mojo datapipe to the remote server.
// - |type| is the type of the message. It must be set to either
// WebSocketMessageType.TEXT or WebSocketMessageType.BINARY.
diff --git a/chromium/services/network/public/mojom/x_frame_options.mojom b/chromium/services/network/public/mojom/x_frame_options.mojom
new file mode 100644
index 00000000000..9eaa02ef32b
--- /dev/null
+++ b/chromium/services/network/public/mojom/x_frame_options.mojom
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module network.mojom;
+
+// This enum represents the possible values for the X-Frame-Options header:
+// https://html.spec.whatwg.org/multipage/browsing-the-web.html#the-x-frame-options-header.
+enum XFrameOptionsValue {
+ kNone, // No XFO header is present.
+ kDeny, // XFO: DENY
+ kSameOrigin, // XFO: SAMEORIGIN
+ kAllowAll, // XFO: ALLOWALL
+ kInvalid, // XFO: [anything other than DENY, SAMEORIGIN, or ALLOWALL]
+ kConflict // Multiple XFO headers are present, with distinct values.
+};
diff --git a/chromium/services/network/public/proto/BUILD.gn b/chromium/services/network/public/proto/BUILD.gn
index 0ab24319138..7de51ed6bf9 100644
--- a/chromium/services/network/public/proto/BUILD.gn
+++ b/chromium/services/network/public/proto/BUILD.gn
@@ -6,17 +6,12 @@ import("//services/network/public/cpp/features.gni")
import("//third_party/protobuf/proto_library.gni")
group("proto") {
- public_deps = [ ":tls_deprecation_config_proto" ]
-
+ public_deps = []
if (is_ct_supported) {
public_deps += [ ":sct_audit_report_proto" ]
}
}
-proto_library("tls_deprecation_config_proto") {
- sources = [ "tls_deprecation_config.proto" ]
-}
-
if (is_ct_supported) {
proto_library("sct_audit_report_proto") {
sources = [ "sct_audit_report.proto" ]
diff --git a/chromium/services/network/public/proto/sct_audit_report.proto b/chromium/services/network/public/proto/sct_audit_report.proto
index d292c5c7564..9ae1b8b4528 100644
--- a/chromium/services/network/public/proto/sct_audit_report.proto
+++ b/chromium/services/network/public/proto/sct_audit_report.proto
@@ -13,16 +13,26 @@ option optimize_for = LITE_RUNTIME;
package sct_auditing;
+// SCTClientReport represents a single report from a client, containing reports
+// from multiple independent connections, each of which contain multiple SCTs.
+message SCTClientReport {
+ // The simplified user agent of the submitter (e.g. Chrome/xy.0.abcd.e).
+ // Supplements API keys to provide per-version granularity.
+ string user_agent = 1;
+
+ repeated TLSConnectionReport certificate_report = 2;
+}
+
// TLSConnectionReport is the primary per-handshake report for SCT auditing.
message TLSConnectionReport {
TLSConnectionContext context = 1;
- // SCTs may appear in any order. See SCTWithSourceAndVerifyStatus for details.
- repeated SCTWithSourceAndVerifyStatus included_scts = 2;
+ // SCTs may appear in any order. See SCTWithVerifyStatus for details.
+ repeated SCTWithVerifyStatus included_sct = 2;
}
-// TLSConnectionContext contains details about the connection that are common
-// to all SCTs observed in that connection.
+// TLSConnectionContext contains details about the connection that are common to
+// all SCTs observed in that connection.
message TLSConnectionContext {
// Time when the UA observed the certificate in seconds since the Unix epoch.
int64 time_seen = 1;
@@ -41,9 +51,9 @@ message TLSConnectionContext {
repeated bytes certificate_chain = 3;
}
-// SCTWithSourceAndVerifyStatus contains the raw SCT, where it was found in the
-// certificate, and its validation status according to the UA.
-message SCTWithSourceAndVerifyStatus {
+// SCTWithVerifyStatus contains the serialized SCT along with the validation
+// status according to the UA.
+message SCTWithVerifyStatus {
// Keep sync'd with SctVerifyStatus in Chrome's net/cert/sct_status_flags.h.
enum SctVerifyStatus {
// Default to unspecified status. See go/unspecified-enum.
@@ -67,15 +77,7 @@ message SCTWithSourceAndVerifyStatus {
}
SctVerifyStatus status = 1;
- // The source is the manner in which the client received the SCT (embedded in
- // the certificate, delivered via the TLS handshake, or delivered via OCSP).
- enum Source {
- SOURCE_UNSPECIFIED = 0;
- EMBEDDED = 1;
- TLS_EXTENSION = 2;
- OCSP_RESPONSE = 3;
- }
- Source source = 2;
-
- bytes sct = 3;
+ // SignedCertificateTimestamp struct serialized via
+ // net::ct::EncodeSignedCertificateTimestamp().
+ bytes serialized_sct = 2;
}
diff --git a/chromium/services/network/public/proto/tls_deprecation_config.proto b/chromium/services/network/public/proto/tls_deprecation_config.proto
deleted file mode 100644
index a54d5d36d3d..00000000000
--- a/chromium/services/network/public/proto/tls_deprecation_config.proto
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto2";
-
-package chrome_browser_ssl;
-
-option optimize_for = LITE_RUNTIME;
-
-// The set of sites to be used as a control group for Legacy TLS experiments.
-// Warning UI will not be shown on these sites.
-message LegacyTLSExperimentConfig {
- optional uint32 version_id = 1;
- // SHA-256 hash of the hostname of sites in the control group (e.g., for
- // "https://test.example.com/foo" the hostname is "test.example.com"). This
- // list must be in sorted order (alphanumeric by hash value).
- repeated string control_site_hashes = 2;
-}