summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/loader
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/loader')
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/BUILD.gn31
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/DEPS4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/DIR_METADATA4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc69
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.cc247
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.h64
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc82
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc135
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc96
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc154
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc88
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.h51
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc293
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc285
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc182
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc359
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h59
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h36
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc170
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc132
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/subresource_web_bundle.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS31
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc594
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h128
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc898
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc102
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc335
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h155
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc219
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h60
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.cc459
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader_test.cc336
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc630
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc561
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc1172
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_factory.cc46
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc715
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/mixed_content.cc102
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/mixed_content.h52
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc53
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/web_url_request_extra_data.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/web_url_request_util.cc54
97 files changed, 7697 insertions, 2325 deletions
diff --git a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
index 4f8c6195b48..fb533c27816 100644
--- a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -24,6 +24,7 @@ blink_platform_sources("loader") {
"cors/cors.h",
"cors/cors_error_string.cc",
"cors/cors_error_string.h",
+ "fetch/back_forward_cache_loader_helper.h",
"fetch/buffering_bytes_consumer.cc",
"fetch/buffering_bytes_consumer.h",
"fetch/bytes_consumer.cc",
@@ -64,6 +65,7 @@ blink_platform_sources("loader") {
"fetch/preload_key.h",
"fetch/raw_resource.cc",
"fetch/raw_resource.h",
+ "fetch/render_blocking_behavior.h",
"fetch/resource.cc",
"fetch/resource.h",
"fetch/resource_client.cc",
@@ -116,10 +118,17 @@ blink_platform_sources("loader") {
"fetch/trust_token_params_conversion.h",
"fetch/unique_identifier.cc",
"fetch/unique_identifier.h",
+ "fetch/url_loader/mojo_url_loader_client.cc",
+ "fetch/url_loader/mojo_url_loader_client.h",
"fetch/url_loader/request_conversion.cc",
"fetch/url_loader/request_conversion.h",
- "fetch/url_loader/web_bundle_subresource_loader.cc",
- "fetch/url_loader/web_bundle_subresource_loader.h",
+ "fetch/url_loader/sync_load_context.cc",
+ "fetch/url_loader/sync_load_context.h",
+ "fetch/url_loader/sync_load_response.cc",
+ "fetch/url_loader/sync_load_response.h",
+ "fetch/url_loader/web_resource_request_sender.cc",
+ "fetch/url_loader/web_url_loader.cc",
+ "fetch/url_loader/web_url_loader_factory.cc",
"fetch/url_loader/worker_main_script_loader.cc",
"fetch/url_loader/worker_main_script_loader.h",
"fetch/url_loader/worker_main_script_loader_client.h",
@@ -131,6 +140,8 @@ blink_platform_sources("loader") {
"internet_disconnected_web_url_loader.cc",
"link_header.cc",
"link_header.h",
+ "mixed_content.cc",
+ "mixed_content.h",
"mixed_content_autoupgrade_status.h",
"static_data_navigation_body_loader.cc",
"static_data_navigation_body_loader.h",
@@ -147,17 +158,21 @@ blink_platform_sources("loader") {
deps = [
":make_platform_loader_generated_fetch_initiator_type_names",
"//components/link_header_util",
- "//components/web_package",
+ "//components/variations/net:net",
"//net",
"//services/metrics/public/cpp:ukm_builders",
"//services/network/public/cpp",
"//services/network/public/mojom:mojom_blink",
+ "//third_party/blink/public/mojom:mojom_platform_blink",
"//third_party/blink/renderer/platform/blob:blob",
"//third_party/blink/renderer/platform/instrumentation:instrumentation",
"//third_party/blink/renderer/platform/network:network",
"//third_party/blink/renderer/platform/scheduler:scheduler",
]
- public_deps = [ "//third_party/blink/renderer/platform/heap:heap" ]
+ public_deps = [
+ "//third_party/blink/public/mojom:mojom_platform_headers",
+ "//third_party/blink/renderer/platform/heap:heap",
+ ]
allow_circular_includes_from =
[ "//third_party/blink/renderer/platform/network:network" ]
}
@@ -174,6 +189,7 @@ source_set("unit_tests") {
"cors/cors_test.cc",
"fetch/buffering_bytes_consumer_test.cc",
"fetch/bytes_consumer_test.cc",
+ "fetch/cached_metadata_handler_test.cc",
"fetch/client_hints_preferences_test.cc",
"fetch/data_pipe_bytes_consumer_test.cc",
"fetch/fetch_api_request_body_mojom_traits_test.cc",
@@ -192,7 +208,10 @@ source_set("unit_tests") {
"fetch/response_body_loader_test.cc",
"fetch/shared_buffer_bytes_consumer_test.cc",
"fetch/source_keyed_cached_metadata_handler_test.cc",
- "fetch/url_loader/web_bundle_subresource_loader_test.cc",
+ "fetch/url_loader/mojo_url_loader_client_unittest.cc",
+ "fetch/url_loader/sync_load_context_unittest.cc",
+ "fetch/url_loader/web_resource_request_sender_unittest.cc",
+ "fetch/url_loader/web_url_loader_unittest.cc",
"fetch/url_loader/worker_main_script_loader_unittest.cc",
"ftp_directory_listing_test.cc",
"link_header_test.cc",
@@ -204,8 +223,8 @@ source_set("unit_tests") {
deps = [
"//base/test:test_support",
- "//components/web_package:test_support",
"//mojo/public/cpp/test_support:test_utils",
+ "//net:test_support",
"//net/traffic_annotation:test_support",
"//services/network:test_support",
"//testing/gmock",
diff --git a/chromium/third_party/blink/renderer/platform/loader/DEPS b/chromium/third_party/blink/renderer/platform/loader/DEPS
index 52019c0ffc9..4d149b6e493 100644
--- a/chromium/third_party/blink/renderer/platform/loader/DEPS
+++ b/chromium/third_party/blink/renderer/platform/loader/DEPS
@@ -11,8 +11,11 @@ include_rules = [
"+components/link_header_util", # for LinkHeader.cpp
"+net/base/load_flags.h",
"+net/base/net_errors.h",
+ "+net/traffic_annotation/network_traffic_annotation_test_helper.h",
+ "+net/url_request/redirect_info.h",
"+services/metrics/public", # for UKM API
"+services/network/public", # for Fetch API and CORS
+ "+third_party/blink/renderer/platform/back_forward_cache_utils.h",
"+third_party/blink/renderer/platform/bindings/dom_wrapper_world.h",
"+third_party/blink/renderer/platform/bindings/parkable_string.h",
"+third_party/blink/renderer/platform/bindings/script_forbidden_scope.h",
@@ -28,6 +31,7 @@ include_rules = [
"+third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h",
"+third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h",
"+third_party/blink/renderer/platform/mhtml",
+ "+third_party/blink/renderer/platform/mojo/mojo_binding_context.h",
"+third_party/blink/renderer/platform/network",
"+third_party/blink/renderer/platform/platform_export.h",
"+third_party/blink/renderer/platform/platform_probe_sink.h",
diff --git a/chromium/third_party/blink/renderer/platform/loader/DIR_METADATA b/chromium/third_party/blink/renderer/platform/loader/DIR_METADATA
new file mode 100644
index 00000000000..a080a748373
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/DIR_METADATA
@@ -0,0 +1,4 @@
+monorail {
+ component: "Blink>Loader"
+}
+team_email: "loading-dev@chromium.org" \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/platform/loader/OWNERS b/chromium/third_party/blink/renderer/platform/loader/OWNERS
index 1c34e1edc6a..b46fa621550 100644
--- a/chromium/third_party/blink/renderer/platform/loader/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/loader/OWNERS
@@ -4,6 +4,3 @@ mkwst@chromium.org
toyoshim@chromium.org
yhirano@chromium.org
yoavweiss@chromium.org
-
-# TEAM: loading-dev@chromium.org
-# COMPONENT: Blink>Loader
diff --git a/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc b/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
index 180d4f32735..1d45872564e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
@@ -56,6 +56,16 @@ const WebFeature kTextXmlFeatures[2] = {
WebFeature::kSameOriginTextXml,
};
+const WebFeature kJsonFeatures[2] = {
+ WebFeature::kCrossOriginJsonTypeForScript,
+ WebFeature::kSameOriginJsonTypeForScript,
+};
+
+const WebFeature kUnknownFeatures[2] = {
+ WebFeature::kCrossOriginStrictNosniffWouldBlock,
+ WebFeature::kSameOriginStrictNosniffWouldBlock,
+};
+
// Helper function to decide what to do with with a given mime type. This takes
// - a mime type
// - inputs that affect the decision (is_same_origin, mime_type_check_mode).
@@ -121,6 +131,11 @@ bool AllowMimeTypeAsScript(const String& mime_type,
counter = kTextPlainFeatures[same_origin];
} else if (mime_type.StartsWithIgnoringCase("text/xml")) {
counter = kTextXmlFeatures[same_origin];
+ } else if (mime_type.StartsWithIgnoringCase("text/json") ||
+ mime_type.StartsWithIgnoringCase("application/json")) {
+ counter = kJsonFeatures[same_origin];
+ } else {
+ counter = kUnknownFeatures[same_origin];
}
return true;
diff --git a/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc b/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
index 4f47d21a355..f4db8179fc9 100644
--- a/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
@@ -152,6 +152,16 @@ TEST_F(AllowedByNosniffTest, Counters) {
{bla, blubb, "text/plain", kOpaque, WebFeature::kCrossOriginTextPlain},
{bla, bla, "text/plain", kBasic, WebFeature::kSameOriginTextScript},
{bla, bla, "text/plain", kBasic, WebFeature::kSameOriginTextPlain},
+ {bla, bla, "text/json", kBasic, WebFeature::kSameOriginTextScript},
+
+ // JSON
+ {bla, bla, "text/json", kBasic, WebFeature::kSameOriginJsonTypeForScript},
+ {bla, bla, "application/json", kBasic,
+ WebFeature::kSameOriginJsonTypeForScript},
+ {bla, blubb, "text/json", kOpaque,
+ WebFeature::kCrossOriginJsonTypeForScript},
+ {bla, blubb, "application/json", kOpaque,
+ WebFeature::kCrossOriginJsonTypeForScript},
// Test mime type and subtype handling.
{bla, bla, "text/xml", kBasic, WebFeature::kSameOriginTextScript},
@@ -166,6 +176,12 @@ TEST_F(AllowedByNosniffTest, Counters) {
{blubb, blubb, "application/xml", kCors,
WebFeature::kCrossOriginApplicationXml},
{bla, bla, "text/html", kBasic, WebFeature::kSameOriginTextHtml},
+
+ // Unknown
+ {bla, bla, "not/script", kBasic,
+ WebFeature::kSameOriginStrictNosniffWouldBlock},
+ {bla, blubb, "not/script", kOpaque,
+ WebFeature::kCrossOriginStrictNosniffWouldBlock},
};
for (auto& testcase : data) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc b/chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
index c2d4cc78b9b..44ba2e94ed1 100644
--- a/chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
@@ -120,10 +120,29 @@ BoundRemoteMapToPendingRemoteMap(
return output;
}
+// TODO(https://crbug.com/1114822): Remove ScopedRequestCrashKeys (it duplicates
+// a similar class in //services/network/crash_keys.h) once it is no longer used
+// below.
class ScopedRequestCrashKeys {
public:
- explicit ScopedRequestCrashKeys(const network::ResourceRequest& request);
- ~ScopedRequestCrashKeys();
+ static base::debug::CrashKeyString* GetRequestUrlCrashKey() {
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
+ "request_url", base::debug::CrashKeySize::Size256);
+ return crash_key;
+ }
+
+ static base::debug::CrashKeyString* GetRequestInitiatorCrashKey() {
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
+ "request_initiator", base::debug::CrashKeySize::Size64);
+ return crash_key;
+ }
+
+ explicit ScopedRequestCrashKeys(const network::ResourceRequest& request)
+ : url_(GetRequestUrlCrashKey(), request.url.possibly_invalid_spec()),
+ request_initiator_(GetRequestInitiatorCrashKey(),
+ base::OptionalOrNullptr(request.request_initiator)) {
+ }
+ ~ScopedRequestCrashKeys() = default;
ScopedRequestCrashKeys(const ScopedRequestCrashKeys&) = delete;
ScopedRequestCrashKeys& operator=(const ScopedRequestCrashKeys&) = delete;
@@ -133,26 +152,6 @@ class ScopedRequestCrashKeys {
url::debug::ScopedOriginCrashKey request_initiator_;
};
-base::debug::CrashKeyString* GetRequestUrlCrashKey() {
- static auto* crash_key = base::debug::AllocateCrashKeyString(
- "request_url", base::debug::CrashKeySize::Size256);
- return crash_key;
-}
-
-base::debug::CrashKeyString* GetRequestInitiatorCrashKey() {
- static auto* crash_key = base::debug::AllocateCrashKeyString(
- "request_initiator", base::debug::CrashKeySize::Size64);
- return crash_key;
-}
-
-ScopedRequestCrashKeys::ScopedRequestCrashKeys(
- const network::ResourceRequest& request)
- : url_(GetRequestUrlCrashKey(), request.url.possibly_invalid_spec()),
- request_initiator_(GetRequestInitiatorCrashKey(),
- base::OptionalOrNullptr(request.request_initiator)) {}
-
-ScopedRequestCrashKeys::~ScopedRequestCrashKeys() = default;
-
} // namespace
ChildPendingURLLoaderFactoryBundle::ChildPendingURLLoaderFactoryBundle() =
@@ -238,24 +237,6 @@ network::mojom::URLLoaderFactory* ChildURLLoaderFactoryBundle::GetFactory(
if (base_result)
return base_result;
- // All renderer-initiated requests need to provide a value for
- // |request_initiator| - this is enforced by
- // CorsURLLoaderFactory::IsValidRequest (see the
- // InitiatorLockCompatibility::kNoInitiator case).
- DCHECK(request.request_initiator.has_value());
- if (is_deprecated_process_wide_factory_) {
- // The CHECK condition below (in a Renderer process) is also enforced later
- // (in the NetworkService process) by CorsURLLoaderFactory::IsValidRequest
- // (see the InitiatorLockCompatibility::kNoLock case) - this enforcement may
- // result in a renderer kill when the NetworkService is hosted in a separate
- // process from the Browser process. Despite the redundancy, we want to
- // also have the CHECK below, so that the Renderer process terminates
- // earlier, with a callstack that (unlike the NetworkService
- // mojo::ReportBadMessage) is hopefully useful for tracking down the source
- // of the problem.
- CHECK(request.request_initiator->opaque());
- }
-
InitDirectNetworkFactoryIfNecessary();
DCHECK(direct_network_factory_);
return direct_network_factory_.get();
@@ -293,14 +274,6 @@ void ChildURLLoaderFactoryBundle::CreateLoaderAndStart(
// special prefetch handling.
// TODO(horo): Move this routing logic to network service, when we will have
// the special prefetch handling in network service.
- if ((request.resource_type ==
- static_cast<int>(blink::mojom::ResourceType::kPrefetch)) &&
- prefetch_loader_factory_) {
- prefetch_loader_factory_->CreateLoaderAndStart(
- std::move(loader), routing_id, request_id, options, request,
- std::move(client), traffic_annotation);
- return;
- }
if ((request.load_flags & net::LOAD_PREFETCH) && prefetch_loader_factory_) {
// This is no-state prefetch (see
// WebURLRequest::GetLoadFlagsForWebUrlRequest).
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc b/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
index f759b9a5d3f..919102b97d3 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
@@ -4,79 +4,20 @@
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
-#include <memory>
#include <string>
-#include <utility>
#include "net/http/http_util.h"
#include "services/network/public/cpp/cors/cors.h"
-#include "services/network/public/cpp/cors/preflight_cache.h"
-#include "services/network/public/cpp/request_mode.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
-#include "url/gurl.h"
-#include "url/origin.h"
namespace blink {
namespace {
-base::Optional<std::string> GetHeaderValue(const HTTPHeaderMap& header_map,
- const AtomicString& header_name) {
- if (header_map.Contains(header_name)) {
- return header_map.Get(header_name).Latin1();
- }
- return base::nullopt;
-}
-
-network::cors::PreflightCache& GetPerThreadPreflightCache() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<network::cors::PreflightCache>,
- cache, ());
- return *cache;
-}
-
-base::Optional<std::string> GetOptionalHeaderValue(
- const HTTPHeaderMap& header_map,
- const AtomicString& header_name) {
- const AtomicString& result = header_map.Get(header_name);
- if (result.IsNull())
- return base::nullopt;
-
- return result.Ascii();
-}
-
-std::unique_ptr<net::HttpRequestHeaders> CreateNetHttpRequestHeaders(
- const HTTPHeaderMap& header_map) {
- std::unique_ptr<net::HttpRequestHeaders> request_headers =
- std::make_unique<net::HttpRequestHeaders>();
- for (HTTPHeaderMap::const_iterator i = header_map.begin(),
- end = header_map.end();
- i != end; ++i) {
- DCHECK(!i->key.IsNull());
- DCHECK(!i->value.IsNull());
- request_headers->SetHeader(i->key.Ascii(), i->value.Ascii());
- }
- return request_headers;
-}
-
-url::Origin AsUrlOrigin(const SecurityOrigin& origin) {
- // "file:" origin is treated like an opaque unique origin when
- // allow-file-access-from-files is not specified. Such origin is not
- // opaque (i.e., IsOpaque() returns false) but still serializes to
- // "null".
- return origin.ToString() == "null" ? url::Origin() : origin.ToUrlOrigin();
-}
-
// A parser for the value of the Access-Control-Expose-Headers header.
class HTTPHeaderNameListParser {
STACK_ALLOCATED();
@@ -159,165 +100,10 @@ class HTTPHeaderNameListParser {
namespace cors {
-base::Optional<network::CorsErrorStatus> CheckAccess(
- const KURL& response_url,
- const HTTPHeaderMap& response_header,
- network::mojom::CredentialsMode credentials_mode,
- const SecurityOrigin& origin) {
- return network::cors::CheckAccess(
- response_url,
- GetHeaderValue(response_header, http_names::kAccessControlAllowOrigin),
- GetHeaderValue(response_header,
- http_names::kAccessControlAllowCredentials),
- credentials_mode, AsUrlOrigin(origin));
-}
-
-base::Optional<network::CorsErrorStatus> CheckPreflightAccess(
- const KURL& response_url,
- const int response_status_code,
- const HTTPHeaderMap& response_header,
- network::mojom::CredentialsMode actual_credentials_mode,
- const SecurityOrigin& origin) {
- return network::cors::CheckPreflightAccess(
- response_url, response_status_code,
- GetHeaderValue(response_header, http_names::kAccessControlAllowOrigin),
- GetHeaderValue(response_header,
- http_names::kAccessControlAllowCredentials),
- actual_credentials_mode, AsUrlOrigin(origin));
-}
-
-base::Optional<network::CorsErrorStatus> CheckRedirectLocation(
- const KURL& url,
- network::mojom::RequestMode request_mode,
- const SecurityOrigin* origin,
- CorsFlag cors_flag) {
- base::Optional<url::Origin> origin_to_pass;
- if (origin)
- origin_to_pass = AsUrlOrigin(*origin);
-
- // Blink-side implementations rewrite the origin instead of setting the
- // tainted flag.
- return network::cors::CheckRedirectLocation(
- url, request_mode, origin_to_pass, cors_flag == CorsFlag::Set, false);
-}
-
-base::Optional<network::CorsErrorStatus> CheckExternalPreflight(
- const HTTPHeaderMap& response_header) {
- return network::cors::CheckExternalPreflight(
- GetHeaderValue(response_header, http_names::kAccessControlAllowExternal));
-}
-
bool IsCorsEnabledRequestMode(network::mojom::RequestMode request_mode) {
return network::cors::IsCorsEnabledRequestMode(request_mode);
}
-base::Optional<network::CorsErrorStatus> EnsurePreflightResultAndCacheOnSuccess(
- const HTTPHeaderMap& response_header_map,
- const String& origin,
- const KURL& request_url,
- const String& request_method,
- const HTTPHeaderMap& request_header_map,
- network::mojom::CredentialsMode request_credentials_mode) {
- DCHECK(!origin.IsNull());
- DCHECK(!request_method.IsNull());
-
- base::Optional<network::mojom::CorsError> error;
-
- std::unique_ptr<network::cors::PreflightResult> result =
- network::cors::PreflightResult::Create(
- request_credentials_mode,
- GetOptionalHeaderValue(response_header_map,
- http_names::kAccessControlAllowMethods),
- GetOptionalHeaderValue(response_header_map,
- http_names::kAccessControlAllowHeaders),
- GetOptionalHeaderValue(response_header_map,
- http_names::kAccessControlMaxAge),
- &error);
- if (error)
- return network::CorsErrorStatus(*error);
-
- base::Optional<network::CorsErrorStatus> status;
- status = result->EnsureAllowedCrossOriginMethod(request_method.Ascii());
- if (status)
- return status;
-
- // |is_revalidating| is not needed for blink-side CORS.
- constexpr bool is_revalidating = false;
- status = result->EnsureAllowedCrossOriginHeaders(
- *CreateNetHttpRequestHeaders(request_header_map), is_revalidating);
- if (status)
- return status;
-
- GetPerThreadPreflightCache().AppendEntry(
- url::Origin::Create(GURL(origin.Ascii())), request_url,
- net::NetworkIsolationKey(), std::move(result));
- return base::nullopt;
-}
-
-bool CheckIfRequestCanSkipPreflight(
- const String& origin,
- const KURL& url,
- network::mojom::CredentialsMode credentials_mode,
- const String& method,
- const HTTPHeaderMap& request_header_map) {
- DCHECK(!origin.IsNull());
- DCHECK(!method.IsNull());
-
- // |is_revalidating| is not needed for blink-side CORS.
- constexpr bool is_revalidating = false;
- return GetPerThreadPreflightCache().CheckIfRequestCanSkipPreflight(
- url::Origin::Create(GURL(origin.Ascii())), url,
- net::NetworkIsolationKey(), credentials_mode, method.Ascii(),
- *CreateNetHttpRequestHeaders(request_header_map), is_revalidating);
-}
-
-// Keep this in sync with the identical function
-// network::cors::CorsURLLoader::CalculateResponseTainting.
-//
-// This is the same as that function except using KURL and SecurityOrigin
-// instead of GURL and url::Origin. We can't combine them because converting
-// SecurityOrigin to url::Origin loses information about origins that are
-// allowed by SecurityPolicy.
-//
-// This function also doesn't use a |tainted_origin| flag because Blink loaders
-// mutate the origin instead of using such a flag.
-network::mojom::FetchResponseType CalculateResponseTainting(
- const KURL& url,
- network::mojom::RequestMode request_mode,
- const SecurityOrigin* origin,
- const SecurityOrigin* isolated_world_origin,
- CorsFlag cors_flag) {
- if (url.ProtocolIsData())
- return network::mojom::FetchResponseType::kBasic;
-
- if (cors_flag == CorsFlag::Set) {
- DCHECK(IsCorsEnabledRequestMode(request_mode));
- return network::mojom::FetchResponseType::kCors;
- }
-
- if (!origin) {
- // This is actually not defined in the fetch spec, but in this case CORS
- // is disabled so no one should care this value.
- return network::mojom::FetchResponseType::kBasic;
- }
-
- if (request_mode == network::mojom::RequestMode::kNoCors) {
- bool can_request = origin->CanRequest(url);
- if (!can_request && isolated_world_origin)
- can_request = isolated_world_origin->CanRequest(url);
- if (!can_request)
- return network::mojom::FetchResponseType::kOpaque;
- }
- return network::mojom::FetchResponseType::kBasic;
-}
-
-bool CalculateCredentialsFlag(
- network::mojom::CredentialsMode credentials_mode,
- network::mojom::FetchResponseType response_tainting) {
- return network::cors::CalculateCredentialsFlag(credentials_mode,
- response_tainting);
-}
-
bool IsCorsSafelistedMethod(const String& method) {
DCHECK(!method.IsNull());
return network::cors::IsCorsSafelistedMethod(method.Latin1());
@@ -327,9 +113,10 @@ bool IsCorsSafelistedContentType(const String& media_type) {
return network::cors::IsCorsSafelistedContentType(media_type.Latin1());
}
-bool IsNoCorsSafelistedHeaderName(const String& name) {
+bool IsNoCorsSafelistedHeader(const String& name, const String& value) {
DCHECK(!name.IsNull());
- return network::cors::IsNoCorsSafelistedHeaderName(name.Latin1());
+ DCHECK(!value.IsNull());
+ return network::cors::IsNoCorsSafelistedHeader(name.Latin1(), value.Latin1());
}
bool IsPrivilegedNoCorsHeaderName(const String& name) {
@@ -337,23 +124,9 @@ bool IsPrivilegedNoCorsHeaderName(const String& name) {
return network::cors::IsPrivilegedNoCorsHeaderName(name.Latin1());
}
-bool IsNoCorsSafelistedHeader(const String& name, const String& value) {
+bool IsNoCorsSafelistedHeaderName(const String& name) {
DCHECK(!name.IsNull());
- DCHECK(!value.IsNull());
- return network::cors::IsNoCorsSafelistedHeader(name.Latin1(), value.Latin1());
-}
-
-Vector<String> CorsUnsafeRequestHeaderNames(const HTTPHeaderMap& headers) {
- net::HttpRequestHeaders::HeaderVector in;
- for (const auto& entry : headers) {
- in.push_back(net::HttpRequestHeaders::HeaderKeyValuePair(
- entry.key.Latin1(), entry.value.Latin1()));
- }
-
- Vector<String> header_names;
- for (const auto& name : network::cors::CorsUnsafeRequestHeaderNames(in))
- header_names.push_back(WebString::FromLatin1(name));
- return header_names;
+ return network::cors::IsNoCorsSafelistedHeaderName(name.Latin1());
}
PLATFORM_EXPORT Vector<String> PrivilegedNoCorsHeaderNames() {
@@ -368,8 +141,13 @@ bool IsForbiddenHeaderName(const String& name) {
}
bool ContainsOnlyCorsSafelistedHeaders(const HTTPHeaderMap& header_map) {
- Vector<String> header_names = CorsUnsafeRequestHeaderNames(header_map);
- return header_names.IsEmpty();
+ net::HttpRequestHeaders::HeaderVector in;
+ for (const auto& entry : header_map) {
+ in.push_back(net::HttpRequestHeaders::HeaderKeyValuePair(
+ entry.key.Latin1(), entry.value.Latin1()));
+ }
+
+ return network::cors::CorsUnsafeRequestHeaderNames(in).empty();
}
bool ContainsOnlyCorsSafelistedOrForbiddenHeaders(
@@ -476,6 +254,7 @@ bool IsNoCorsAllowedContext(mojom::blink::RequestContextType context) {
case mojom::blink::RequestContextType::SHARED_WORKER:
case mojom::blink::RequestContextType::VIDEO:
case mojom::blink::RequestContextType::WORKER:
+ case mojom::blink::RequestContextType::SUBRESOURCE_WEBBUNDLE:
return true;
default:
return false;
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors.h b/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
index e76d68adaa2..f3886e799e6 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
@@ -31,78 +31,17 @@ enum class CorsFlag : uint8_t {
namespace cors {
// Thin wrapper functions below are for calling ::network::cors functions from
-// Blink core. Once Out-of-renderer CORS is enabled, following functions will
-// be removed.
-PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckAccess(
- const KURL&,
- const HTTPHeaderMap&,
- network::mojom::CredentialsMode,
- const SecurityOrigin&);
-
-PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckPreflightAccess(
- const KURL&,
- const int response_status_code,
- const HTTPHeaderMap&,
- network::mojom::CredentialsMode,
- const SecurityOrigin&);
-
-PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckRedirectLocation(
- const KURL&,
- network::mojom::RequestMode,
- const SecurityOrigin*,
- CorsFlag);
-
-PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckExternalPreflight(
- const HTTPHeaderMap&);
-
+// Blink core.
PLATFORM_EXPORT bool IsCorsEnabledRequestMode(network::mojom::RequestMode);
-
-PLATFORM_EXPORT base::Optional<network::CorsErrorStatus>
-EnsurePreflightResultAndCacheOnSuccess(
- const HTTPHeaderMap& response_header_map,
- const String& origin,
- const KURL& request_url,
- const String& request_method,
- const HTTPHeaderMap& request_header_map,
- network::mojom::CredentialsMode request_credentials_mode);
-
-PLATFORM_EXPORT bool CheckIfRequestCanSkipPreflight(
- const String& origin,
- const KURL&,
- network::mojom::CredentialsMode,
- const String& method,
- const HTTPHeaderMap& request_header_map);
-
-// Returns the response tainting value
-// (https://fetch.spec.whatwg.org/#concept-request-response-tainting) for a
-// request and the CORS flag, as specified in
-// https://fetch.spec.whatwg.org/#main-fetch.
-PLATFORM_EXPORT network::mojom::FetchResponseType CalculateResponseTainting(
- const KURL& url,
- network::mojom::RequestMode request_mode,
- const SecurityOrigin* origin,
- const SecurityOrigin* isolated_world_origin,
- CorsFlag cors_flag);
-
-PLATFORM_EXPORT bool CalculateCredentialsFlag(
- network::mojom::CredentialsMode credentials_mode,
- network::mojom::FetchResponseType response_tainting);
-
-// Thin wrapper functions that will not be removed even after out-of-renderer
-// CORS is enabled.
PLATFORM_EXPORT bool IsCorsSafelistedMethod(const String& method);
PLATFORM_EXPORT bool IsCorsSafelistedContentType(const String&);
PLATFORM_EXPORT bool IsNoCorsSafelistedHeader(const String& name,
const String& value);
PLATFORM_EXPORT bool IsPrivilegedNoCorsHeaderName(const String& name);
PLATFORM_EXPORT bool IsNoCorsSafelistedHeaderName(const String& name);
-PLATFORM_EXPORT Vector<String> CorsUnsafeRequestHeaderNames(
- const HTTPHeaderMap& headers);
PLATFORM_EXPORT Vector<String> PrivilegedNoCorsHeaderNames();
PLATFORM_EXPORT bool IsForbiddenHeaderName(const String& name);
PLATFORM_EXPORT bool ContainsOnlyCorsSafelistedHeaders(const HTTPHeaderMap&);
-PLATFORM_EXPORT bool ContainsOnlyCorsSafelistedOrForbiddenHeaders(
- const HTTPHeaderMap&);
PLATFORM_EXPORT bool IsOkStatus(int status);
@@ -114,7 +53,6 @@ PLATFORM_EXPORT bool IsOkStatus(int status);
// |kNavigate|.
// This should be identical to CalculateCorsFlag defined in
// //services/network/cors/cors_url_loader.cc.
-// This function will be removed when out-of-renderer CORS is enabled.
PLATFORM_EXPORT bool CalculateCorsFlag(
const KURL& url,
const SecurityOrigin* initiator_origin,
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc b/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
index 173f852a577..33a82641852 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
@@ -7,7 +7,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
@@ -101,87 +100,6 @@ TEST_F(CorsExposedHeadersTest, Asterisk) {
HTTPHeaderSet({"a", "b", "*"}));
}
-// Keep this in sync with the CalculateResponseTainting test in
-// services/network/cors/cors_url_loader_unittest.cc.
-TEST(CorsTest, CalculateResponseTainting) {
- using network::mojom::FetchResponseType;
- using network::mojom::RequestMode;
-
- const KURL same_origin_url("https://example.com/");
- const KURL cross_origin_url("https://example2.com/");
- scoped_refptr<SecurityOrigin> origin_refptr =
- SecurityOrigin::Create(same_origin_url);
- const SecurityOrigin* origin = origin_refptr.get();
- const SecurityOrigin* no_origin = nullptr;
-
- // CORS flag is false, same-origin request
- EXPECT_EQ(
- FetchResponseType::kBasic,
- cors::CalculateResponseTainting(same_origin_url, RequestMode::kSameOrigin,
- origin, nullptr, CorsFlag::Unset));
- EXPECT_EQ(
- FetchResponseType::kBasic,
- cors::CalculateResponseTainting(same_origin_url, RequestMode::kNoCors,
- origin, nullptr, CorsFlag::Unset));
- EXPECT_EQ(FetchResponseType::kBasic,
- cors::CalculateResponseTainting(same_origin_url, RequestMode::kCors,
- origin, nullptr, CorsFlag::Unset));
- EXPECT_EQ(FetchResponseType::kBasic,
- cors::CalculateResponseTainting(
- same_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
- nullptr, CorsFlag::Unset));
- EXPECT_EQ(
- FetchResponseType::kBasic,
- cors::CalculateResponseTainting(same_origin_url, RequestMode::kNavigate,
- origin, nullptr, CorsFlag::Unset));
-
- // CORS flag is false, cross-origin request
- EXPECT_EQ(
- FetchResponseType::kOpaque,
- cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNoCors,
- origin, nullptr, CorsFlag::Unset));
- EXPECT_EQ(
- FetchResponseType::kBasic,
- cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNavigate,
- origin, nullptr, CorsFlag::Unset));
-
- // CORS flag is true, same-origin request
- EXPECT_EQ(FetchResponseType::kCors,
- cors::CalculateResponseTainting(same_origin_url, RequestMode::kCors,
- origin, nullptr, CorsFlag::Set));
- EXPECT_EQ(FetchResponseType::kCors,
- cors::CalculateResponseTainting(
- same_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
- nullptr, CorsFlag::Set));
-
- // CORS flag is true, cross-origin request
- EXPECT_EQ(FetchResponseType::kCors, cors::CalculateResponseTainting(
- cross_origin_url, RequestMode::kCors,
- origin, nullptr, CorsFlag::Set));
- EXPECT_EQ(FetchResponseType::kCors,
- cors::CalculateResponseTainting(
- cross_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
- nullptr, CorsFlag::Set));
-
- // Origin is not provided.
- EXPECT_EQ(
- FetchResponseType::kBasic,
- cors::CalculateResponseTainting(same_origin_url, RequestMode::kNoCors,
- no_origin, nullptr, CorsFlag::Unset));
- EXPECT_EQ(
- FetchResponseType::kBasic,
- cors::CalculateResponseTainting(same_origin_url, RequestMode::kNavigate,
- no_origin, nullptr, CorsFlag::Unset));
- EXPECT_EQ(
- FetchResponseType::kBasic,
- cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNoCors,
- no_origin, nullptr, CorsFlag::Unset));
- EXPECT_EQ(
- FetchResponseType::kBasic,
- cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNavigate,
- no_origin, nullptr, CorsFlag::Unset));
-}
-
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/DEPS b/chromium/third_party/blink/renderer/platform/loader/fetch/DEPS
index 6b62d911e62..2c306ca7b4d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/DEPS
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+net/base/ip_endpoint.h",
+ "+net/base/schemeful_site.h",
"+net/dns/public",
"+services/network/public/cpp/fetch_api_utils.h",
"+services/network/public/cpp/optional_trust_token_params.h",
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h b/chromium/third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h
new file mode 100644
index 00000000000..ea87bb15a53
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h
@@ -0,0 +1,43 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_BACK_FORWARD_CACHE_LOADER_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_BACK_FORWARD_CACHE_LOADER_HELPER_H_
+
+#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-forward.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+// Helper class for in-flight network request support for back-forward cache.
+class PLATFORM_EXPORT BackForwardCacheLoaderHelper
+ : public GarbageCollected<BackForwardCacheLoaderHelper> {
+ public:
+ // Evict the page from BackForwardCache. Should be called when handling an
+ // event which can't proceed if the page is in BackForwardCache and can't be
+ // easily deferred to handle later, for example network redirect handling.
+ virtual void EvictFromBackForwardCache(mojom::RendererEvictionReason reason) {
+ }
+
+ // Called when a network request buffered an additional `num_bytes` while the
+ // in back-forward cache. May be called multiple times.
+ virtual void DidBufferLoadWhileInBackForwardCache(size_t num_bytes) {}
+
+ // Returns true if we can still continue buffering data from in-flight network
+ // requests while in back-forward cache.
+ virtual bool CanContinueBufferingWhileInBackForwardCache() const {
+ return false;
+ }
+
+ virtual void Detach() {}
+
+ virtual void Trace(Visitor*) const {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_BACK_FORWARD_CACHE_LOADER_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
index b33a8bc2cf0..60743ac1d79 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
@@ -19,7 +19,7 @@ BufferingBytesConsumer* BufferingBytesConsumer::CreateWithDelay(
BytesConsumer* bytes_consumer,
scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner) {
return MakeGarbageCollected<BufferingBytesConsumer>(
- util::PassKey<BufferingBytesConsumer>(), bytes_consumer,
+ base::PassKey<BufferingBytesConsumer>(), bytes_consumer,
std::move(timer_task_runner),
base::TimeDelta::FromMilliseconds(kDelayMilliseconds));
}
@@ -28,12 +28,12 @@ BufferingBytesConsumer* BufferingBytesConsumer::CreateWithDelay(
BufferingBytesConsumer* BufferingBytesConsumer::Create(
BytesConsumer* bytes_consumer) {
return MakeGarbageCollected<BufferingBytesConsumer>(
- util::PassKey<BufferingBytesConsumer>(), bytes_consumer, nullptr,
+ base::PassKey<BufferingBytesConsumer>(), bytes_consumer, nullptr,
base::TimeDelta());
}
BufferingBytesConsumer::BufferingBytesConsumer(
- util::PassKey<BufferingBytesConsumer> key,
+ base::PassKey<BufferingBytesConsumer> key,
BytesConsumer* bytes_consumer,
scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner,
base::TimeDelta buffering_start_delay)
@@ -165,6 +165,7 @@ BytesConsumer::Error BufferingBytesConsumer::GetError() const {
void BufferingBytesConsumer::Trace(Visitor* visitor) const {
visitor->Trace(bytes_consumer_);
visitor->Trace(client_);
+ visitor->Trace(timer_);
BytesConsumer::Trace(visitor);
BytesConsumer::Client::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h
index 8ca2f349ca3..44b8a663a76 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
-#include "base/util/type_safety/pass_key.h"
+#include "base/types/pass_key.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -46,7 +46,7 @@ class PLATFORM_EXPORT BufferingBytesConsumer final
// Use the Create*() factory methods instead of direct instantiation.
BufferingBytesConsumer(
- util::PassKey<BufferingBytesConsumer> key,
+ base::PassKey<BufferingBytesConsumer> key,
BytesConsumer* bytes_consumer,
scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner,
base::TimeDelta buffering_start_delay);
@@ -87,7 +87,7 @@ class PLATFORM_EXPORT BufferingBytesConsumer final
void BufferData();
const Member<BytesConsumer> bytes_consumer_;
- TaskRunnerTimer<BufferingBytesConsumer> timer_;
+ HeapTaskRunnerTimer<BufferingBytesConsumer> timer_;
Deque<Vector<char>> buffer_;
size_t offset_for_first_chunk_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
index 037092cf783..d77b39794df 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
@@ -32,8 +32,8 @@ class BufferingBytesConsumerTest : public testing::Test {
mojo::ScopedDataPipeConsumerHandle consumer_handle;
mojo::ScopedDataPipeProducerHandle producer_handle;
CHECK_EQ(MOJO_RESULT_OK,
- mojo::CreateDataPipe(&data_pipe_options, &producer_handle,
- &consumer_handle));
+ mojo::CreateDataPipe(&data_pipe_options, producer_handle,
+ consumer_handle));
return consumer_handle;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc
new file mode 100644
index 00000000000..d9f2f162d1b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler_test.cc
@@ -0,0 +1,135 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this sink code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+namespace {
+
+class MockPlatform final : public TestingPlatformSupportWithMockScheduler {
+ public:
+ MockPlatform() = default;
+ ~MockPlatform() override = default;
+
+ // From blink::Platform:
+ void CacheMetadata(mojom::blink::CodeCacheType cache_type,
+ const WebURL& url,
+ base::Time,
+ const uint8_t*,
+ size_t) override {
+ cached_urls_.push_back(url);
+ }
+
+ void CacheMetadataInCacheStorage(const WebURL& url,
+ base::Time,
+ const uint8_t*,
+ size_t,
+ const WebSecurityOrigin&,
+ const WebString&) override {
+ cache_storage_cached_urls_.push_back(url);
+ }
+
+ const Vector<WebURL>& CachedURLs() const { return cached_urls_; }
+ const Vector<WebURL>& CacheStorageCachedURLs() const {
+ return cache_storage_cached_urls_;
+ }
+
+ private:
+ Vector<WebURL> cached_urls_;
+ Vector<WebURL> cache_storage_cached_urls_;
+};
+
+ResourceResponse CreateTestResourceResponse() {
+ ResourceResponse response(KURL("https://example.com/"));
+ response.SetHttpStatusCode(200);
+ return response;
+}
+
+void SendDataFor(const ResourceResponse& response) {
+ constexpr uint8_t kTestData[] = {1, 2, 3, 4, 5};
+ std::unique_ptr<CachedMetadataSender> sender = CachedMetadataSender::Create(
+ response, mojom::blink::CodeCacheType::kJavascript,
+ SecurityOrigin::Create(response.CurrentRequestUrl()));
+ sender->Send(kTestData, sizeof(kTestData));
+}
+
+TEST(CachedMetadataHandlerTest, SendsMetadataToPlatform) {
+ ScopedTestingPlatformSupport<MockPlatform> mock;
+ ResourceResponse response(CreateTestResourceResponse());
+
+ SendDataFor(response);
+ EXPECT_EQ(1u, mock->CachedURLs().size());
+ EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
+}
+
+TEST(
+ CachedMetadataHandlerTest,
+ DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithSyntheticResponse) {
+ ScopedTestingPlatformSupport<MockPlatform> mock;
+
+ // Equivalent to service worker calling respondWith(new Response(...))
+ ResourceResponse response(CreateTestResourceResponse());
+ response.SetWasFetchedViaServiceWorker(true);
+
+ SendDataFor(response);
+ EXPECT_EQ(0u, mock->CachedURLs().size());
+ EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
+}
+
+TEST(
+ CachedMetadataHandlerTest,
+ SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithPassThroughResponse) {
+ ScopedTestingPlatformSupport<MockPlatform> mock;
+
+ // Equivalent to service worker calling respondWith(fetch(evt.request.url));
+ ResourceResponse response(CreateTestResourceResponse());
+ response.SetWasFetchedViaServiceWorker(true);
+ response.SetUrlListViaServiceWorker({response.CurrentRequestUrl()});
+
+ SendDataFor(response);
+ EXPECT_EQ(1u, mock->CachedURLs().size());
+ EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
+}
+
+TEST(
+ CachedMetadataHandlerTest,
+ DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithDifferentURLResponse) {
+ ScopedTestingPlatformSupport<MockPlatform> mock;
+
+ // Equivalent to service worker calling respondWith(fetch(some_different_url))
+ ResourceResponse response(CreateTestResourceResponse());
+ response.SetWasFetchedViaServiceWorker(true);
+ response.SetUrlListViaServiceWorker(
+ {KURL("https://example.com/different/url")});
+
+ SendDataFor(response);
+ EXPECT_EQ(0u, mock->CachedURLs().size());
+ EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
+}
+
+TEST(CachedMetadataHandlerTest,
+ SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithCacheResponse) {
+ ScopedTestingPlatformSupport<MockPlatform> mock;
+
+ // Equivalent to service worker calling respondWith(cache.match(some_url));
+ ResourceResponse response(CreateTestResourceResponse());
+ response.SetWasFetchedViaServiceWorker(true);
+ response.SetCacheStorageCacheName("dummy");
+
+ SendDataFor(response);
+ EXPECT_EQ(0u, mock->CachedURLs().size());
+ EXPECT_EQ(1u, mock->CacheStorageCachedURLs().size());
+}
+
+} // namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
index 638a7f6b0b6..1ff152ca7af 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
@@ -7,13 +7,14 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "services/network/public/cpp/client_hints.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "url/origin.h"
namespace blink {
@@ -34,6 +35,18 @@ void ClientHintsPreferences::UpdateFrom(
}
}
+void ClientHintsPreferences::CombineWith(
+ const ClientHintsPreferences& preferences) {
+ for (size_t i = 0;
+ i < static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) + 1;
+ ++i) {
+ network::mojom::WebClientHintsType type =
+ static_cast<network::mojom::WebClientHintsType>(i);
+ if (preferences.ShouldSend(type))
+ SetShouldSend(type);
+ }
+}
+
bool ClientHintsPreferences::UserAgentClientHintEnabled() {
return RuntimeEnabledFeatures::UserAgentClientHintEnabled() &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -83,8 +96,7 @@ void ClientHintsPreferences::UpdateFromHttpEquivAcceptCH(
// static
bool ClientHintsPreferences::IsClientHintsAllowed(const KURL& url) {
return (url.ProtocolIs("http") || url.ProtocolIs("https")) &&
- (SecurityOrigin::IsSecure(url) ||
- SecurityOrigin::Create(url)->IsLocalhost());
+ network::IsOriginPotentiallyTrustworthy(url::Origin::Create(url));
}
WebEnabledClientHints ClientHintsPreferences::GetWebEnabledClientHints() const {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
index 0d1a88e2322..7083040b28e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
@@ -31,6 +31,7 @@ class PLATFORM_EXPORT ClientHintsPreferences {
ClientHintsPreferences();
void UpdateFrom(const ClientHintsPreferences&);
+ void CombineWith(const ClientHintsPreferences&);
// Parses <meta http-equiv="accept-ch"> value |header_value|, and updates
// |this| to enable the requested client hints. |url| is the URL of the page.
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
index b1c50f139e5..a0db4ee39df 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
@@ -45,16 +45,18 @@ TEST_F(ClientHintsPreferencesTest, BasicSecure) {
false, false, false},
{"DPRW", false, false, false, false, false, false, false, false, false,
false, false, false},
- {"ua", false, false, false, false, false, false, false, true, false,
- false, false, false},
- {"ua-arch", false, false, false, false, false, false, false, false, true,
- false, false, false},
- {"ua-platform", false, false, false, false, false, false, false, false,
- false, true, false, false},
- {"ua-model", false, false, false, false, false, false, false, false,
- false, false, true, false},
- {"ua, ua-arch, ua-platform, ua-model, ua-full-version", false, false,
- false, false, false, false, false, true, true, true, true, true},
+ {"sec-ch-ua", false, false, false, false, false, false, false, true,
+ false, false, false, false},
+ {"sec-ch-ua-arch", false, false, false, false, false, false, false, false,
+ true, false, false, false},
+ {"sec-ch-ua-platform", false, false, false, false, false, false, false,
+ false, false, true, false, false},
+ {"sec-ch-ua-model", false, false, false, false, false, false, false,
+ false, false, false, true, false},
+ {"sec-ch-ua, sec-ch-ua-arch, sec-ch-ua-platform, sec-ch-ua-model, "
+ "sec-ch-ua-full-version",
+ false, false, false, false, false, false, false, true, true, true, true,
+ true},
};
for (const auto& test_case : cases) {
@@ -254,8 +256,10 @@ TEST_F(ClientHintsPreferencesTest, ParseHeaders) {
false, false, false, false, false},
{"dpr rtt", false, false, false, false, false, false, false, false, false,
false, false, false, false},
- {"ua, ua-arch, ua-platform, ua-model, ua-full-version", false, false,
- false, false, false, false, false, false, true, true, true, true, true},
+ {"sec-ch-ua, sec-ch-ua-arch, sec-ch-ua-platform, sec-ch-ua-model, "
+ "sec-ch-ua-full-version",
+ false, false, false, false, false, false, false, false, true, true, true,
+ true, true},
};
for (const auto& test : test_cases) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h b/chromium/third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h
index 2da56da0848..4093593334a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h
@@ -7,6 +7,8 @@
namespace blink {
+// This corresponds to the CORS settings attributes defined in the HTML spec:
+// https://html.spec.whatwg.org/C/#cors-settings-attributes
enum CrossOriginAttributeValue {
kCrossOriginAttributeNotSet,
kCrossOriginAttributeAnonymous,
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc
index ec03ab4e89b..9ae4783e87a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer_test.cc
@@ -22,24 +22,26 @@ class DataPipeBytesConsumerTest : public testing::Test {
};
TEST_F(DataPipeBytesConsumerTest, TwoPhaseRead) {
- mojo::DataPipe pipe;
- ASSERT_TRUE(pipe.producer_handle.is_valid());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
const std::string kData = "Such hospitality. I'm underwhelmed.";
uint32_t write_size = kData.size();
- MojoResult rv = pipe.producer_handle->WriteData(kData.c_str(), &write_size,
- MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult rv = producer_handle->WriteData(kData.c_str(), &write_size,
+ MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, rv);
ASSERT_EQ(kData.size(), write_size);
// Close the producer so the consumer will reach the kDone state after
// completion is signaled below.
- pipe.producer_handle.reset();
+ producer_handle.reset();
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
- task_runner_, std::move(pipe.consumer_handle), &notifier);
+ task_runner_, std::move(consumer_handle), &notifier);
notifier->SignalComplete();
auto result = MakeGarbageCollected<BytesConsumerTestReader>(consumer)->Run(
task_runner_.get());
@@ -48,22 +50,24 @@ TEST_F(DataPipeBytesConsumerTest, TwoPhaseRead) {
}
TEST_F(DataPipeBytesConsumerTest, TwoPhaseRead_SignalError) {
- mojo::DataPipe pipe;
- ASSERT_TRUE(pipe.producer_handle.is_valid());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
const std::string kData = "Such hospitality. I'm underwhelmed.";
uint32_t write_size = kData.size();
- MojoResult rv = pipe.producer_handle->WriteData(kData.c_str(), &write_size,
- MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult rv = producer_handle->WriteData(kData.c_str(), &write_size,
+ MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, rv);
ASSERT_EQ(kData.size(), write_size);
- pipe.producer_handle.reset();
+ producer_handle.reset();
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
- task_runner_, std::move(pipe.consumer_handle), &notifier);
+ task_runner_, std::move(consumer_handle), &notifier);
// Then explicitly signal an error. This should override the pipe completion
// and result in kError.
@@ -79,12 +83,14 @@ TEST_F(DataPipeBytesConsumerTest, TwoPhaseRead_SignalError) {
// must be called for the DataPipeBytesConsumer to reach the closed
// state.
TEST_F(DataPipeBytesConsumerTest, EndOfPipeBeforeComplete) {
- mojo::DataPipe pipe;
- ASSERT_TRUE(pipe.producer_handle.is_valid());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
- task_runner_, std::move(pipe.consumer_handle), &notifier);
+ task_runner_, std::move(consumer_handle), &notifier);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
@@ -94,7 +100,7 @@ TEST_F(DataPipeBytesConsumerTest, EndOfPipeBeforeComplete) {
Result rv = consumer->BeginRead(&buffer, &available);
EXPECT_EQ(Result::kShouldWait, rv);
- pipe.producer_handle.reset();
+ producer_handle.reset();
rv = consumer->BeginRead(&buffer, &available);
EXPECT_EQ(Result::kShouldWait, rv);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
@@ -107,12 +113,14 @@ TEST_F(DataPipeBytesConsumerTest, EndOfPipeBeforeComplete) {
}
TEST_F(DataPipeBytesConsumerTest, CompleteBeforeEndOfPipe) {
- mojo::DataPipe pipe;
- ASSERT_TRUE(pipe.producer_handle.is_valid());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
- task_runner_, std::move(pipe.consumer_handle), &notifier);
+ task_runner_, std::move(consumer_handle), &notifier);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
@@ -128,7 +136,7 @@ TEST_F(DataPipeBytesConsumerTest, CompleteBeforeEndOfPipe) {
rv = consumer->BeginRead(&buffer, &available);
EXPECT_EQ(Result::kShouldWait, rv);
- pipe.producer_handle.reset();
+ producer_handle.reset();
rv = consumer->BeginRead(&buffer, &available);
EXPECT_EQ(Result::kDone, rv);
EXPECT_EQ(PublicState::kClosed, consumer->GetPublicState());
@@ -138,12 +146,14 @@ TEST_F(DataPipeBytesConsumerTest, CompleteBeforeEndOfPipe) {
// errored state immediately without waiting for the end of the
// DataPipe.
TEST_F(DataPipeBytesConsumerTest, EndOfPipeBeforeError) {
- mojo::DataPipe pipe;
- ASSERT_TRUE(pipe.producer_handle.is_valid());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
- task_runner_, std::move(pipe.consumer_handle), &notifier);
+ task_runner_, std::move(consumer_handle), &notifier);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
@@ -153,7 +163,7 @@ TEST_F(DataPipeBytesConsumerTest, EndOfPipeBeforeError) {
Result rv = consumer->BeginRead(&buffer, &available);
EXPECT_EQ(Result::kShouldWait, rv);
- pipe.producer_handle.reset();
+ producer_handle.reset();
rv = consumer->BeginRead(&buffer, &available);
EXPECT_EQ(Result::kShouldWait, rv);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
@@ -170,8 +180,7 @@ TEST_F(DataPipeBytesConsumerTest, SignalSizeBeforeRead) {
mojo::ScopedDataPipeProducerHandle writable;
const MojoCreateDataPipeOptions options{
sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 0};
- ASSERT_EQ(MOJO_RESULT_OK,
- mojo::CreateDataPipe(&options, &writable, &readable));
+ ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, writable, readable));
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
task_runner_, std::move(readable), &notifier);
@@ -212,8 +221,7 @@ TEST_F(DataPipeBytesConsumerTest, SignalExcessSizeBeforeEndOfData) {
mojo::ScopedDataPipeProducerHandle writable;
const MojoCreateDataPipeOptions options{
sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 0};
- ASSERT_EQ(MOJO_RESULT_OK,
- mojo::CreateDataPipe(&options, &writable, &readable));
+ ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, writable, readable));
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
task_runner_, std::move(readable), &notifier);
@@ -240,8 +248,7 @@ TEST_F(DataPipeBytesConsumerTest, SignalExcessSizeAfterEndOfData) {
mojo::ScopedDataPipeProducerHandle writable;
const MojoCreateDataPipeOptions options{
sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 0};
- ASSERT_EQ(MOJO_RESULT_OK,
- mojo::CreateDataPipe(&options, &writable, &readable));
+ ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, writable, readable));
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
task_runner_, std::move(readable), &notifier);
@@ -268,8 +275,7 @@ TEST_F(DataPipeBytesConsumerTest, SignalSizeAfterRead) {
mojo::ScopedDataPipeProducerHandle writable;
const MojoCreateDataPipeOptions options{
sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 0};
- ASSERT_EQ(MOJO_RESULT_OK,
- mojo::CreateDataPipe(&options, &writable, &readable));
+ ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, writable, readable));
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
@@ -300,12 +306,14 @@ TEST_F(DataPipeBytesConsumerTest, SignalSizeAfterRead) {
}
TEST_F(DataPipeBytesConsumerTest, ErrorBeforeEndOfPipe) {
- mojo::DataPipe pipe;
- ASSERT_TRUE(pipe.producer_handle.is_valid());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
- task_runner_, std::move(pipe.consumer_handle), &notifier);
+ task_runner_, std::move(consumer_handle), &notifier);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
@@ -321,7 +329,7 @@ TEST_F(DataPipeBytesConsumerTest, ErrorBeforeEndOfPipe) {
rv = consumer->BeginRead(&buffer, &available);
EXPECT_EQ(Result::kError, rv);
- pipe.producer_handle.reset();
+ producer_handle.reset();
rv = consumer->BeginRead(&buffer, &available);
EXPECT_EQ(Result::kError, rv);
EXPECT_EQ(PublicState::kErrored, consumer->GetPublicState());
@@ -330,12 +338,14 @@ TEST_F(DataPipeBytesConsumerTest, ErrorBeforeEndOfPipe) {
// Verify that draining the DataPipe and SignalComplete() will
// close the DataPipeBytesConsumer.
TEST_F(DataPipeBytesConsumerTest, DrainPipeBeforeComplete) {
- mojo::DataPipe pipe;
- ASSERT_TRUE(pipe.producer_handle.is_valid());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
- task_runner_, std::move(pipe.consumer_handle), &notifier);
+ task_runner_, std::move(consumer_handle), &notifier);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
@@ -360,12 +370,14 @@ TEST_F(DataPipeBytesConsumerTest, DrainPipeBeforeComplete) {
}
TEST_F(DataPipeBytesConsumerTest, CompleteBeforeDrainPipe) {
- mojo::DataPipe pipe;
- ASSERT_TRUE(pipe.producer_handle.is_valid());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
DataPipeBytesConsumer::CompletionNotifier* notifier = nullptr;
DataPipeBytesConsumer* consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
- task_runner_, std::move(pipe.consumer_handle), &notifier);
+ task_runner_, std::move(consumer_handle), &notifier);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
index 4558e08606d..a12b2b814d8 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
@@ -8,73 +8,40 @@
#include "mojo/public/cpp/base/file_path_mojom_traits.h"
#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h"
#include "third_party/blink/renderer/platform/network/form_data_encoder.h"
#include "third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h"
namespace mojo {
// static
-WTF::Vector<blink::mojom::blink::FetchAPIDataElementPtr>
+WTF::Vector<network::DataElement>
StructTraits<blink::mojom::FetchAPIRequestBodyDataView,
blink::ResourceRequestBody>::elements(blink::ResourceRequestBody&
mutable_body) {
- WTF::Vector<blink::mojom::blink::FetchAPIDataElementPtr> out_elements;
- const auto& body = mutable_body;
- if (body.IsEmpty()) {
- return out_elements;
+ scoped_refptr<network::ResourceRequestBody> network_body;
+ if (auto form_body = mutable_body.FormBody()) {
+ // Here we need to keep the original body, because other members such as
+ // `identifier` are on the form body.
+ network_body = NetworkResourceRequestBodyFor(
+ blink::ResourceRequestBody(form_body),
+ /*allow_http1_for_streaming_upload=*/false);
+ } else if (mutable_body.StreamBody()) {
+ // Here we don't need to keep the original body (and it's impossible to do
+ // so, because the streaming body is not copyable).
+ network_body = NetworkResourceRequestBodyFor(
+ std::move(mutable_body), /*allow_http1_for_streaming_upload=*/false);
}
-
- if (mutable_body.StreamBody()) {
- auto out = blink::mojom::blink::FetchAPIDataElement::New();
- out->type = network::mojom::DataElementType::kReadOnceStream;
- out->chunked_data_pipe_getter = mutable_body.TakeStreamBody();
- out_elements.push_back(std::move(out));
- return out_elements;
+ if (!network_body) {
+ return WTF::Vector<network::DataElement>();
}
-
- DCHECK(body.FormBody());
- for (const auto& element : body.FormBody()->elements_) {
- auto out = blink::mojom::blink::FetchAPIDataElement::New();
- switch (element.type_) {
- case blink::FormDataElement::kData:
- out->type = network::mojom::DataElementType::kBytes;
- out->buf.ReserveCapacity(element.data_.size());
- for (const char c : element.data_) {
- out->buf.push_back(static_cast<uint8_t>(c));
- }
- break;
- case blink::FormDataElement::kEncodedFile:
- out->type = network::mojom::DataElementType::kFile;
- out->path = base::FilePath::FromUTF8Unsafe(element.filename_.Utf8());
- out->offset = element.file_start_;
- out->length = element.file_length_;
- out->expected_modification_time =
- element.expected_file_modification_time_.value_or(base::Time());
- break;
- case blink::FormDataElement::kEncodedBlob: {
- out->type = network::mojom::DataElementType::kDataPipe;
- out->length = element.optional_blob_data_handle_->size();
-
- mojo::Remote<blink::mojom::blink::Blob> blob_remote(
- mojo::PendingRemote<blink::mojom::blink::Blob>(
- element.optional_blob_data_handle_->CloneBlobRemote()
- .PassPipe(),
- blink::mojom::blink::Blob::Version_));
- blob_remote->AsDataPipeGetter(
- out->data_pipe_getter.InitWithNewPipeAndPassReceiver());
- break;
- }
- case blink::FormDataElement::kDataPipe:
- out->type = network::mojom::DataElementType::kDataPipe;
- if (element.data_pipe_getter_) {
- element.data_pipe_getter_->GetDataPipeGetter()->Clone(
- out->data_pipe_getter.InitWithNewPipeAndPassReceiver());
- }
- break;
- }
- out_elements.push_back(std::move(out));
+ WTF::Vector<network::DataElement> out_elements;
+ DCHECK(network_body->elements_mutable());
+ for (auto& element : *network_body->elements_mutable()) {
+ out_elements.emplace_back(std::move(element));
}
return out_elements;
}
@@ -89,73 +56,58 @@ bool StructTraits<blink::mojom::FetchAPIRequestBodyDataView,
return true;
}
- mojo::ArrayDataView<blink::mojom::FetchAPIDataElementDataView> elements_view;
+ mojo::ArrayDataView<network::mojom::DataElementDataView> elements_view;
in.GetElementsDataView(&elements_view);
if (elements_view.size() == 1) {
- blink::mojom::FetchAPIDataElementDataView view;
+ network::mojom::DataElementDataView view;
elements_view.GetDataView(0, &view);
- network::mojom::DataElementType type;
- if (!view.ReadType(&type)) {
- return false;
- }
- if (type == network::mojom::DataElementType::kReadOnceStream) {
- auto chunked_data_pipe_getter = view.TakeChunkedDataPipeGetter<
- mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>>();
- *out = blink::ResourceRequestBody(std::move(chunked_data_pipe_getter));
+ DCHECK(!view.is_null());
+ if (view.tag() == network::DataElement::Tag::kChunkedDataPipe) {
+ network::DataElement element;
+ if (!elements_view.Read(0, &element)) {
+ return false;
+ }
+ auto& chunked_data_pipe =
+ element.As<network::DataElementChunkedDataPipe>();
+ *out = blink::ResourceRequestBody(blink::ToCrossVariantMojoType(
+ chunked_data_pipe.ReleaseChunkedDataPipeGetter()));
return true;
}
}
auto form_data = blink::EncodedFormData::Create();
for (size_t i = 0; i < elements_view.size(); ++i) {
- blink::mojom::FetchAPIDataElementDataView view;
- elements_view.GetDataView(i, &view);
-
- network::mojom::DataElementType type;
- if (!view.ReadType(&type)) {
+ network::DataElement element;
+ if (!elements_view.Read(i, &element)) {
return false;
}
- switch (type) {
- case network::mojom::DataElementType::kBytes: {
- // TODO(richard.li): Delete this workaround when type of
- // blink::FormDataElement::data_ is changed to WTF::Vector<uint8_t>
- WTF::Vector<uint8_t> buf;
- if (!view.ReadBuf(&buf)) {
- return false;
- }
- form_data->AppendData(buf.data(), buf.size());
+
+ switch (element.type()) {
+ case network::DataElement::Tag::kBytes: {
+ const auto& bytes = element.As<network::DataElementBytes>();
+ form_data->AppendData(bytes.bytes().data(), bytes.bytes().size());
break;
}
- case network::mojom::DataElementType::kFile: {
- base::FilePath file_path;
- base::Time expected_time;
- if (!view.ReadPath(&file_path) ||
- !view.ReadExpectedModificationTime(&expected_time)) {
- return false;
- }
- base::Optional<base::Time> expected_file_modification_time;
- if (!expected_time.is_null()) {
- expected_file_modification_time = expected_time;
+ case network::DataElement::Tag::kFile: {
+ const auto& file = element.As<network::DataElementFile>();
+ base::Optional<base::Time> expected_modification_time;
+ if (!file.expected_modification_time().is_null()) {
+ expected_modification_time = file.expected_modification_time();
}
- form_data->AppendFileRange(blink::FilePathToString(file_path),
- view.offset(), view.length(),
- expected_file_modification_time);
+ form_data->AppendFileRange(blink::FilePathToString(file.path()),
+ file.offset(), file.length(),
+ expected_modification_time);
break;
}
- case network::mojom::DataElementType::kDataPipe: {
- auto data_pipe_ptr_remote = view.TakeDataPipeGetter<
- mojo::PendingRemote<network::mojom::blink::DataPipeGetter>>();
- DCHECK(data_pipe_ptr_remote.is_valid());
-
+ case network::DataElement::Tag::kDataPipe: {
+ auto& datapipe = element.As<network::DataElementDataPipe>();
form_data->AppendDataPipe(
base::MakeRefCounted<blink::WrappedDataPipeGetter>(
- std::move(data_pipe_ptr_remote)));
-
+ blink::ToCrossVariantMojoType(
+ datapipe.ReleaseDataPipeGetter())));
break;
}
- case network::mojom::DataElementType::kUnknown:
- case network::mojom::DataElementType::kChunkedDataPipe:
- case network::mojom::DataElementType::kReadOnceStream:
+ case network::DataElement::Tag::kChunkedDataPipe:
NOTREACHED();
return false;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
index f85aee270a8..4576e3abe9d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
@@ -21,7 +21,7 @@ struct PLATFORM_EXPORT StructTraits<blink::mojom::FetchAPIRequestBodyDataView,
static void SetToNull(blink::ResourceRequestBody* out) {
*out = blink::ResourceRequestBody();
}
- static WTF::Vector<blink::mojom::blink::FetchAPIDataElementPtr> elements(
+ static WTF::Vector<network::DataElement> elements(
blink::ResourceRequestBody& mutable_body);
static int64_t identifier(const blink::ResourceRequestBody& body) {
return body.FormBody() ? body.FormBody()->Identifier() : 0;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc
index 7f96b51c38f..c6505181f2b 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits_test.cc
@@ -30,7 +30,7 @@ TEST_F(FetchApiRequestBodyMojomTraitsTest, RoundTripEmpty) {
ResourceRequestBody dest;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- blink::mojom::blink::FetchAPIRequestBody>(&src, &dest));
+ blink::mojom::blink::FetchAPIRequestBody>(src, dest));
EXPECT_TRUE(dest.IsEmpty());
}
@@ -43,7 +43,7 @@ TEST_F(FetchApiRequestBodyMojomTraitsTest, RoundTripBytes) {
ResourceRequestBody dest;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- blink::mojom::blink::FetchAPIRequestBody>(&src, &dest));
+ blink::mojom::blink::FetchAPIRequestBody>(src, dest));
ASSERT_TRUE(dest.FormBody());
EXPECT_EQ(dest.FormBody()->Identifier(), 29);
@@ -61,7 +61,7 @@ TEST_F(FetchApiRequestBodyMojomTraitsTest, RoundTripFile) {
ResourceRequestBody dest;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- blink::mojom::blink::FetchAPIRequestBody>(&src, &dest));
+ blink::mojom::blink::FetchAPIRequestBody>(src, dest));
ASSERT_TRUE(dest.FormBody());
ASSERT_EQ(1u, dest.FormBody()->Elements().size());
@@ -79,7 +79,7 @@ TEST_F(FetchApiRequestBodyMojomTraitsTest, RoundTripFileRange) {
ResourceRequestBody dest;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- blink::mojom::blink::FetchAPIRequestBody>(&src, &dest));
+ blink::mojom::blink::FetchAPIRequestBody>(src, dest));
ASSERT_TRUE(dest.FormBody());
ASSERT_EQ(1u, dest.FormBody()->Elements().size());
@@ -102,7 +102,7 @@ TEST_F(FetchApiRequestBodyMojomTraitsTest, RoundTripBlobWithOpionalHandle) {
ResourceRequestBody dest;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- blink::mojom::blink::FetchAPIRequestBody>(&src, &dest));
+ blink::mojom::blink::FetchAPIRequestBody>(src, dest));
ASSERT_TRUE(dest.FormBody());
ASSERT_EQ(1u, dest.FormBody()->Elements().size());
@@ -122,7 +122,7 @@ TEST_F(FetchApiRequestBodyMojomTraitsTest, RoundTripDataPipeGetter) {
ResourceRequestBody dest;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- blink::mojom::blink::FetchAPIRequestBody>(&src, &dest));
+ blink::mojom::blink::FetchAPIRequestBody>(src, dest));
ASSERT_TRUE(dest.FormBody());
ASSERT_EQ(1u, dest.FormBody()->Elements().size());
@@ -139,7 +139,7 @@ TEST_F(FetchApiRequestBodyMojomTraitsTest, RoundTripStreamBody) {
ResourceRequestBody dest;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
- blink::mojom::blink::FetchAPIRequestBody>(&src, &dest));
+ blink::mojom::blink::FetchAPIRequestBody>(src, dest));
EXPECT_FALSE(dest.FormBody());
ASSERT_TRUE(dest.StreamBody());
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
index c2405674ddf..f3af4183d5c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
@@ -65,18 +65,6 @@ class PLATFORM_EXPORT FetchClientSettingsObject
// https://html.spec.whatwg.org/C/#concept-settings-object-referrer-policy
virtual network::mojom::ReferrerPolicy GetReferrerPolicy() const = 0;
- // |GetReferrerPolicyDisregardingMetaTagsContainingLists|
- // returns the policy that would have been set had we been ignoring all <meta
- // name=referrer> tags with values comma-separated lists of policies. This
- // allows histogramming the proportion of requests that would end up with
- // different referrers were these tags ignored, helping interpret the impact
- // of removing support for them (which is inconsistent with the spec and other
- // engines).
- virtual base::Optional<network::mojom::ReferrerPolicy>
- GetReferrerPolicyDisregardingMetaTagsContainingLists() const {
- return base::nullopt;
- }
-
// "referrerURL" used in the "Determine request's Referrer" algorithm:
// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
virtual const String GetOutgoingReferrer() const = 0;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
index f4d380bda6e..6eef1738995 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -120,6 +120,19 @@ class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
const {
return ResourceRequestBlockedReason::kOther;
}
+ // In derived classes, performs *only* a SubresourceFilter check for whether
+ // the request can go through or should be blocked.
+ virtual base::Optional<ResourceRequestBlockedReason>
+ CanRequestBasedOnSubresourceFilterOnly(
+ ResourceType,
+ const ResourceRequest&,
+ const KURL&,
+ const ResourceLoaderOptions&,
+ ReportingDisposition,
+ const base::Optional<ResourceRequest::RedirectInfo>& redirect_info)
+ const {
+ return ResourceRequestBlockedReason::kOther;
+ }
virtual base::Optional<ResourceRequestBlockedReason> CheckCSPForRequest(
mojom::blink::RequestContextType,
network::mojom::RequestDestination request_destination,
@@ -151,9 +164,11 @@ class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
virtual const FeaturePolicy* GetFeaturePolicy() const { return nullptr; }
// Determine if the request is on behalf of an advertisement. If so, return
- // true.
+ // true. Checks `resource_request.Url()` unless `alias_url` is non-null, in
+ // which case it checks the latter.
virtual bool CalculateIfAdSubresource(
- const ResourceRequest& resource_request,
+ const ResourceRequestHead& resource_request,
+ const base::Optional<KURL>& alias_url,
ResourceType type,
const FetchInitiatorInfo& initiator_info) {
return false;
@@ -174,6 +189,9 @@ class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
return nullptr;
}
+ // Returns if the request context is for prerendering or not.
+ virtual bool IsPrerendering() const { return false; }
+
private:
DISALLOW_COPY_AND_ASSIGN(FetchContext);
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
index 0a351b55b34..c8995c1284e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
@@ -130,4 +130,9 @@ void FetchParameters::SetLazyImageNonBlocking() {
image_request_behavior_ = kNonBlockingImage;
}
+void FetchParameters::SetModuleScript() {
+ DCHECK_EQ(mojom::blink::ScriptType::kClassic, script_type_);
+ script_type_ = mojom::blink::ScriptType::kModule;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
index c38f4571771..cb95a274740 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -27,10 +27,13 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_FETCH_PARAMETERS_H_
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-shared.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
#include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
+#include "third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
@@ -66,6 +69,7 @@ class PLATFORM_EXPORT FetchParameters {
kNonBlockingImage // The image load may continue, but must be placed in
// ResourceFetcher::non_blocking_loaders_.
};
+
struct ResourceWidth {
DISALLOW_NEW();
float width;
@@ -192,6 +196,10 @@ class PLATFORM_EXPORT FetchParameters {
void SetLazyImageDeferred();
void SetLazyImageNonBlocking();
+ mojom::blink::ScriptType GetScriptType() const { return script_type_; }
+
+ void SetModuleScript();
+
// See documentation in blink::ResourceRequest.
bool IsFromOriginDirtyStyleSheet() const {
return is_from_origin_dirty_style_sheet_;
@@ -204,6 +212,15 @@ class PLATFORM_EXPORT FetchParameters {
resource_request_.SetSignedExchangePrefetchCacheEnabled(enabled);
}
+ RenderBlockingBehavior GetRenderBlockingBehavior() const {
+ return render_blocking_behavior_;
+ }
+
+ void SetRenderBlockingBehavior(
+ RenderBlockingBehavior render_blocking_behavior) {
+ render_blocking_behavior_ = render_blocking_behavior;
+ }
+
private:
ResourceRequest resource_request_;
// |decoder_options_|'s ContentType is set to |kPlainTextContent| in
@@ -216,8 +233,11 @@ class PLATFORM_EXPORT FetchParameters {
ResourceWidth resource_width_;
ClientHintsPreferences client_hint_preferences_;
ImageRequestBehavior image_request_behavior_;
+ mojom::blink::ScriptType script_type_ = mojom::blink::ScriptType::kClassic;
bool is_stale_revalidation_ = false;
bool is_from_origin_dirty_style_sheet_ = false;
+ RenderBlockingBehavior render_blocking_behavior_ =
+ RenderBlockingBehavior::kUnset;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
index 5b5a5363894..c5ca2727e80 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
@@ -447,7 +447,8 @@ bool MemoryCache::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail,
return true;
}
-void MemoryCache::OnMemoryPressure(WebMemoryPressureLevel level) {
+void MemoryCache::OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel level) {
PruneAll();
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
index 16184a56356..74b17f2e573 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
@@ -151,7 +151,8 @@ class PLATFORM_EXPORT MemoryCache final : public GarbageCollected<MemoryCache>,
// Take memory usage snapshot for tracing.
bool OnMemoryDump(WebMemoryDumpLevelOfDetail, WebProcessMemoryDump*) override;
- void OnMemoryPressure(WebMemoryPressureLevel) override;
+ void OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel) override;
private:
enum PruneStrategy {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
index f3e230d965f..e647437fdf6 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
@@ -132,7 +132,8 @@ class MemoryCacheCorrectnessTest : public testing::Test {
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
MakeGarbageCollected<TestLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ MakeGarbageCollected<MockContextLifecycleNotifier>(),
+ nullptr /* back_forward_cache_loader_helper */));
Resource::SetClockForTesting(platform_->test_task_runner()->GetMockClock());
}
void TearDown() override {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
index 3c928d3a779..a1217b9eb1f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
@@ -104,12 +104,13 @@ class MemoryCacheTest : public testing::Test {
global_memory_cache_ = ReplaceMemoryCacheForTesting(
MakeGarbageCollected<MemoryCache>(platform_->test_task_runner()));
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
+ lifecycle_notifier_ = MakeGarbageCollected<MockContextLifecycleNotifier>();
fetcher_ = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
properties->MakeDetachable(), MakeGarbageCollected<MockFetchContext>(),
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
- MakeGarbageCollected<TestLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ MakeGarbageCollected<TestLoaderFactory>(), lifecycle_notifier_,
+ nullptr /* back_forward_cache_loader_helper */));
}
void TearDown() override {
@@ -118,6 +119,7 @@ class MemoryCacheTest : public testing::Test {
Persistent<MemoryCache> global_memory_cache_;
Persistent<ResourceFetcher> fetcher_;
+ Persistent<MockContextLifecycleNotifier> lifecycle_notifier_;
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform_;
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
index 965b76b4a08..c4f1754af79 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
@@ -36,8 +36,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_client_walker.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h"
-#include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h"
-#include "third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
@@ -233,11 +231,6 @@ void RawResource::WillNotFollowRedirect() {
c->RedirectBlocked();
}
-SingleCachedMetadataHandler* RawResource::ScriptCacheHandler() {
- DCHECK_EQ(ResourceType::kRaw, GetType());
- return static_cast<SingleCachedMetadataHandler*>(Resource::CacheHandler());
-}
-
scoped_refptr<BlobDataHandle> RawResource::DownloadedBlob() const {
return downloaded_blob_;
}
@@ -300,33 +293,15 @@ void RawResource::ResponseBodyReceived(
client->ResponseBodyReceived(this, body_loader.DrainAsBytesConsumer());
}
-CachedMetadataHandler* RawResource::CreateCachedMetadataHandler(
- std::unique_ptr<CachedMetadataSender> send_callback) {
- if (GetType() == ResourceType::kRaw) {
- // This is a resource of indeterminate type, e.g. a fetched WebAssembly
- // module; create a cache handler that can store a single metadata entry.
- return MakeGarbageCollected<ScriptCachedMetadataHandler>(
- Encoding(), std::move(send_callback));
- }
- return Resource::CreateCachedMetadataHandler(std::move(send_callback));
-}
-
void RawResource::SetSerializedCachedMetadata(mojo_base::BigBuffer data) {
// Resource ignores the cached metadata.
Resource::SetSerializedCachedMetadata(mojo_base::BigBuffer());
- // Notify clients before potentially transferring ownership of the buffer.
ResourceClientWalker<RawResourceClient> w(Clients());
- while (RawResourceClient* c = w.Next()) {
- c->SetSerializedCachedMetadata(this, data.data(), data.size());
- }
-
- if (GetType() == ResourceType::kRaw) {
- ScriptCachedMetadataHandler* cache_handler =
- static_cast<ScriptCachedMetadataHandler*>(Resource::CacheHandler());
- if (cache_handler) {
- cache_handler->SetSerializedCachedMetadata(std::move(data));
- }
+ // We rely on the fact that RawResource cannot have multiple clients.
+ CHECK_LE(Clients().size(), 1u);
+ if (RawResourceClient* c = w.Next()) {
+ c->CachedMetadataReceived(this, std::move(data));
}
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
index 12dd376670b..6846361c04a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
@@ -26,6 +26,7 @@
#include <memory>
#include "base/optional.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
@@ -39,7 +40,6 @@ class BufferingBytesConsumer;
class FetchParameters;
class RawResourceClient;
class ResourceFetcher;
-class SingleCachedMetadataHandler;
class PLATFORM_EXPORT RawResource final : public Resource {
public:
@@ -87,19 +87,10 @@ class PLATFORM_EXPORT RawResource final : public Resource {
void SetSerializedCachedMetadata(mojo_base::BigBuffer data) override;
- // Used for code caching of fetched code resources. Returns a cache handler
- // which can only store a single cache metadata entry. This is valid only if
- // type is kRaw.
- SingleCachedMetadataHandler* ScriptCacheHandler();
-
scoped_refptr<BlobDataHandle> DownloadedBlob() const;
void Trace(Visitor* visitor) const override;
- protected:
- CachedMetadataHandler* CreateCachedMetadataHandler(
- std::unique_ptr<CachedMetadataSender> send_callback) override;
-
private:
class RawResourceFactory : public NonTextResourceFactory {
public:
@@ -184,7 +175,7 @@ class PLATFORM_EXPORT RawResourceClient : public ResourceClient {
uint64_t /* totalBytesToBeSent */) {}
virtual void ResponseBodyReceived(Resource*, BytesConsumer&) {}
virtual void ResponseReceived(Resource*, const ResourceResponse&) {}
- virtual void SetSerializedCachedMetadata(Resource*, const uint8_t*, size_t) {}
+ virtual void CachedMetadataReceived(Resource*, mojo_base::BigBuffer) {}
virtual bool RedirectReceived(Resource*,
const ResourceRequest&,
const ResourceResponse&) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
index 9ed72a6c757..48f308f59eb 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
@@ -67,7 +67,6 @@ class RawResourceTest : public testing::Test {
void DidFinishLoadingBody() override {}
void DidFailLoadingBody() override {}
void DidCancelLoadingBody() override {}
- void EvictFromBackForwardCache(mojom::RendererEvictionReason) override {}
};
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
@@ -243,7 +242,7 @@ TEST_F(RawResourceTest, PreloadWithAsynchronousAddClient) {
ReplayingBytesConsumer::Command(ReplayingBytesConsumer::Command::kDone));
ResponseBodyLoader* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
*bytes_consumer, *MakeGarbageCollected<NoopResponseBodyLoaderClient>(),
- platform_->test_task_runner().get());
+ platform_->test_task_runner().get(), nullptr);
Persistent<DummyClient> dummy_client = MakeGarbageCollected<DummyClient>();
// Set the response first to make ResourceClient addition asynchronous.
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h b/chromium/third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h
new file mode 100644
index 00000000000..7a7761fa226
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h
@@ -0,0 +1,19 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RENDER_BLOCKING_BEHAVIOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RENDER_BLOCKING_BEHAVIOR_H_
+
+namespace blink {
+enum class RenderBlockingBehavior : uint8_t {
+ kUnset, // Render blocking value was not set.
+ kBlocking, // Render Blocking resource.
+ kNonBlocking, // Non-blocking resource.
+ kNonBlockingDynamic, // Dynamically injected non-blocking resource.
+ kPotentiallyBlocking, // Dynamically injected non-blocking resource.
+ kInBodyParserBlocking, // Blocks parser below element declaration.
+};
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
index 3265d12e68e..b59317fa3e7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -41,8 +41,6 @@
#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
@@ -71,12 +69,6 @@ void NotifyFinishObservers(
observer->NotifyFinished();
}
-blink::mojom::CodeCacheType ToCodeCacheType(ResourceType resource_type) {
- return resource_type == ResourceType::kRaw
- ? blink::mojom::CodeCacheType::kWebAssembly
- : blink::mojom::CodeCacheType::kJavascript;
-}
-
void GetSharedBufferMemoryDump(SharedBuffer* buffer,
const String& dump_prefix,
WebProcessMemoryDump* memory_dump) {
@@ -136,7 +128,8 @@ static inline bool ShouldUpdateHeaderAfterRevalidation(
namespace {
const base::Clock* g_clock_for_testing = nullptr;
-}
+
+} // namespace
static inline base::Time Now() {
const base::Clock* clock = g_clock_for_testing
@@ -163,6 +156,13 @@ Resource::Resource(const ResourceRequestHead& request,
response_timestamp_(Now()),
resource_request_(request),
overhead_size_(CalculateOverheadSize()) {
+ scoped_refptr<const SecurityOrigin> top_frame_origin =
+ resource_request_.TopFrameOrigin();
+ if (top_frame_origin) {
+ net::SchemefulSite site(top_frame_origin->ToUrlOrigin());
+ existing_top_frame_sites_in_cache_.insert(site);
+ }
+
InstanceCounters::IncrementCounter(InstanceCounters::kResourceCounter);
if (IsMainThread())
@@ -175,7 +175,6 @@ Resource::~Resource() {
void Resource::Trace(Visitor* visitor) const {
visitor->Trace(loader_);
- visitor->Trace(cache_handler_);
visitor->Trace(clients_);
visitor->Trace(clients_awaiting_callback_);
visitor->Trace(finished_clients_);
@@ -507,23 +506,12 @@ bool Resource::WillFollowRedirect(const ResourceRequest& new_request,
void Resource::SetResponse(const ResourceResponse& response) {
response_ = response;
-
- // Currently we support the metadata caching only for HTTP family.
- if (!GetResourceRequest().Url().ProtocolIsInHTTPFamily() ||
- !GetResponse().CurrentRequestUrl().ProtocolIsInHTTPFamily()) {
- cache_handler_.Clear();
- return;
- }
-
- cache_handler_ = CreateCachedMetadataHandler(
- CachedMetadataSender::Create(GetResponse(), ToCodeCacheType(GetType()),
- GetResourceRequest().RequestorOrigin()));
}
void Resource::ResponseReceived(const ResourceResponse& response) {
response_timestamp_ = Now();
if (is_revalidating_) {
- if (response.HttpStatusCode() == 304) {
+ if (IsSuccessfulRevalidationResponse(response)) {
RevalidationSucceeded(response);
return;
}
@@ -538,8 +526,6 @@ void Resource::ResponseReceived(const ResourceResponse& response) {
void Resource::SetSerializedCachedMetadata(mojo_base::BigBuffer data) {
DCHECK(!is_revalidating_);
DCHECK(!GetResponse().IsNull());
- // Actual metadata transferred here will be lost.
- DCHECK(!data.size());
}
String Resource::ReasonNotDeletable() const {
@@ -675,11 +661,9 @@ void Resource::DidRemoveClientOrObserver() {
// from volatile storage as promptly as possible"
// "... History buffers MAY store such responses as part of their normal
// operation."
- // We allow non-secure content to be reused in history, but we do not allow
- // secure content to be reused.
- if (HasCacheControlNoStoreHeader() && Url().ProtocolIs("https") &&
- IsMainThread())
+ if (HasCacheControlNoStoreHeader() && IsMainThread()) {
GetMemoryCache()->Remove(this);
+ }
}
}
@@ -765,13 +749,16 @@ Resource::MatchStatus Resource::CanReuse(const FetchParameters& params) const {
return MatchStatus::kUnknownFailure;
}
+ // Use GetResourceRequest to get the const resource_request_.
+ const ResourceRequestHead& current_request = GetResourceRequest();
+
// If credentials were sent with the previous request and won't be with this
// one, or vice versa, re-fetch the resource.
//
// This helps with the case where the server sends back
// "Access-Control-Allow-Origin: *" all the time, but some of the client's
// requests are made without CORS and some with.
- if (GetResourceRequest().AllowStoredCredentials() !=
+ if (current_request.AllowStoredCredentials() !=
new_request.AllowStoredCredentials()) {
return MatchStatus::kRequestCredentialsModeDoesNotMatch;
}
@@ -818,10 +805,10 @@ Resource::MatchStatus Resource::CanReuse(const FetchParameters& params) const {
return MatchStatus::kSynchronousFlagDoesNotMatch;
}
- if (resource_request_.GetKeepalive() || new_request.GetKeepalive())
+ if (current_request.GetKeepalive() || new_request.GetKeepalive())
return MatchStatus::kKeepaliveSet;
- if (GetResourceRequest().HttpMethod() != http_names::kGET ||
+ if (current_request.HttpMethod() != http_names::kGET ||
new_request.HttpMethod() != http_names::kGET) {
return MatchStatus::kRequestMethodDoesNotMatch;
}
@@ -833,16 +820,13 @@ Resource::MatchStatus Resource::CanReuse(const FetchParameters& params) const {
if (!existing_origin->IsSameOriginWith(new_origin.get()))
return MatchStatus::kUnknownFailure;
- // securityOrigin has more complicated checks which callers are responsible
- // for.
-
if (new_request.GetCredentialsMode() !=
- resource_request_.GetCredentialsMode()) {
+ current_request.GetCredentialsMode()) {
return MatchStatus::kRequestCredentialsModeDoesNotMatch;
}
const auto new_mode = new_request.GetMode();
- const auto existing_mode = resource_request_.GetMode();
+ const auto existing_mode = current_request.GetMode();
if (new_mode != existing_mode)
return MatchStatus::kRequestModeDoesNotMatch;
@@ -856,9 +840,6 @@ void Resource::Prune() {
void Resource::OnPurgeMemory() {
Prune();
- if (!cache_handler_)
- return;
- cache_handler_->ClearCachedMetadata(CachedMetadataHandler::kClearLocally);
}
void Resource::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail,
@@ -924,10 +905,6 @@ void Resource::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail,
overhead_dump->AddScalar("size", "bytes", OverheadSize());
memory_dump->AddSuballocation(
overhead_dump->Guid(), String(WTF::Partitions::kAllocatedObjectPoolName));
-
- const String cache_name = dump_name + "/code_cache";
- if (cache_handler_)
- cache_handler_->OnMemoryDump(memory_dump, cache_name);
}
String Resource::GetMemoryDumpName() const {
@@ -977,7 +954,6 @@ void Resource::RevalidationSucceeded(
void Resource::RevalidationFailed() {
SECURITY_CHECK(redirect_chain_.IsEmpty());
ClearData();
- cache_handler_.Clear();
integrity_disposition_ = ResourceIntegrityDisposition::kNotChecked;
integrity_report_info_.Clear();
DestroyDecodedDataForFailedRevalidation();
@@ -1188,19 +1164,6 @@ const char* Resource::ResourceTypeToString(
return InitiatorTypeNameToString(fetch_initiator_name);
}
-// static
-blink::mojom::CodeCacheType Resource::ResourceTypeToCodeCacheType(
- ResourceType resource_type) {
- DCHECK(
- // Cacheable WebAssembly modules are fetched, so raw resource type.
- resource_type == ResourceType::kRaw ||
- // Cacheable Javascript is a script resource.
- resource_type == ResourceType::kScript ||
- // Also accept mock resources for testing.
- resource_type == ResourceType::kMock);
- return ToCodeCacheType(resource_type);
-}
-
bool Resource::IsLoadEventBlockingResourceType() const {
switch (type_) {
case ResourceType::kImage:
@@ -1229,13 +1192,14 @@ void Resource::SetClockForTesting(const base::Clock* clock) {
g_clock_for_testing = clock;
}
-size_t Resource::CodeCacheSize() const {
- return cache_handler_ ? cache_handler_->GetCodeCacheSize() : 0;
+bool Resource::AppendTopFrameSiteForMetrics(const SecurityOrigin& origin) {
+ net::SchemefulSite site(origin.ToUrlOrigin());
+ auto result = existing_top_frame_sites_in_cache_.insert(site);
+ return !result.second;
}
-CachedMetadataHandler* Resource::CreateCachedMetadataHandler(
- std::unique_ptr<CachedMetadataSender> send_callback) {
- return nullptr;
+void Resource::SetIsAdResource() {
+ resource_request_.SetIsAdResource();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
index 5ef043e5352..ffbfd4696ca 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -31,6 +31,7 @@
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "mojo/public/cpp/base/big_buffer.h"
+#include "net/base/schemeful_site.h"
#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h"
@@ -63,8 +64,6 @@ class Clock;
namespace blink {
class BlobDataHandle;
-class CachedMetadataHandler;
-class CachedMetadataSender;
class FetchParameters;
class ResourceClient;
class ResourceFinishObserver;
@@ -142,6 +141,9 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
// Match fails due to different request headers.
kRequestHeadersDoNotMatch,
+
+ // Match fails due to different script types.
+ kScriptTypeDoesNotMatch,
};
~Resource() override;
@@ -228,7 +230,7 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
size_t DecodedSize() const { return decoded_size_; }
size_t OverheadSize() const { return overhead_size_; }
- size_t CodeCacheSize() const;
+ virtual size_t CodeCacheSize() const { return 0; }
bool IsLoaded() const { return status_ > ResourceStatus::kPending; }
@@ -266,8 +268,8 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
const ResourceResponse& GetResponse() const { return response_; }
// Sets the serialized metadata retrieved from the platform's cache.
- // Subclasses of Resource that support cached metadata should override this
- // method with one that fills the current CachedMetadataHandler.
+ // The default implementation does nothing. Subclasses interested in the data
+ // should implement the resource-specific behavior.
virtual void SetSerializedCachedMetadata(mojo_base::BigBuffer data);
AtomicString HttpContentType() const;
@@ -382,8 +384,6 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
ResourceType,
const AtomicString& fetch_initiator_name);
- static blink::mojom::CodeCacheType ResourceTypeToCodeCacheType(ResourceType);
-
class ProhibitAddRemoveClientInScope : public base::AutoReset<bool> {
public:
ProhibitAddRemoveClientInScope(Resource* resource)
@@ -407,6 +407,14 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
return CalculateOverheadSize();
}
+ // Appends the top-frame site derived from |origin| to
+ // |existing_top_frame_sites_in_cache_| and returns true if the same site
+ // already exists.
+ bool AppendTopFrameSiteForMetrics(const SecurityOrigin& origin);
+
+ // Sets the ResourceRequest to be tagged as an ad.
+ void SetIsAdResource();
+
protected:
Resource(const ResourceRequestHead&,
ResourceType,
@@ -440,6 +448,11 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
finished_clients_.Contains(client);
}
+ bool IsSuccessfulRevalidationResponse(
+ const ResourceResponse& response) const {
+ return IsCacheValidator() && response.HttpStatusCode() == 304;
+ }
+
struct RedirectPair {
DISALLOW_NEW();
@@ -471,16 +484,6 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
virtual void SetEncoding(const String&) {}
- // Create a handler for the cached metadata of this resource. Subclasses of
- // Resource that support cached metadata should override this method with one
- // that creates an appropriate CachedMetadataHandler implementation, and
- // override SetSerializedCachedMetadata with an implementation that fills the
- // cache handler.
- virtual CachedMetadataHandler* CreateCachedMetadataHandler(
- std::unique_ptr<CachedMetadataSender> send_callback);
-
- CachedMetadataHandler* CacheHandler() { return cache_handler_.Get(); }
-
private:
friend class ResourceLoader;
@@ -500,8 +503,6 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
ResourceType type_;
ResourceStatus status_;
- Member<CachedMetadataHandler> cache_handler_;
-
base::Optional<ResourceError> error_;
base::TimeTicks load_response_end_;
@@ -552,6 +553,13 @@ class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
WebScopedVirtualTimePauser virtual_time_pauser_;
+ // To compute metrics for measuring the efficacy of the
+ // memory cache if it was partitioned by top-frame site (in addition to the
+ // current origin which it is already partitioned by).
+ // TODO(crbug.com/1127971): Remove this once the decision is made to partition
+ // the cache using either Network Isolation Key or scoped to per-document.
+ std::set<net::SchemefulSite> existing_top_frame_sites_in_cache_;
+
DISALLOW_COPY_AND_ASSIGN(Resource);
};
@@ -592,11 +600,6 @@ class NonTextResourceFactory : public ResourceFactory {
}
};
-#define DEFINE_RESOURCE_TYPE_CASTS(typeName) \
- DEFINE_TYPE_CASTS(typeName##Resource, Resource, resource, \
- resource->GetType() == ResourceType::k##typeName, \
- resource.GetType() == ResourceType::k##typeName)
-
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
index 784a98d7377..adb87702500 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
@@ -180,7 +180,8 @@ bool ResourceError::IsCancellation() const {
}
bool ResourceError::IsTrustTokenCacheHit() const {
- return error_code_ == net::ERR_TRUST_TOKEN_OPERATION_CACHE_HIT;
+ return error_code_ ==
+ net::ERR_TRUST_TOKEN_OPERATION_SUCCESS_WITHOUT_SENDING_REQUEST;
}
bool ResourceError::IsUnactionableTrustTokensStatus() const {
@@ -300,9 +301,8 @@ String DescriptionForBlockedByClientOrResponse(int error, int extended_error) {
case ResourceRequestBlockedReason::kCorpNotSameSite:
detail = "NotSameSite";
break;
- case ResourceRequestBlockedReason::
- kBlockedByExtensionCrbug1128174Investigation:
- detail = "BlockedByExtensionCrbug1128174Investigation";
+ case ResourceRequestBlockedReason::kConversionRequest:
+ detail = "ConversionRequest";
break;
}
return WebString::FromASCII(net::ErrorToString(error) + "." + detail);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 7c99713e600..3c445ddaa2b 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -47,6 +47,7 @@
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
@@ -56,6 +57,7 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
+#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
#include "third_party/blink/renderer/platform/loader/fetch/detachable_use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
@@ -75,6 +77,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
#include "third_party/blink/renderer/platform/mhtml/archive_resource.h"
#include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
+#include "third_party/blink/renderer/platform/mojo/mojo_binding_context.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -242,50 +245,6 @@ ResourceLoadPriority AdjustPriorityWithPriorityHint(
return new_priority;
}
-ResourceLoadPriority AdjustPriorityWithDeferScriptIntervention(
- const FetchContext& fetch_context,
- ResourceLoadPriority priority_so_far,
- ResourceType type,
- const ResourceRequestHead& resource_request,
- FetchParameters::DeferOption defer_option,
- bool is_link_preload) {
- if (!base::FeatureList::IsEnabled(
- blink::features::kLowerJavaScriptPriorityWhenForceDeferred)) {
- return priority_so_far;
- }
-
- PreviewsState context_previews_state = fetch_context.previews_state();
-
- if (type != ResourceType::kScript)
- return priority_so_far;
-
- // If none of the JavaScript resources are render blocking (due to the
- // DeferAllScript intervention), then lower their priority so they do not
- // contend for network resources with higher priority resources that may be
- // render blocking (e.g., html, css). ResourceLoadPriority::kMedium
- // corresponds to a network priority of
- // network::mojom::blink::RequestPriority::kLow which is considered delayable
- // by the resource scheduler on the browser side.
- if (RuntimeEnabledFeatures::ForceDeferScriptInterventionEnabled() ||
- (context_previews_state & PreviewsTypes::kDeferAllScriptOn)) {
- return std::min(priority_so_far, ResourceLoadPriority::kMedium);
- }
- return priority_so_far;
-}
-
-std::unique_ptr<TracedValue> BeginResourceLoadData(
- const blink::ResourceRequest& request) {
- auto value = std::make_unique<TracedValue>();
- value->SetString("url", request.Url().GetString());
- return value;
-}
-
-std::unique_ptr<TracedValue> EndResourceLoadFailData() {
- auto value = std::make_unique<TracedValue>();
- value->SetString("outcome", "Fail");
- return value;
-}
-
std::unique_ptr<TracedValue> ResourcePrioritySetData(
blink::ResourceLoadPriority priority) {
auto value = std::make_unique<TracedValue>();
@@ -295,9 +254,9 @@ std::unique_ptr<TracedValue> ResourcePrioritySetData(
// This function corresponds with step 2 substep 7 of
// https://fetch.spec.whatwg.org/#main-fetch.
-void SetReferrer(ResourceRequest& request,
- const FetchClientSettingsObject& fetch_client_settings_object,
- UseCounter& use_counter) {
+void SetReferrer(
+ ResourceRequest& request,
+ const FetchClientSettingsObject& fetch_client_settings_object) {
String referrer_to_use = request.ReferrerString();
network::mojom::ReferrerPolicy referrer_policy_to_use =
request.GetReferrerPolicy();
@@ -305,42 +264,12 @@ void SetReferrer(ResourceRequest& request,
if (referrer_to_use == Referrer::ClientReferrerString())
referrer_to_use = fetch_client_settings_object.GetOutgoingReferrer();
- bool used_referrer_policy_from_context = false;
- if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault) {
- used_referrer_policy_from_context = true;
+ if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault)
referrer_policy_to_use = fetch_client_settings_object.GetReferrerPolicy();
- }
Referrer generated_referrer = SecurityPolicy::GenerateReferrer(
referrer_policy_to_use, request.Url(), referrer_to_use);
- // The request's referrer would be different in the absence of <meta
- // name=referrer> tags with comma-separated-list values exactly when both
- // 1. the request falls back to its client settings object's policy; and
- // 2. if we recompute the referrer using the value of the client settings
- // object's policy, disregarding any policy that came from a meta tag with a
- // comma-separated value, we obtain a different referrer.
- if (used_referrer_policy_from_context) {
- base::Optional<network::mojom::blink::ReferrerPolicy>
- policy_but_for_meta_tags_with_policy_lists =
- fetch_client_settings_object
- .GetReferrerPolicyDisregardingMetaTagsContainingLists();
-
- bool referrer_would_be_different_absent_meta_tags_with_policy_lists =
- policy_but_for_meta_tags_with_policy_lists.has_value() &&
- (generated_referrer.referrer !=
- SecurityPolicy::GenerateReferrer(
- *policy_but_for_meta_tags_with_policy_lists, request.Url(),
- referrer_to_use)
- .referrer);
-
- if (referrer_would_be_different_absent_meta_tags_with_policy_lists) {
- use_counter.CountUse(
- mojom::WebFeature::
- kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest);
- }
- }
-
request.SetReferrerString(generated_referrer.referrer);
request.SetReferrerPolicy(generated_referrer.referrer_policy);
}
@@ -371,13 +300,15 @@ ResourceFetcherInit::ResourceFetcherInit(
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
ResourceFetcher::LoaderFactory* loader_factory,
- ContextLifecycleNotifier* context_lifecycle_notifier)
+ ContextLifecycleNotifier* context_lifecycle_notifier,
+ BackForwardCacheLoaderHelper* back_forward_cache_loader_helper)
: properties(&properties),
context(context),
freezable_task_runner(std::move(freezable_task_runner)),
unfreezable_task_runner(std::move(unfreezable_task_runner)),
loader_factory(loader_factory),
- context_lifecycle_notifier(context_lifecycle_notifier) {
+ context_lifecycle_notifier(context_lifecycle_notifier),
+ back_forward_cache_loader_helper(back_forward_cache_loader_helper) {
DCHECK(context);
DCHECK(this->freezable_task_runner);
DCHECK(this->unfreezable_task_runner);
@@ -553,10 +484,6 @@ ResourceLoadPriority ResourceFetcher::ComputeLoadPriority(
priority = AdjustPriorityWithPriorityHint(priority, type, resource_request,
defer_option, is_link_preload);
- priority = AdjustPriorityWithDeferScriptIntervention(
- Context(), priority, type, resource_request, defer_option,
- is_link_preload);
-
if (properties_->IsSubframeDeprioritizationEnabled()) {
if (properties_->IsMainFrame()) {
UMA_HISTOGRAM_ENUMERATION(
@@ -601,6 +528,7 @@ ResourceFetcher::ResourceFetcher(const ResourceFetcherInit& init)
init.frame_or_worker_scheduler,
*console_logger_,
init.loading_behavior_observer)),
+ back_forward_cache_loader_helper_(init.back_forward_cache_loader_helper),
archive_(init.archive),
resource_timing_report_timer_(
freezable_task_runner_,
@@ -645,6 +573,11 @@ ResourceFetcher::IsControlledByServiceWorker() const {
bool ResourceFetcher::ResourceNeedsLoad(Resource* resource,
const FetchParameters& params,
RevalidationPolicy policy) {
+ // MHTML documents should not trigger actual loads (i.e. all resource requests
+ // should be fulfilled by the MHTML archive).
+ if (archive_)
+ return false;
+
// Defer a font load until it is actually needed unless this is a link
// preload.
if (resource->GetType() == ResourceType::kFont && !params.IsLinkPreload())
@@ -664,13 +597,15 @@ bool ResourceFetcher::ResourceNeedsLoad(Resource* resource,
void ResourceFetcher::DidLoadResourceFromMemoryCache(
Resource* resource,
const ResourceRequest& request,
- bool is_static_data) {
+ bool is_static_data,
+ RenderBlockingBehavior render_blocking_behavior) {
if (IsDetached() || !resource_load_observer_)
return;
resource_load_observer_->WillSendRequest(
request.InspectorId(), request, ResourceResponse() /* redirects */,
- resource->GetType(), resource->Options().initiator_info);
+ resource->GetType(), resource->Options().initiator_info,
+ render_blocking_behavior);
resource_load_observer_->DidReceiveResponse(
request.InspectorId(), request, resource->GetResponse(), resource,
ResourceLoadObserver::ResponseSource::kFromMemoryCache);
@@ -707,7 +642,7 @@ void ResourceFetcher::DidLoadResourceFromMemoryCache(
}
}
-Resource* ResourceFetcher::ResourceForStaticData(
+Resource* ResourceFetcher::CreateResourceForStaticData(
const FetchParameters& params,
const ResourceFactory& factory) {
const KURL& url = params.GetResourceRequest().Url();
@@ -801,11 +736,13 @@ void ResourceFetcher::MakePreloadedResourceBlockOnloadIfNeeded(
}
}
-void ResourceFetcher::UpdateMemoryCacheStats(Resource* resource,
- RevalidationPolicy policy,
- const FetchParameters& params,
- const ResourceFactory& factory,
- bool is_static_data) const {
+void ResourceFetcher::UpdateMemoryCacheStats(
+ Resource* resource,
+ RevalidationPolicy policy,
+ const FetchParameters& params,
+ const ResourceFactory& factory,
+ bool is_static_data,
+ bool same_top_frame_site_resource_cached) const {
if (is_static_data)
return;
@@ -813,6 +750,11 @@ void ResourceFetcher::UpdateMemoryCacheStats(Resource* resource,
DEFINE_RESOURCE_HISTOGRAM("Preload.");
} else {
DEFINE_RESOURCE_HISTOGRAM("");
+
+ // Log metrics to evaluate effectiveness of the memory cache if it was
+ // partitioned by the top-frame site.
+ if (same_top_frame_site_resource_cached)
+ DEFINE_RESOURCE_HISTOGRAM("PerTopFrameSite.");
}
// Aims to count Resource only referenced from MemoryCache (i.e. what would be
@@ -924,6 +866,8 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
DCHECK_NE(computed_load_priority, ResourceLoadPriority::kUnresolved);
resource_request.SetPriority(computed_load_priority);
+ resource_request.SetRenderBlockingBehavior(
+ params.GetRenderBlockingBehavior());
if (resource_request.GetCacheMode() == mojom::FetchCacheMode::kDefault) {
resource_request.SetCacheMode(Context().ResourceRequestCachePolicy(
@@ -947,8 +891,7 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
http_names::kGET &&
!params.IsStaleRevalidation());
- SetReferrer(resource_request, properties_->GetFetchClientSettingsObject(),
- GetUseCounter());
+ SetReferrer(resource_request, properties_->GetFetchClientSettingsObject());
resource_request.SetExternalRequestStateFromRequestorAddressSpace(
properties_->GetFetchClientSettingsObject().GetAddressSpace());
@@ -959,7 +902,7 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
TRACE_DISABLED_BY_DEFAULT("network"), "ResourcePrioritySet",
TRACE_ID_WITH_SCOPE("BlinkResourceID",
TRACE_ID_LOCAL(resource_request.InspectorId())),
- "data", ResourcePrioritySetData(resource_request.Priority()));
+ "priority", resource_request.Priority());
KURL url = MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url());
base::Optional<ResourceRequestBlockedReason> blocked_reason =
@@ -967,8 +910,9 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
reporting_disposition,
resource_request.GetRedirectInfo());
- if (Context().CalculateIfAdSubresource(resource_request, resource_type,
- options.initiator_info))
+ if (Context().CalculateIfAdSubresource(resource_request,
+ base::nullopt /* alias_url */,
+ resource_type, options.initiator_info))
resource_request.SetIsAdResource();
if (blocked_reason)
@@ -988,9 +932,37 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
resource_request.SetAllowStoredCredentials(false);
}
+ if (resource_request.GetWebBundleTokenParams()) {
+ DCHECK_EQ(resource_request.GetRequestDestination(),
+ network::mojom::RequestDestination::kWebBundle);
+ } else {
+ AttachWebBundleTokenIfNeeded(resource_request);
+ }
+
return base::nullopt;
}
+bool ResourceFetcher::ShouldBeLoadedFromWebBundle(const KURL& url) const {
+ for (auto& bundle : subresource_web_bundles_) {
+ if (bundle->CanHandleRequest(url))
+ return true;
+ }
+ return false;
+}
+
+void ResourceFetcher::AttachWebBundleTokenIfNeeded(
+ ResourceRequest& resource_request) const {
+ for (auto& bundle : subresource_web_bundles_) {
+ if (!bundle->CanHandleRequest(resource_request.Url()))
+ continue;
+ resource_request.SetWebBundleTokenParams(
+ ResourceRequestHead::WebBundleTokenParams(bundle->GetBundleUrl(),
+ bundle->WebBundleToken(),
+ mojo::NullRemote()));
+ return;
+ }
+}
+
Resource* ResourceFetcher::RequestResource(FetchParameters& params,
const ResourceFactory& factory,
ResourceClient* client) {
@@ -1022,8 +994,8 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
params.IsFromOriginDirtyStyleSheet());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
TRACE_DISABLED_BY_DEFAULT("network"), "ResourceLoad",
- TRACE_ID_WITH_SCOPE("BlinkResourceID", TRACE_ID_LOCAL(identifier)),
- "beginData", BeginResourceLoadData(resource_request));
+ TRACE_ID_WITH_SCOPE("BlinkResourceID", TRACE_ID_LOCAL(identifier)), "url",
+ resource_request.Url());
SCOPED_BLINK_UMA_HISTOGRAM_TIMER_THREAD_SAFE(
"Blink.Fetch.RequestResourceTime");
TRACE_EVENT1("blink", "ResourceFetcher::requestResource", "url",
@@ -1054,7 +1026,7 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
bool is_static_data = is_data_url || archive_;
bool is_stale_revalidation = params.IsStaleRevalidation();
if (!is_stale_revalidation && is_static_data) {
- resource = ResourceForStaticData(params, factory);
+ resource = CreateResourceForStaticData(params, factory);
if (resource) {
policy =
DetermineRevalidationPolicy(resource_type, params, *resource, true);
@@ -1068,6 +1040,10 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
}
}
+ bool same_top_frame_site_resource_cached = false;
+ bool in_cached_resources_map = cached_resources_map_.Contains(
+ MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()));
+
if (!is_stale_revalidation && !resource) {
resource = MatchPreload(params, resource_type);
if (resource) {
@@ -1076,16 +1052,28 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
// found, we may need to make it block the onload event.
MakePreloadedResourceBlockOnloadIfNeeded(resource, params);
} else if (IsMainThread()) {
- resource = GetMemoryCache()->ResourceForURL(
- params.Url(), GetCacheIdentifier(params.Url()));
+ if (base::FeatureList::IsEnabled(features::kScopeMemoryCachePerContext) &&
+ !in_cached_resources_map) {
+ resource = nullptr;
+ } else {
+ resource = GetMemoryCache()->ResourceForURL(
+ params.Url(), GetCacheIdentifier(params.Url()));
+ }
if (resource) {
policy = DetermineRevalidationPolicy(resource_type, params, *resource,
is_static_data);
+ scoped_refptr<const SecurityOrigin> top_frame_origin =
+ resource_request.TopFrameOrigin();
+ if (top_frame_origin) {
+ same_top_frame_site_resource_cached =
+ resource->AppendTopFrameSiteForMetrics(*top_frame_origin);
+ }
}
}
}
- UpdateMemoryCacheStats(resource, policy, params, factory, is_static_data);
+ UpdateMemoryCacheStats(resource, policy, params, factory, is_static_data,
+ same_top_frame_site_resource_cached);
switch (policy) {
case RevalidationPolicy::kReload:
@@ -1133,10 +1121,10 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
DCHECK(EqualIgnoringFragmentIdentifier(resource->Url(), params.Url()));
if (policy == RevalidationPolicy::kUse &&
resource->GetStatus() == ResourceStatus::kCached &&
- !cached_resources_map_.Contains(
- MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()))) {
+ !in_cached_resources_map) {
// Loaded from MemoryCache.
- DidLoadResourceFromMemoryCache(resource, resource_request, is_static_data);
+ DidLoadResourceFromMemoryCache(resource, resource_request, is_static_data,
+ params.GetRenderBlockingBehavior());
}
if (!is_stale_revalidation) {
String resource_url =
@@ -1154,13 +1142,14 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
// load-blocking. Lazy loaded images that are eventually fetched, however,
// should always be added to |non_blocking_loaders_|, as they are never
// load-blocking.
- LoadBlockingPolicy load_blocking_policy = LoadBlockingPolicy::kDefault;
+ ImageLoadBlockingPolicy load_blocking_policy =
+ ImageLoadBlockingPolicy::kDefault;
if (resource->GetType() == ResourceType::kImage) {
image_resources_.insert(resource);
not_loaded_image_resources_.insert(resource);
if (params.GetImageRequestBehavior() ==
FetchParameters::kNonBlockingImage) {
- load_blocking_policy = LoadBlockingPolicy::kForceNonBlockingLoad;
+ load_blocking_policy = ImageLoadBlockingPolicy::kForceNonBlockingLoad;
}
}
@@ -1171,7 +1160,7 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
if (ResourceNeedsLoad(resource, params, policy)) {
if (!StartLoad(resource,
std::move(params.MutableResourceRequest().MutableBody()),
- load_blocking_policy)) {
+ load_blocking_policy, params.GetRenderBlockingBehavior())) {
resource->FinishAsError(ResourceError::CancelledError(params.Url()),
freezable_task_runner_.get());
}
@@ -1185,7 +1174,7 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
TRACE_EVENT_NESTABLE_ASYNC_END1(
TRACE_DISABLED_BY_DEFAULT("network"), "ResourceLoad",
TRACE_ID_WITH_SCOPE("BlinkResourceID", TRACE_ID_LOCAL(identifier)),
- "endData", EndResourceLoadFailData());
+ "outcome", "Fail");
}
return resource;
@@ -1250,22 +1239,10 @@ std::unique_ptr<WebURLLoader> ResourceFetcher::CreateURLLoader(
const ResourceLoaderOptions& options) {
DCHECK(!GetProperties().IsDetached());
DCHECK(loader_factory_);
- for (auto& bundle : subresource_web_bundles_) {
- if (!bundle->CanHandleRequest(request.Url()))
- continue;
- ResourceLoaderOptions new_options(options);
- new_options.url_loader_factory = base::MakeRefCounted<base::RefCountedData<
- mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>>>(
- bundle->GetURLLoaderFactory());
- // TODO(yoichio): CreateURLLoader take a ResourceRequestHead instead of
- // ResourceRequest.
- return loader_factory_->CreateURLLoader(ResourceRequest(request),
- new_options, freezable_task_runner_,
- unfreezable_task_runner_);
- }
- return loader_factory_->CreateURLLoader(ResourceRequest(request), options,
- freezable_task_runner_,
- unfreezable_task_runner_);
+ return loader_factory_->CreateURLLoader(
+ ResourceRequest(request), options, freezable_task_runner_,
+ unfreezable_task_runner_,
+ WebBackForwardCacheLoaderHelper(back_forward_cache_loader_helper_));
}
std::unique_ptr<WebCodeCacheLoader> ResourceFetcher::CreateCodeCacheLoader() {
@@ -1287,9 +1264,12 @@ Resource* ResourceFetcher::CreateResourceForLoading(
const ResourceFactory& factory) {
const String cache_identifier =
GetCacheIdentifier(params.GetResourceRequest().Url());
- DCHECK(!IsMainThread() || params.IsStaleRevalidation() ||
- !GetMemoryCache()->ResourceForURL(params.GetResourceRequest().Url(),
- cache_identifier));
+ if (!base::FeatureList::IsEnabled(
+ blink::features::kScopeMemoryCachePerContext)) {
+ DCHECK(!IsMainThread() || params.IsStaleRevalidation() ||
+ !GetMemoryCache()->ResourceForURL(params.GetResourceRequest().Url(),
+ cache_identifier));
+ }
RESOURCE_LOADING_DVLOG(1) << "Loading Resource for "
<< params.GetResourceRequest().Url().ElidedString();
@@ -1426,6 +1406,9 @@ void ResourceFetcher::PrintPreloadWarning(Resource* resource,
case Resource::MatchStatus::kRequestHeadersDoNotMatch:
builder.Append("because the request headers do not match.");
break;
+ case Resource::MatchStatus::kScriptTypeDoesNotMatch:
+ builder.Append("because the script type does not match.");
+ break;
}
console_logger_->AddConsoleMessage(mojom::ConsoleMessageSource::kOther,
mojom::ConsoleMessageLevel::kWarning,
@@ -1519,6 +1502,8 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
bool is_static_data) const {
const ResourceRequest& request = fetch_params.GetResourceRequest();
+ Resource* cached_resource_in_fetcher = CachedResource(request.Url());
+
if (IsDownloadOrStreamRequest(request)) {
return {RevalidationPolicy::kReload,
"It is for download or for streaming."};
@@ -1578,7 +1563,7 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// If resource was populated from archive or data: url, use it.
// This doesn't necessarily mean that |resource| was just created by using
- // ResourceForStaticData().
+ // CreateResourceForStaticData().
if (is_static_data) {
return {RevalidationPolicy::kUse, "Use the existing static resource."};
}
@@ -1640,7 +1625,7 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// validation. We restrict this only to images from memory cache which are the
// same as the version in the current document.
if (type == ResourceType::kImage &&
- &existing_resource == CachedResource(request.Url())) {
+ &existing_resource == cached_resource_in_fetcher) {
return {RevalidationPolicy::kUse,
"Images can be reused without cache validation."};
}
@@ -1758,6 +1743,8 @@ void ResourceFetcher::ClearContext() {
resource_load_observer_ = nullptr;
use_counter_->Detach();
console_logger_->Detach();
+ if (back_forward_cache_loader_helper_)
+ back_forward_cache_loader_helper_->Detach();
loader_factory_ = nullptr;
unused_preloads_timer_.Cancel();
@@ -1962,18 +1949,32 @@ void ResourceFetcher::MoveResourceLoaderToNonBlocking(ResourceLoader* loader) {
}
bool ResourceFetcher::StartLoad(Resource* resource) {
+ DCHECK(resource->GetType() == ResourceType::kFont ||
+ resource->GetType() == ResourceType::kImage);
return StartLoad(resource, ResourceRequestBody(),
- LoadBlockingPolicy::kDefault);
+ ImageLoadBlockingPolicy::kDefault,
+ RenderBlockingBehavior::kNonBlocking);
}
-bool ResourceFetcher::StartLoad(Resource* resource,
- ResourceRequestBody request_body,
- LoadBlockingPolicy policy) {
+bool ResourceFetcher::StartLoad(
+ Resource* resource,
+ ResourceRequestBody request_body,
+ ImageLoadBlockingPolicy policy,
+ RenderBlockingBehavior render_blocking_behavior) {
DCHECK(resource);
DCHECK(resource->StillNeedsLoad());
ResourceLoader* loader = nullptr;
+ if (archive_ && resource->Url().ProtocolIsInHTTPFamily()) {
+ // MHTML documents should not trigger HTTP requests.
+ //
+ // TODO(lukasza): https://crbug.com/1151438: Remove the ad-hoc DwoC below,
+ // once the bug is fixed and verified.
+ NOTREACHED();
+ base::debug::DumpWithoutCrashing();
+ }
+
{
// Forbids JavaScript/revalidation until start()
// to prevent unintended state transitions.
@@ -1995,7 +1996,7 @@ bool ResourceFetcher::StartLoad(Resource* resource,
ResourceResponse response;
resource_load_observer_->WillSendRequest(
resource->InspectorId(), request, response, resource->GetType(),
- resource->Options().initiator_info);
+ resource->Options().initiator_info, render_blocking_behavior);
}
using QuotaType = decltype(inflight_keepalive_bytes_);
@@ -2021,7 +2022,7 @@ bool ResourceFetcher::StartLoad(Resource* resource,
// is handled by MakePreloadedResourceBlockOnloadIfNeeded().
if (!resource->IsLinkPreload() &&
resource->IsLoadEventBlockingResourceType() &&
- policy != LoadBlockingPolicy::kForceNonBlockingLoad) {
+ policy != ImageLoadBlockingPolicy::kForceNonBlockingLoad) {
loaders_.insert(loader);
} else {
non_blocking_loaders_.insert(loader);
@@ -2126,6 +2127,11 @@ String ResourceFetcher::GetCacheIdentifier(const KURL& url) const {
if (properties_->WebBundlePhysicalUrl().IsValid())
return properties_->WebBundlePhysicalUrl().GetString();
+ // Requests that can be satisfied via `archive_` (i.e. MHTML) or
+ // `subresource_web_bundles_` should not participate in the global caching,
+ // but should use a bundle/mhtml-specific cache.
+ if (archive_)
+ return archive_->GetCacheIdentifier();
for (auto& bundle : subresource_web_bundles_) {
if (bundle->CanHandleRequest(url))
return bundle->GetCacheIdentifier();
@@ -2181,7 +2187,8 @@ void ResourceFetcher::EmulateLoadStartedForInspector(
}
DCHECK_EQ(resource->GetStatus(), ResourceStatus::kCached);
DidLoadResourceFromMemoryCache(resource, params.GetResourceRequest(),
- false /* is_static_data */);
+ false /* is_static_data */,
+ params.GetRenderBlockingBehavior());
}
void ResourceFetcher::PrepareForLeakDetection() {
@@ -2270,14 +2277,6 @@ void ResourceFetcher::RemoveSubresourceWebBundle(
subresource_web_bundles_.erase(&subresource_web_bundle);
}
-void ResourceFetcher::EvictFromBackForwardCache(
- mojom::RendererEvictionReason reason) {
- if (!resource_load_observer_)
- return;
-
- resource_load_observer_->EvictFromBackForwardCache(reason);
-}
-
void ResourceFetcher::Trace(Visitor* visitor) const {
visitor->Trace(context_);
visitor->Trace(properties_);
@@ -2286,7 +2285,9 @@ void ResourceFetcher::Trace(Visitor* visitor) const {
visitor->Trace(console_logger_);
visitor->Trace(loader_factory_);
visitor->Trace(scheduler_);
+ visitor->Trace(back_forward_cache_loader_helper_);
visitor->Trace(archive_);
+ visitor->Trace(resource_timing_report_timer_);
visitor->Trace(loaders_);
visitor->Trace(non_blocking_loaders_);
visitor->Trace(cached_resources_map_);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 327e6812aba..7bfb1e03b7a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -43,6 +43,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
+#include "third_party/blink/renderer/platform/mojo/mojo_binding_context.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -52,6 +53,7 @@
namespace blink {
enum class ResourceType : uint8_t;
+class BackForwardCacheLoaderHelper;
class DetachableConsoleLogger;
class DetachableUseCounter;
class DetachableResourceFetcherProperties;
@@ -64,6 +66,7 @@ class ResourceError;
class ResourceLoadObserver;
class ResourceTimingInfo;
class SubresourceWebBundle;
+class WebBackForwardCacheLoaderHelper;
class WebCodeCacheLoader;
struct ResourceFetcherInit;
struct ResourceLoaderOptions;
@@ -99,8 +102,8 @@ class PLATFORM_EXPORT ResourceFetcher
const ResourceRequest&,
const ResourceLoaderOptions&,
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner>
- unfreezable_task_runner) = 0;
+ scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
+ WebBackForwardCacheLoaderHelper) = 0;
// Create a code cache loader to fetch data from code caches.
virtual std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() = 0;
@@ -174,11 +177,13 @@ class PLATFORM_EXPORT ResourceFetcher
base::OnceCallback<void(int)>);
using DocumentResourceMap = HeapHashMap<String, WeakMember<Resource>>;
+ // Note: This function is defined for devtools. Do not use this function in
+ // non-inspector/non-tent-only contexts.
const DocumentResourceMap& AllResources() const {
return cached_resources_map_;
}
- enum class LoadBlockingPolicy {
+ enum class ImageLoadBlockingPolicy {
kDefault,
kForceNonBlockingLoad,
};
@@ -189,7 +194,10 @@ class PLATFORM_EXPORT ResourceFetcher
// call this method explicitly on cases such as ResourceNeedsLoad() returning
// false.
bool StartLoad(Resource*);
- bool StartLoad(Resource*, ResourceRequestBody, LoadBlockingPolicy);
+ bool StartLoad(Resource*,
+ ResourceRequestBody,
+ ImageLoadBlockingPolicy,
+ RenderBlockingBehavior);
void SetAutoLoadImages(bool);
void SetImagesEnabled(bool);
@@ -305,8 +313,12 @@ class PLATFORM_EXPORT ResourceFetcher
void AddSubresourceWebBundle(SubresourceWebBundle& subresource_web_bundle);
void RemoveSubresourceWebBundle(SubresourceWebBundle& subresource_web_bundle);
+ void AttachWebBundleTokenIfNeeded(ResourceRequest&) const;
+ bool ShouldBeLoadedFromWebBundle(const KURL&) const;
- void EvictFromBackForwardCache(mojom::RendererEvictionReason reason);
+ BackForwardCacheLoaderHelper* GetBackForwardCacheLoaderHelper() {
+ return back_forward_cache_loader_helper_;
+ }
private:
friend class ResourceCacheValidationSuppressor;
@@ -341,8 +353,8 @@ class PLATFORM_EXPORT ResourceFetcher
const ResourceFactory&,
WebScopedVirtualTimePauser& virtual_time_pauser);
- Resource* ResourceForStaticData(const FetchParameters&,
- const ResourceFactory&);
+ Resource* CreateResourceForStaticData(const FetchParameters&,
+ const ResourceFactory&);
Resource* ResourceForBlockedRequest(const FetchParameters&,
const ResourceFactory&,
ResourceRequestBlockedReason,
@@ -394,7 +406,8 @@ class PLATFORM_EXPORT ResourceFetcher
void DidLoadResourceFromMemoryCache(Resource*,
const ResourceRequest&,
- bool is_static_data);
+ bool is_static_data,
+ RenderBlockingBehavior);
bool ResourceNeedsLoad(Resource*, const FetchParameters&, RevalidationPolicy);
@@ -406,7 +419,8 @@ class PLATFORM_EXPORT ResourceFetcher
RevalidationPolicy,
const FetchParameters&,
const ResourceFactory&,
- bool is_static_data) const;
+ bool is_static_data,
+ bool same_top_frame_site_resource_cached) const;
void ScheduleStaleRevalidate(Resource* stale_resource);
void RevalidateStaleResource(Resource* stale_resource);
@@ -422,6 +436,7 @@ class PLATFORM_EXPORT ResourceFetcher
const Member<DetachableConsoleLogger> console_logger_;
Member<LoaderFactory> loader_factory_;
const Member<ResourceLoadScheduler> scheduler_;
+ Member<BackForwardCacheLoaderHelper> back_forward_cache_loader_helper_;
DocumentResourceMap cached_resources_map_;
@@ -437,7 +452,7 @@ class PLATFORM_EXPORT ResourceFetcher
HeapVector<Member<Resource>> matched_preloads_;
Member<MHTMLArchive> archive_;
- TaskRunnerTimer<ResourceFetcher> resource_timing_report_timer_;
+ HeapTaskRunnerTimer<ResourceFetcher> resource_timing_report_timer_;
TaskHandle unused_preloads_timer_;
@@ -529,7 +544,8 @@ struct PLATFORM_EXPORT ResourceFetcherInit final {
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
ResourceFetcher::LoaderFactory* loader_factory,
- ContextLifecycleNotifier* context_lifecycle_notifier);
+ ContextLifecycleNotifier* context_lifecycle_notifier,
+ BackForwardCacheLoaderHelper* back_forward_cache_loader_helper = nullptr);
DetachableResourceFetcherProperties* const properties;
FetchContext* const context;
@@ -546,6 +562,7 @@ struct PLATFORM_EXPORT ResourceFetcherInit final {
ResourceLoadScheduler::ThrottleOptionOverride throttle_option_override =
ResourceLoadScheduler::ThrottleOptionOverride::kNone;
LoadingBehaviorObserver* loading_behavior_observer = nullptr;
+ BackForwardCacheLoaderHelper* back_forward_cache_loader_helper = nullptr;
DISALLOW_COPY_AND_ASSIGN(ResourceFetcherInit);
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
index 1bb89327220..ae66f3e7952 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -32,9 +32,11 @@
#include <memory>
#include "base/optional.h"
+#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
@@ -65,6 +67,7 @@
#include "third_party/blink/renderer/platform/loader/testing/mock_resource_client.h"
#include "third_party/blink/renderer/platform/loader/testing/test_loader_factory.h"
#include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
+#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include "third_party/blink/renderer/platform/testing/mock_context_lifecycle_notifier.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/scoped_mocked_url.h"
@@ -127,7 +130,8 @@ class ResourceFetcherTest : public testing::Test {
const ResourceRequest& request,
const ResourceResponse& redirect_response,
ResourceType,
- const FetchInitiatorInfo&) override {
+ const FetchInitiatorInfo&,
+ RenderBlockingBehavior) override {
request_ = PartialResourceRequest(request);
}
void DidChangePriority(uint64_t identifier,
@@ -153,7 +157,6 @@ class ResourceFetcherTest : public testing::Test {
const ResourceError&,
int64_t encoded_data_length,
IsInternalRequest is_internal_request) override {}
- void EvictFromBackForwardCache(mojom::RendererEvictionReason) override {}
const base::Optional<PartialResourceRequest>& GetLastRequest() const {
return request_;
}
@@ -175,7 +178,8 @@ class ResourceFetcherTest : public testing::Test {
CreateTaskRunner(),
MakeGarbageCollected<TestLoaderFactory>(
platform_->GetURLLoaderMockFactory()),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ MakeGarbageCollected<MockContextLifecycleNotifier>(),
+ nullptr /* back_forward_cache_loader_helper */));
}
ResourceFetcher* CreateFetcher(
@@ -222,12 +226,14 @@ TEST_F(ResourceFetcherTest, StartLoadAfterFrameDetach) {
EXPECT_FALSE(GetMemoryCache()->ResourceForURL(secure_url));
// Start by calling StartLoad() directly, rather than via RequestResource().
- // This shouldn't crash.
+ // This shouldn't crash. Setting the resource type to image, as StartLoad with
+ // a single argument is only called on images or fonts.
fetcher->StartLoad(RawResource::CreateForTest(
- secure_url, SecurityOrigin::CreateUniqueOpaque(), ResourceType::kRaw));
+ secure_url, SecurityOrigin::CreateUniqueOpaque(), ResourceType::kImage));
}
TEST_F(ResourceFetcherTest, UseExistingResource) {
+ blink::HistogramTester histogram_tester;
auto* fetcher = CreateFetcher();
KURL url("http://127.0.0.1:8000/foo.html");
@@ -248,6 +254,253 @@ TEST_F(ResourceFetcherTest, UseExistingResource) {
Resource* new_resource = MockResource::Fetch(fetch_params, fetcher, nullptr);
EXPECT_EQ(resource, new_resource);
+
+ // Test histograms.
+ histogram_tester.ExpectTotalCount("Blink.MemoryCache.RevalidationPolicy.Mock",
+ 2);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3 /* RevalidationPolicy::kLoad */, 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 1);
+
+ // Create a new fetcher and load the same resource.
+ auto* new_fetcher = CreateFetcher();
+ Resource* new_fetcher_resource =
+ MockResource::Fetch(fetch_params, new_fetcher, nullptr);
+ EXPECT_EQ(resource, new_fetcher_resource);
+ histogram_tester.ExpectTotalCount("Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3 /* RevalidationPolicy::kLoad */, 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 2);
+}
+
+TEST_F(ResourceFetcherTest, MemoryCachePerContextUseExistingResource) {
+ blink::HistogramTester histogram_tester;
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kScopeMemoryCachePerContext);
+
+ KURL url("http://127.0.0.1:8000/foo.html");
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+ response.SetHttpHeaderField(http_names::kCacheControl, "max-age=3600");
+ platform_->GetURLLoaderMockFactory()->RegisterURL(
+ url, WrappedResourceResponse(response),
+ test::PlatformTestDataPath(kTestResourceFilename));
+
+ FetchParameters fetch_params =
+ FetchParameters::CreateForTest(ResourceRequest(url));
+
+ auto* fetcher_a = CreateFetcher();
+ Resource* resource_a = MockResource::Fetch(fetch_params, fetcher_a, nullptr);
+ ASSERT_TRUE(resource_a);
+ platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ EXPECT_TRUE(resource_a->IsLoaded());
+ EXPECT_TRUE(GetMemoryCache()->Contains(resource_a));
+
+ Resource* resource_a1 = MockResource::Fetch(fetch_params, fetcher_a, nullptr);
+ ASSERT_TRUE(resource_a1);
+ EXPECT_EQ(resource_a, resource_a1);
+
+ // Test histograms.
+ histogram_tester.ExpectTotalCount("Blink.MemoryCache.RevalidationPolicy.Mock",
+ 2);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3 /* RevalidationPolicy::kLoad */, 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 1);
+
+ // Create a new fetcher and load the same resource. It should be loaded again.
+ auto* fetcher_b = CreateFetcher();
+ Resource* resource_b = MockResource::Fetch(fetch_params, fetcher_b, nullptr);
+ EXPECT_NE(resource_a1, resource_b);
+ ASSERT_TRUE(resource_b);
+ platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ EXPECT_TRUE(resource_b->IsLoaded());
+ EXPECT_TRUE(GetMemoryCache()->Contains(resource_b));
+ histogram_tester.ExpectTotalCount("Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3 /* RevalidationPolicy::kLoad */, 2);
+
+ // (TODO: crbug.com/1127971) Using the first fetcher now should reuse the same
+ // resource as was earlier loaded by the same fetcher.
+ // EXPECT_EQ(resource_a1, resource_a2);
+ Resource* resource_a2 = MockResource::Fetch(fetch_params, fetcher_a, nullptr);
+ EXPECT_EQ(resource_b, resource_a2);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 2);
+
+ // Using the second fetcher now should reuse the same resource as was earlier
+ // loaded by the same fetcher.
+ Resource* resource_b1 = MockResource::Fetch(fetch_params, fetcher_b, nullptr);
+ EXPECT_EQ(resource_b, resource_b1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 3);
+}
+
+TEST_F(ResourceFetcherTest, MetricsPerTopFrameSite) {
+ blink::HistogramTester histogram_tester;
+
+ KURL url("http://127.0.0.1:8000/foo.html");
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+ response.SetHttpHeaderField(http_names::kCacheControl, "max-age=3600");
+ platform_->GetURLLoaderMockFactory()->RegisterURL(
+ url, WrappedResourceResponse(response),
+ test::PlatformTestDataPath(kTestResourceFilename));
+
+ ResourceRequestHead request_head(url);
+ scoped_refptr<const SecurityOrigin> origin_a =
+ SecurityOrigin::Create(KURL("https://a.test"));
+ request_head.SetTopFrameOrigin(origin_a);
+ request_head.SetRequestorOrigin(origin_a);
+ FetchParameters fetch_params =
+ FetchParameters::CreateForTest(ResourceRequest(request_head));
+ auto* fetcher_1 = CreateFetcher();
+ Resource* resource_1 = MockResource::Fetch(fetch_params, fetcher_1, nullptr);
+ ASSERT_TRUE(resource_1);
+ platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ EXPECT_TRUE(resource_1->IsLoaded());
+ EXPECT_TRUE(GetMemoryCache()->Contains(resource_1));
+
+ auto* fetcher_2 = CreateFetcher();
+ ResourceRequestHead request_head_2(url);
+ scoped_refptr<const SecurityOrigin> origin_b =
+ SecurityOrigin::Create(KURL("https://b.test"));
+ request_head_2.SetTopFrameOrigin(origin_b);
+ request_head_2.SetRequestorOrigin(origin_a);
+ FetchParameters fetch_params_2 =
+ FetchParameters::CreateForTest(ResourceRequest(request_head_2));
+ Resource* resource_2 =
+ MockResource::Fetch(fetch_params_2, fetcher_2, nullptr);
+ EXPECT_EQ(resource_1, resource_2);
+
+ // Test histograms.
+ histogram_tester.ExpectTotalCount(
+ "Blink.MemoryCache.RevalidationPolicy.PerTopFrameSite.Mock", 0);
+
+ histogram_tester.ExpectTotalCount("Blink.MemoryCache.RevalidationPolicy.Mock",
+ 2);
+
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3 /* RevalidationPolicy::kLoad */, 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 1);
+
+ // Now load the same resource with origin_b as top-frame site. The
+ // PerTopFrameSite histogram should be incremented.
+ auto* fetcher_3 = CreateFetcher();
+ ResourceRequestHead request_head_3(url);
+ scoped_refptr<const SecurityOrigin> foo_origin_b =
+ SecurityOrigin::Create(KURL("https://foo.b.test"));
+ request_head_3.SetTopFrameOrigin(foo_origin_b);
+ request_head_3.SetRequestorOrigin(origin_a);
+ FetchParameters fetch_params_3 =
+ FetchParameters::CreateForTest(ResourceRequest(request_head_3));
+ Resource* resource_3 =
+ MockResource::Fetch(fetch_params_2, fetcher_3, nullptr);
+ EXPECT_EQ(resource_1, resource_3);
+ histogram_tester.ExpectTotalCount(
+ "Blink.MemoryCache.RevalidationPolicy.PerTopFrameSite.Mock", 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.PerTopFrameSite.Mock",
+ 0 /* RevalidationPolicy::kUse */, 1);
+ histogram_tester.ExpectTotalCount("Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 2);
+}
+
+TEST_F(ResourceFetcherTest, MetricsPerTopFrameSiteOpaqueOrigins) {
+ blink::HistogramTester histogram_tester;
+
+ KURL url("http://127.0.0.1:8000/foo.html");
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+ response.SetHttpHeaderField(http_names::kCacheControl, "max-age=3600");
+ platform_->GetURLLoaderMockFactory()->RegisterURL(
+ url, WrappedResourceResponse(response),
+ test::PlatformTestDataPath(kTestResourceFilename));
+
+ ResourceRequestHead request_head(url);
+ scoped_refptr<const SecurityOrigin> origin_a =
+ SecurityOrigin::Create(KURL("https://a.test"));
+ scoped_refptr<const SecurityOrigin> opaque_origin1 =
+ SecurityOrigin::CreateUniqueOpaque();
+ request_head.SetTopFrameOrigin(opaque_origin1);
+ request_head.SetRequestorOrigin(origin_a);
+ FetchParameters fetch_params =
+ FetchParameters::CreateForTest(ResourceRequest(request_head));
+ auto* fetcher_1 = CreateFetcher();
+ Resource* resource_1 = MockResource::Fetch(fetch_params, fetcher_1, nullptr);
+ ASSERT_TRUE(resource_1);
+ platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ EXPECT_TRUE(resource_1->IsLoaded());
+ EXPECT_TRUE(GetMemoryCache()->Contains(resource_1));
+
+ // Create a 2nd opaque top-level origin.
+ auto* fetcher_2 = CreateFetcher();
+ ResourceRequestHead request_head_2(url);
+ scoped_refptr<const SecurityOrigin> opaque_origin2 =
+ SecurityOrigin::CreateUniqueOpaque();
+ request_head_2.SetTopFrameOrigin(opaque_origin2);
+ request_head_2.SetRequestorOrigin(origin_a);
+ FetchParameters fetch_params_2 =
+ FetchParameters::CreateForTest(ResourceRequest(request_head_2));
+ Resource* resource_2 =
+ MockResource::Fetch(fetch_params_2, fetcher_2, nullptr);
+ EXPECT_EQ(resource_1, resource_2);
+
+ // Test histograms.
+ histogram_tester.ExpectTotalCount(
+ "Blink.MemoryCache.RevalidationPolicy.PerTopFrameSite.Mock", 0);
+
+ histogram_tester.ExpectTotalCount("Blink.MemoryCache.RevalidationPolicy.Mock",
+ 2);
+
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3 /* RevalidationPolicy::kLoad */, 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 1);
+
+ // Now load the same resource with opaque_origin1 as top-frame site. The
+ // PerTopFrameSite histogram should be incremented.
+ auto* fetcher_3 = CreateFetcher();
+ ResourceRequestHead request_head_3(url);
+ request_head_3.SetTopFrameOrigin(opaque_origin2);
+ request_head_3.SetRequestorOrigin(origin_a);
+ FetchParameters fetch_params_3 =
+ FetchParameters::CreateForTest(ResourceRequest(request_head_3));
+ Resource* resource_3 =
+ MockResource::Fetch(fetch_params_2, fetcher_3, nullptr);
+ EXPECT_EQ(resource_1, resource_3);
+ histogram_tester.ExpectTotalCount(
+ "Blink.MemoryCache.RevalidationPolicy.PerTopFrameSite.Mock", 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.PerTopFrameSite.Mock",
+ 0 /* RevalidationPolicy::kUse */, 1);
+ histogram_tester.ExpectTotalCount("Blink.MemoryCache.RevalidationPolicy.Mock",
+ 3);
+ histogram_tester.ExpectBucketCount(
+ "Blink.MemoryCache.RevalidationPolicy.Mock",
+ 0 /* RevalidationPolicy::kUse */, 2);
}
// Verify that the ad bit is copied to WillSendRequest's request when the
@@ -413,7 +666,8 @@ class RequestSameResourceOnComplete
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
MakeGarbageCollected<TestLoaderFactory>(mock_factory_),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ MakeGarbageCollected<MockContextLifecycleNotifier>(),
+ nullptr /* back_forward_cache_loader_helper */));
ResourceRequest resource_request2(GetResource()->Url());
resource_request2.SetCacheMode(mojom::FetchCacheMode::kValidateCache);
FetchParameters fetch_params2 =
@@ -500,7 +754,7 @@ class ServeRequestsOnCompleteClient final
void ResponseReceived(Resource*, const ResourceResponse&) override {
ASSERT_TRUE(false);
}
- void SetSerializedCachedMetadata(Resource*, const uint8_t*, size_t) override {
+ void CachedMetadataReceived(Resource*, mojo_base::BigBuffer) override {
ASSERT_TRUE(false);
}
void DataReceived(Resource*, const char*, size_t) override {
@@ -581,7 +835,8 @@ class ScopedMockRedirectRequester {
properties->MakeDetachable(), context_, task_runner_,
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
MakeGarbageCollected<TestLoaderFactory>(mock_factory_),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ MakeGarbageCollected<MockContextLifecycleNotifier>(),
+ nullptr /* back_forward_cache_loader_helper */));
ResourceRequest resource_request(url);
resource_request.SetRequestContext(
mojom::blink::RequestContextType::INTERNAL);
@@ -1166,13 +1421,13 @@ TEST_F(ResourceFetcherTest, DeprioritizeSubframe) {
TEST_F(ResourceFetcherTest, Detach) {
DetachableResourceFetcherProperties& properties =
MakeGarbageCollected<TestResourceFetcherProperties>()->MakeDetachable();
- auto* const fetcher =
- MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties, MakeGarbageCollected<MockFetchContext>(),
- CreateTaskRunner(), CreateTaskRunner(),
- MakeGarbageCollected<TestLoaderFactory>(
- platform_->GetURLLoaderMockFactory()),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* const fetcher = MakeGarbageCollected<ResourceFetcher>(
+ ResourceFetcherInit(properties, MakeGarbageCollected<MockFetchContext>(),
+ CreateTaskRunner(), CreateTaskRunner(),
+ MakeGarbageCollected<TestLoaderFactory>(
+ platform_->GetURLLoaderMockFactory()),
+ MakeGarbageCollected<MockContextLifecycleNotifier>(),
+ nullptr /* back_forward_cache_loader_helper */));
EXPECT_EQ(&properties, &fetcher->GetProperties());
EXPECT_FALSE(properties.IsDetached());
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
index be55d02976a..3e87f24c44d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
@@ -8,7 +8,7 @@
#include <inttypes.h>
#include "base/containers/span.h"
-#include "base/util/type_safety/strong_alias.h"
+#include "base/types/strong_alias.h"
#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
@@ -52,7 +52,8 @@ class PLATFORM_EXPORT ResourceLoadObserver
const ResourceRequest&,
const ResourceResponse& redirect_response,
ResourceType,
- const FetchInitiatorInfo&) = 0;
+ const FetchInitiatorInfo&,
+ RenderBlockingBehavior) = 0;
// Called when the priority of the request changes.
virtual void DidChangePriority(uint64_t identifier,
@@ -89,7 +90,7 @@ class PLATFORM_EXPORT ResourceLoadObserver
int64_t decoded_body_length,
bool should_report_corb_blocking) = 0;
- using IsInternalRequest = util::StrongAlias<class IsInternalRequestTag, bool>;
+ using IsInternalRequest = base::StrongAlias<class IsInternalRequestTag, bool>;
// Called when a request fails.
virtual void DidFailLoading(const KURL&,
uint64_t identifier,
@@ -97,11 +98,6 @@ class PLATFORM_EXPORT ResourceLoadObserver
int64_t encoded_data_length,
IsInternalRequest) = 0;
- // Evict the page from BackForwardCache. Should be called when handling an
- // event which can't proceed if the page is in BackForwardCache and can't be
- // easily deferred to handle later, for example network redirect handling.
- virtual void EvictFromBackForwardCache(mojom::RendererEvictionReason) {}
-
virtual void Trace(Visitor*) const {}
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
index e285beac7c2..94af06e1f6e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_timing.cc
@@ -83,6 +83,7 @@ network::mojom::blink::LoadTimingInfoPtr ResourceLoadTiming::ToMojo() const {
dns_start_, dns_end_, connect_start_, connect_end_, ssl_start_,
ssl_end_),
send_start_, send_end_, receive_headers_start_, receive_headers_end_,
+ /*receive_non_informational_headers_start=*/base::TimeTicks::Now(),
/*first_early_hints_time=*/base::TimeTicks::Now(), push_start_,
push_end_, worker_start_, worker_ready_, worker_fetch_start_,
worker_respond_with_settled_);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index 984f2281a2b..5cf198700d2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -55,12 +55,14 @@
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/renderer/platform/back_forward_cache_utils.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
+#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
@@ -91,20 +93,15 @@ namespace blink {
namespace {
-enum RequestOutcome { kSuccess, kFail };
+enum class RequestOutcome { kSuccess, kFail };
-std::unique_ptr<TracedValue> EndResourceLoadData(RequestOutcome outcome) {
- auto value = std::make_unique<TracedValue>();
+const char* RequestOutcomeToString(RequestOutcome outcome) {
switch (outcome) {
case RequestOutcome::kSuccess:
- value->SetString("outcome", "Success");
- break;
+ return "Success";
case RequestOutcome::kFail:
- value->SetString("outcome", "Fail");
- break;
+ return "Fail";
}
-
- return value;
}
bool IsThrottlableRequestContext(mojom::blink::RequestContextType context) {
@@ -190,6 +187,28 @@ SchedulingPolicy::Feature GetFeatureFromRequestContextType(
}
}
+void LogCnameAliasMetrics(const CnameAliasMetricInfo& info) {
+ UMA_HISTOGRAM_BOOLEAN("SubresourceFilter.CnameAlias.Renderer.HadAliases",
+ info.has_aliases);
+
+ if (info.has_aliases) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "SubresourceFilter.CnameAlias.Renderer.WasAdTaggedBasedOnAlias",
+ info.was_ad_tagged_based_on_alias);
+ UMA_HISTOGRAM_BOOLEAN(
+ "SubresourceFilter.CnameAlias.Renderer.WasBlockedBasedOnAlias",
+ info.was_blocked_based_on_alias);
+ UMA_HISTOGRAM_COUNTS_1000(
+ "SubresourceFilter.CnameAlias.Renderer.ListLength", info.list_length);
+ UMA_HISTOGRAM_COUNTS_1000(
+ "SubresourceFilter.CnameAlias.Renderer.InvalidCount",
+ info.invalid_count);
+ UMA_HISTOGRAM_COUNTS_1000(
+ "SubresourceFilter.CnameAlias.Renderer.RedundantCount",
+ info.redundant_count);
+ }
+}
+
} // namespace
// CodeCacheRequest handles the requests to fetch data from code cache.
@@ -419,11 +438,11 @@ ResourceLoader::ResourceLoader(ResourceFetcher* fetcher,
// Only when this feature is turned on and the loading tasks keep being
// processed and the data is queued up on the renderer, a page can stay in
// BackForwardCache with network requests.
- if (!base::FeatureList::IsEnabled(features::kLoadingTasksUnfreezable)) {
+ if (!IsInflightNetworkRequestBackForwardCacheSupportEnabled()) {
feature_handle_for_scheduler_ =
frame_or_worker_scheduler->RegisterFeature(
GetFeatureFromRequestContextType(request_context),
- {SchedulingPolicy::RecordMetricsForBackForwardCache()});
+ {SchedulingPolicy::DisableBackForwardCache()});
}
}
}
@@ -439,6 +458,7 @@ void ResourceLoader::Trace(Visitor* visitor) const {
visitor->Trace(resource_);
visitor->Trace(response_body_loader_);
visitor->Trace(data_pipe_completion_notifier_);
+ visitor->Trace(cancel_timer_);
ResourceLoadSchedulerClient::Trace(visitor);
}
@@ -525,8 +545,8 @@ void ResourceLoader::DidStartLoadingResponseBodyInternal(
DCHECK(!response_body_loader_);
ResponseBodyLoaderClient& response_body_loader_client = *this;
response_body_loader_ = MakeGarbageCollected<ResponseBodyLoader>(
- bytes_consumer, response_body_loader_client,
- task_runner_for_body_loader_);
+ bytes_consumer, response_body_loader_client, task_runner_for_body_loader_,
+ fetcher_->GetBackForwardCacheLoaderHelper());
resource_->ResponseBodyReceived(*response_body_loader_,
task_runner_for_body_loader_);
if (response_body_loader_->IsDrained()) {
@@ -539,6 +559,8 @@ void ResourceLoader::DidStartLoadingResponseBodyInternal(
}
void ResourceLoader::Run() {
+ // TODO(crbug.com/1169032): Manage cookies' capability control here for the
+ // Prerender2.
StartWith(resource_->GetResourceRequest());
}
@@ -787,8 +809,9 @@ bool ResourceLoader::WillFollowRedirect(
reporting_disposition,
new_request->GetRedirectInfo());
- if (Context().CalculateIfAdSubresource(*new_request, resource_type,
- options.initiator_info))
+ if (Context().CalculateIfAdSubresource(
+ *new_request, base::nullopt /* alias_url */, resource_type,
+ options.initiator_info))
new_request->SetIsAdResource();
if (blocked_reason) {
@@ -823,7 +846,8 @@ bool ResourceLoader::WillFollowRedirect(
if (auto* observer = fetcher_->GetResourceLoadObserver()) {
observer->WillSendRequest(resource_->InspectorId(), *new_request,
redirect_response, resource_->GetType(),
- options.initiator_info);
+ options.initiator_info,
+ initial_request.GetRenderBlockingBehavior());
}
// First-party cookie logic moved from DocumentLoader in Blink to
@@ -858,7 +882,16 @@ void ResourceLoader::DidReceiveCachedMetadata(mojo_base::BigBuffer data) {
}
blink::mojom::CodeCacheType ResourceLoader::GetCodeCacheType() const {
- return Resource::ResourceTypeToCodeCacheType(resource_->GetType());
+ const auto& request = resource_->GetResourceRequest();
+ if (request.GetRequestDestination() ==
+ network::mojom::RequestDestination::kEmpty) {
+ // For requests initiated by the fetch function, we use code cache for
+ // WASM compiled code.
+ return mojom::blink::CodeCacheType::kWebAssembly;
+ } else {
+ // Otherwise, we use code cache for scripting.
+ return mojom::blink::CodeCacheType::kJavascript;
+ }
}
void ResourceLoader::SendCachedCodeToResource(mojo_base::BigBuffer data) {
@@ -949,6 +982,15 @@ void ResourceLoader::DidReceiveResponseInternal(
return;
}
+ // Redirect information for possible post-request checks below.
+ const base::Optional<ResourceRequest::RedirectInfo>& previous_redirect_info =
+ request.GetRedirectInfo();
+ const KURL& original_url = previous_redirect_info
+ ? previous_redirect_info->original_url
+ : request.Url();
+ const ResourceRequest::RedirectInfo redirect_info(original_url,
+ request.Url());
+
if (response.WasFetchedViaServiceWorker()) {
// Run post-request CSP checks. This is the "Should response to request be
// blocked by Content Security Policy?" algorithm in the CSP specification:
@@ -968,16 +1010,10 @@ void ResourceLoader::DidReceiveResponseInternal(
// checks as a first-class concept instead of just reusing the functions for
// pre-request checks, and consider running the checks regardless of service
// worker interception.
- const KURL& response_url = response.ResponseUrl();
- const base::Optional<ResourceRequest::RedirectInfo>&
- previous_redirect_info = request.GetRedirectInfo();
- const KURL& original_url = previous_redirect_info
- ? previous_redirect_info->original_url
- : request.Url();
- const ResourceRequest::RedirectInfo redirect_info(original_url,
- request.Url());
+ //
// CanRequest() below only checks enforced policies: check report-only
// here to ensure violations are sent.
+ const KURL& response_url = response.ResponseUrl();
Context().CheckCSPForRequest(
request_context, request_destination, response_url, options,
ReportingDisposition::kReport, original_url,
@@ -994,6 +1030,18 @@ void ResourceLoader::DidReceiveResponseInternal(
}
}
+ if (base::FeatureList::IsEnabled(
+ features::kSendCnameAliasesToSubresourceFilterFromRenderer)) {
+ CnameAliasMetricInfo info;
+ bool should_block = ShouldBlockRequestBasedOnSubresourceFilterDnsAliasCheck(
+ response.DnsAliases(), request.Url(), original_url, resource_type,
+ initial_request, options, redirect_info, &info);
+ LogCnameAliasMetrics(info);
+
+ if (should_block)
+ return;
+ }
+
// A response should not serve partial content if it was not requested via a
// Range header: https://fetch.spec.whatwg.org/#main-fetch
if (response.GetType() == network::mojom::FetchResponseType::kOpaque &&
@@ -1029,12 +1077,12 @@ void ResourceLoader::DidReceiveResponseInternal(
if (response.CacheControlContainsNoCache()) {
frame_or_worker_scheduler->RegisterStickyFeature(
SchedulingPolicy::Feature::kSubresourceHasCacheControlNoCache,
- {SchedulingPolicy::RecordMetricsForBackForwardCache()});
+ {SchedulingPolicy::DisableBackForwardCache()});
}
if (response.CacheControlContainsNoStore()) {
frame_or_worker_scheduler->RegisterStickyFeature(
SchedulingPolicy::Feature::kSubresourceHasCacheControlNoStore,
- {SchedulingPolicy::RecordMetricsForBackForwardCache()});
+ {SchedulingPolicy::DisableBackForwardCache()});
}
}
@@ -1098,7 +1146,7 @@ void ResourceLoader::DidFinishLoadingFirstPartInMultipart() {
TRACE_DISABLED_BY_DEFAULT("network"), "ResourceLoad",
TRACE_ID_WITH_SCOPE("BlinkResourceID",
TRACE_ID_LOCAL(resource_->InspectorId())),
- "endData", EndResourceLoadData(RequestOutcome::kSuccess));
+ "outcome", RequestOutcomeToString(RequestOutcome::kSuccess));
fetcher_->HandleLoaderFinish(resource_.Get(), base::TimeTicks(),
ResourceFetcher::kDidFinishFirstPartInMultipart,
@@ -1142,7 +1190,7 @@ void ResourceLoader::DidFinishLoading(base::TimeTicks response_end_time,
TRACE_DISABLED_BY_DEFAULT("network"), "ResourceLoad",
TRACE_ID_WITH_SCOPE("BlinkResourceID",
TRACE_ID_LOCAL(resource_->InspectorId())),
- "endData", EndResourceLoadData(RequestOutcome::kSuccess));
+ "outcome", RequestOutcomeToString(RequestOutcome::kSuccess));
fetcher_->HandleLoaderFinish(
resource_.Get(), response_end_time, ResourceFetcher::kDidFinishLoading,
@@ -1209,7 +1257,7 @@ void ResourceLoader::HandleError(const ResourceError& error) {
TRACE_DISABLED_BY_DEFAULT("network"), "ResourceLoad",
TRACE_ID_WITH_SCOPE("BlinkResourceID",
TRACE_ID_LOCAL(resource_->InspectorId())),
- "endData", EndResourceLoadData(RequestOutcome::kFail));
+ "outcome", RequestOutcomeToString(RequestOutcome::kFail));
// Set Now() as the response time, in case a more accurate one wasn't set in
// DidFinishLoading or DidFail. This is important for error cases that don't
@@ -1222,11 +1270,6 @@ void ResourceLoader::HandleError(const ResourceError& error) {
inflight_keepalive_bytes_);
}
-void ResourceLoader::EvictFromBackForwardCache(
- mojom::RendererEvictionReason reason) {
- fetcher_->EvictFromBackForwardCache(reason);
-}
-
void ResourceLoader::RequestSynchronously(const ResourceRequestHead& request) {
DCHECK(loader_);
DCHECK_EQ(request.Priority(), ResourceLoadPriority::kHighest);
@@ -1507,4 +1550,73 @@ void ResourceLoader::HandleDataUrl() {
false /* should_report_corb_blocking */);
}
+bool ResourceLoader::ShouldBlockRequestBasedOnSubresourceFilterDnsAliasCheck(
+ const Vector<String>& dns_aliases,
+ const KURL& request_url,
+ const KURL& original_url,
+ ResourceType resource_type,
+ const ResourceRequestHead& initial_request,
+ const ResourceLoaderOptions& options,
+ const ResourceRequest::RedirectInfo redirect_info,
+ CnameAliasMetricInfo* out_metric_info) {
+ DCHECK(out_metric_info);
+
+ // Look for CNAME aliases, and if any are found, run SubresourceFilter
+ // checks on them to perform resource-blocking and ad-tagging based on the
+ // aliases: if any one of the aliases is on the denylist, then the
+ // request will be deemed on the denylist and treated accordingly (blocked
+ // and/or tagged).
+ out_metric_info->has_aliases = !dns_aliases.IsEmpty();
+ out_metric_info->list_length = dns_aliases.size();
+
+ // If there are no aliases, we have no reason to block based on them.
+ if (!out_metric_info->has_aliases)
+ return false;
+
+ // CNAME aliases were found, and so the SubresourceFilter must be
+ // consulted for each one.
+ // Create a copy of the request URL. We will swap out the host below.
+ KURL alias_url = request_url;
+
+ for (const String& alias : dns_aliases) {
+ alias_url.SetHost(alias);
+
+ // The SubresourceFilter only performs nontrivial matches for
+ // valid URLs. Skip sending this alias if it's invalid.
+ if (!alias_url.IsValid()) {
+ out_metric_info->invalid_count++;
+ continue;
+ }
+
+ // Do not perform a SubresourceFilter check on an `alias_url` that matches
+ // the requested URL (or, inclusively, the original URL in the case of
+ // redirects).
+ if (alias_url == original_url || alias_url == request_url) {
+ out_metric_info->redundant_count++;
+ continue;
+ }
+
+ base::Optional<ResourceRequestBlockedReason> blocked_reason =
+ Context().CanRequestBasedOnSubresourceFilterOnly(
+ resource_type, ResourceRequest(initial_request), alias_url, options,
+ ReportingDisposition::kReport, redirect_info);
+ if (blocked_reason) {
+ HandleError(ResourceError::CancelledDueToAccessCheckError(
+ alias_url, blocked_reason.value()));
+ out_metric_info->was_blocked_based_on_alias = true;
+ return true;
+ }
+
+ if (!resource_->GetResourceRequest().IsAdResource() &&
+ Context().CalculateIfAdSubresource(resource_->GetResourceRequest(),
+ alias_url, resource_type,
+ options.initiator_info)) {
+ resource_->SetIsAdResource();
+ out_metric_info->was_ad_tagged_based_on_alias = true;
+ }
+ }
+
+ return false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
index d53b0facf20..4498155f5be 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -31,6 +31,7 @@
#include <memory>
#include "base/containers/span.h"
+#include "base/feature_list.h"
#include "base/gtest_prod_util.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/base/big_buffer.h"
@@ -58,6 +59,17 @@ class ResourceError;
class ResourceFetcher;
class ResponseBodyLoader;
+// Struct for keeping variables used in recording CNAME alias metrics bundled
+// together.
+struct CnameAliasMetricInfo {
+ bool has_aliases = false;
+ bool was_ad_tagged_based_on_alias = false;
+ bool was_blocked_based_on_alias = false;
+ int list_length = 0;
+ int invalid_count = 0;
+ int redundant_count = 0;
+};
+
// A ResourceLoader is created for each Resource by the ResourceFetcher when it
// needs to load the specified resource. A ResourceLoader creates a
// WebURLLoader and loads the resource using it. Any per-load logic should be
@@ -140,7 +152,6 @@ class PLATFORM_EXPORT ResourceLoader final
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) override;
- void EvictFromBackForwardCache(mojom::RendererEvictionReason) override;
blink::mojom::CodeCacheType GetCodeCacheType() const;
void SendCachedCodeToResource(mojo_base::BigBuffer data);
@@ -205,6 +216,19 @@ class PLATFORM_EXPORT ResourceLoader final
// Processes Data URL in ResourceLoader instead of using |loader_|.
void HandleDataUrl();
+ // If enabled, performs SubresourceFilter checks for any DNS aliases found for
+ // the requested URL, which may result in ad-tagging the ResourceRequest.
+ // Returns true if the request should be blocked based on these checks.
+ bool ShouldBlockRequestBasedOnSubresourceFilterDnsAliasCheck(
+ const Vector<String>& dns_aliases,
+ const KURL& request_url,
+ const KURL& original_url,
+ ResourceType resource_type,
+ const ResourceRequestHead& initial_request,
+ const ResourceLoaderOptions& options,
+ const ResourceRequest::RedirectInfo redirect_info,
+ CnameAliasMetricInfo* out_metric_info);
+
std::unique_ptr<WebURLLoader> loader_;
ResourceLoadScheduler::ClientId scheduler_client_id_;
Member<ResourceFetcher> fetcher_;
@@ -247,7 +271,7 @@ class PLATFORM_EXPORT ResourceLoader final
// HandleDataURL().
bool defers_handling_data_url_ = false;
- TaskRunnerTimer<ResourceLoader> cancel_timer_;
+ HeapTaskRunnerTimer<ResourceLoader> cancel_timer_;
FrameScheduler::SchedulingAffectingFeatureHandle
feature_handle_for_scheduler_;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
index b3755010517..a4f285a969d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
@@ -118,7 +118,8 @@ class DeferTestLoaderFactory final : public ResourceFetcher::LoaderFactory {
const ResourceRequest& request,
const ResourceLoaderOptions& options,
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
override {
return std::make_unique<TestWebURLLoader>(defers_flag_);
}
@@ -159,7 +160,8 @@ class ResourceLoaderDefersLoadingTest : public testing::Test {
base::MakeRefCounted<scheduler::FakeTaskRunner>(),
MakeGarbageCollected<DeferTestLoaderFactory>(
&web_url_loader_defers_, process_code_cache_request_callback_),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ MakeGarbageCollected<MockContextLifecycleNotifier>(),
+ nullptr /* back_forward_cache_loader_helper */));
}
void SetCodeCacheProcessFunction(ProcessCodeCacheRequestCallback callback) {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
index e404cafa3ba..4b6952bad01 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOADER_OPTIONS_H_
#include "base/memory/scoped_refptr.h"
-#include "base/util/type_safety/strong_alias.h"
+#include "base/types/strong_alias.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink-forward.h"
@@ -70,7 +70,7 @@ enum CacheAwareLoadingEnabled : uint8_t {
// When true, a response is blocked unless it has
// cross-origin-embedder-policy: require-corp.
using RejectCoepUnsafeNone =
- util::StrongAlias<class RejectCoepUnsafeNoneTag, bool>;
+ base::StrongAlias<class RejectCoepUnsafeNoneTag, bool>;
// This class is thread-bound. Do not copy/pass an instance across threads.
struct PLATFORM_EXPORT ResourceLoaderOptions {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
index 615e434eff9..5458967f87e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
@@ -7,11 +7,15 @@
#include <string>
#include <utility>
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "mojo/public/c/system/data_pipe.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/web_url_request_extra_data.h"
@@ -29,6 +33,19 @@
namespace blink {
+const char kCnameAliasHadAliasesHistogram[] =
+ "SubresourceFilter.CnameAlias.Renderer.HadAliases";
+const char kCnameAliasIsInvalidCountHistogram[] =
+ "SubresourceFilter.CnameAlias.Renderer.InvalidCount";
+const char kCnameAliasIsRedundantCountHistogram[] =
+ "SubresourceFilter.CnameAlias.Renderer.RedundantCount";
+const char kCnameAliasListLengthHistogram[] =
+ "SubresourceFilter.CnameAlias.Renderer.ListLength";
+const char kCnameAliasWasAdTaggedHistogram[] =
+ "SubresourceFilter.CnameAlias.Renderer.WasAdTaggedBasedOnAlias";
+const char kCnameAliasWasBlockedHistogram[] =
+ "SubresourceFilter.CnameAlias.Renderer.WasBlockedBasedOnAlias";
+
class ResourceLoaderTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ResourceLoaderTest);
@@ -64,7 +81,8 @@ class ResourceLoaderTest : public testing::Test {
const ResourceRequest& request,
const ResourceLoaderOptions& options,
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
override {
return std::make_unique<NoopWebURLLoader>(
std::move(freezable_task_runner));
@@ -78,6 +96,16 @@ class ResourceLoaderTest : public testing::Test {
return base::MakeRefCounted<scheduler::FakeTaskRunner>();
}
+ ResourceFetcher* MakeResourceFetcher(
+ TestResourceFetcherProperties* properties,
+ FetchContext* context) {
+ return MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
+ properties->MakeDetachable(), context, CreateTaskRunner(),
+ CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
+ MakeGarbageCollected<MockContextLifecycleNotifier>(),
+ nullptr /* back_forward_cache_loader_helper */));
+ }
+
private:
class NoopWebURLLoader final : public WebURLLoader {
public:
@@ -141,10 +169,7 @@ std::ostream& operator<<(std::ostream& o, const ResourceLoaderTest::From& f) {
TEST_F(ResourceLoaderTest, LoadResponseBody) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
KURL url("https://www.example.com/");
ResourceRequest request(url);
@@ -165,7 +190,7 @@ TEST_F(ResourceLoaderTest, LoadResponseBody) {
options.element_num_bytes = 1;
options.capacity_num_bytes = 3;
- MojoResult result = CreateDataPipe(&options, &producer, &consumer);
+ MojoResult result = CreateDataPipe(&options, producer, consumer);
ASSERT_EQ(result, MOJO_RESULT_OK);
loader->DidReceiveResponse(WrappedResourceResponse(response));
@@ -206,10 +231,7 @@ TEST_F(ResourceLoaderTest, LoadResponseBody) {
TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndNonStream) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
// Fetch a data url.
KURL url("data:text/plain,Hello%20World!");
@@ -260,10 +282,7 @@ class TestRawResourceClient final
TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndStream) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
scheduler::FakeTaskRunner* task_runner =
static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get());
@@ -300,10 +319,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndStream) {
TEST_F(ResourceLoaderTest, LoadDataURL_AsyncEmptyData) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
// Fetch an empty data url.
KURL url("data:text/html,");
@@ -324,10 +340,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncEmptyData) {
TEST_F(ResourceLoaderTest, LoadDataURL_Sync) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
// Fetch a data url synchronously.
KURL url("data:text/plain,Hello%20World!");
@@ -350,10 +363,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_Sync) {
TEST_F(ResourceLoaderTest, LoadDataURL_SyncEmptyData) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
// Fetch an empty data url synchronously.
KURL url("data:text/html,");
@@ -372,10 +382,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_SyncEmptyData) {
TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndNonStream) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
scheduler::FakeTaskRunner* task_runner =
static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get());
@@ -419,10 +426,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndNonStream) {
TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndStream) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
scheduler::FakeTaskRunner* task_runner =
static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get());
@@ -493,10 +497,7 @@ class ResourceLoaderIsolatedCodeCacheTest : public ResourceLoaderTest {
auto* properties =
MakeGarbageCollected<TestResourceFetcherProperties>(origin);
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
- properties->MakeDetachable(), context, CreateTaskRunner(),
- CreateTaskRunner(), MakeGarbageCollected<NoopLoaderFactory>(),
- MakeGarbageCollected<MockContextLifecycleNotifier>()));
+ auto* fetcher = MakeResourceFetcher(properties, context);
ResourceRequest request;
request.SetUrl(foo_url_);
request.SetRequestContext(mojom::blink::RequestContextType::FETCH);
@@ -554,4 +555,286 @@ TEST_F(ResourceLoaderIsolatedCodeCacheTest, CacheResponseFromServiceWorker) {
EXPECT_EQ(false, LoadAndCheckIsolatedCodeCache(response));
}
+class ResourceLoaderSubresourceFilterCnameAliasTest
+ : public ResourceLoaderTest {
+ public:
+ ResourceLoaderSubresourceFilterCnameAliasTest() = default;
+ ~ResourceLoaderSubresourceFilterCnameAliasTest() override = default;
+
+ void SetUp() override {
+ feature_list_.InitAndEnableFeature(
+ features::kSendCnameAliasesToSubresourceFilterFromRenderer);
+ ResourceLoaderTest::SetUp();
+ }
+
+ base::HistogramTester* histogram_tester() { return &histogram_tester_; }
+
+ void SetMockSubresourceFilterBlockLists(Vector<String> blocked_urls,
+ Vector<String> tagged_urls) {
+ blocked_urls_ = blocked_urls;
+ tagged_urls_ = tagged_urls;
+ }
+
+ Resource* CreateResource(ResourceRequest request) {
+ FetchParameters params = FetchParameters::CreateForTest(std::move(request));
+ auto* fetcher = MakeResourceFetcherWithMockSubresourceFilter();
+ return RawResource::Fetch(params, fetcher, nullptr);
+ }
+
+ void GiveResponseToLoader(ResourceResponse response, ResourceLoader* loader) {
+ CreateMojoDataPipe();
+ loader->DidReceiveResponse(WrappedResourceResponse(response));
+ }
+
+ protected:
+ FetchContext* MakeFetchContextWithMockSubresourceFilter(
+ Vector<String> blocked_urls,
+ Vector<String> tagged_urls) {
+ auto* context = MakeGarbageCollected<MockFetchContext>();
+ context->set_blocked_urls(blocked_urls);
+ context->set_tagged_urls(tagged_urls);
+ return context;
+ }
+
+ ResourceFetcher* MakeResourceFetcherWithMockSubresourceFilter() {
+ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
+ FetchContext* context =
+ MakeFetchContextWithMockSubresourceFilter(blocked_urls_, tagged_urls_);
+ return MakeResourceFetcher(properties, context);
+ }
+
+ void CreateMojoDataPipe() {
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = 3;
+
+ MojoResult result = CreateDataPipe(&options, producer, consumer);
+ ASSERT_EQ(result, MOJO_RESULT_OK);
+ }
+
+ void ExpectHistogramsMatching(CnameAliasMetricInfo info) {
+ histogram_tester()->ExpectUniqueSample(kCnameAliasHadAliasesHistogram,
+ info.has_aliases, 1);
+
+ if (info.has_aliases) {
+ histogram_tester()->ExpectUniqueSample(kCnameAliasWasAdTaggedHistogram,
+ info.was_ad_tagged_based_on_alias,
+ 1);
+ histogram_tester()->ExpectUniqueSample(
+ kCnameAliasWasBlockedHistogram, info.was_blocked_based_on_alias, 1);
+ histogram_tester()->ExpectUniqueSample(kCnameAliasListLengthHistogram,
+ info.list_length, 1);
+ histogram_tester()->ExpectUniqueSample(kCnameAliasIsInvalidCountHistogram,
+ info.invalid_count, 1);
+ histogram_tester()->ExpectUniqueSample(
+ kCnameAliasIsRedundantCountHistogram, info.redundant_count, 1);
+ }
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+ base::HistogramTester histogram_tester_;
+ Vector<String> blocked_urls_;
+ Vector<String> tagged_urls_;
+};
+
+TEST_F(ResourceLoaderSubresourceFilterCnameAliasTest,
+ DnsAliasesCheckedBySubresourceFilterDisallowed_TaggedAndBlocked) {
+ // Set the blocklists: the first for blocking, the second for ad-tagging.
+ Vector<String> blocked_urls = {"https://bad-ad.com/some_path.html"};
+ Vector<String> tagged_urls = {"https://ad.com/some_path.html"};
+ SetMockSubresourceFilterBlockLists(blocked_urls, tagged_urls);
+
+ // Create the request.
+ KURL url("https://www.example.com/some_path.html");
+ ResourceRequest request(url);
+ request.SetRequestContext(mojom::blink::RequestContextType::FETCH);
+
+ // Create the resource and loader.
+ Resource* resource = CreateResource(std::move(request));
+ ResourceLoader* loader = resource->Loader();
+
+ // Create the response.
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+
+ // Set the CNAME aliases.
+ Vector<String> aliases({"ad.com", "bad-ad.com", "alias3.com"});
+ response.SetDnsAliases(aliases);
+
+ // Give the response to the loader.
+ GiveResponseToLoader(response, loader);
+
+ // Test the histograms to verify that the CNAME aliases were detected.
+ // Expect that the resource was tagged as a ad, due to first alias.
+ // Expect that the resource was blocked, due to second alias.
+ CnameAliasMetricInfo info = {.has_aliases = true,
+ .was_ad_tagged_based_on_alias = true,
+ .was_blocked_based_on_alias = true,
+ .list_length = 3,
+ .invalid_count = 0,
+ .redundant_count = 0};
+
+ ExpectHistogramsMatching(info);
+}
+
+TEST_F(ResourceLoaderSubresourceFilterCnameAliasTest,
+ DnsAliasesCheckedBySubresourceFilterDisallowed_BlockedOnly) {
+ // Set the blocklists: the first for blocking, the second for ad-tagging.
+ Vector<String> blocked_urls = {"https://bad-ad.com/some_path.html"};
+ Vector<String> tagged_urls = {};
+ SetMockSubresourceFilterBlockLists(blocked_urls, tagged_urls);
+
+ // Create the request.
+ KURL url("https://www.example.com/some_path.html");
+ ResourceRequest request(url);
+ request.SetRequestContext(mojom::blink::RequestContextType::FETCH);
+
+ // Create the resource and loader.
+ Resource* resource = CreateResource(std::move(request));
+ ResourceLoader* loader = resource->Loader();
+
+ // Create the response.
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+
+ // Set the CNAME aliases.
+ Vector<String> aliases({"ad.com", "bad-ad.com", "alias3.com"});
+ response.SetDnsAliases(aliases);
+
+ // Give the response to the loader.
+ GiveResponseToLoader(response, loader);
+
+ // Test the histograms to verify that the CNAME aliases were detected.
+ // Expect that the resource was blocked, due to second alias.
+ CnameAliasMetricInfo info = {.has_aliases = true,
+ .was_ad_tagged_based_on_alias = false,
+ .was_blocked_based_on_alias = true,
+ .list_length = 3,
+ .invalid_count = 0,
+ .redundant_count = 0};
+
+ ExpectHistogramsMatching(info);
+}
+
+TEST_F(ResourceLoaderSubresourceFilterCnameAliasTest,
+ DnsAliasesCheckedBySubresourceFilterDisallowed_TaggedOnly) {
+ // Set the blocklists: the first for blocking, the second for ad-tagging.
+ Vector<String> blocked_urls = {};
+ Vector<String> tagged_urls = {"https://bad-ad.com/some_path.html"};
+ SetMockSubresourceFilterBlockLists(blocked_urls, tagged_urls);
+
+ // Create the request.
+ KURL url("https://www.example.com/some_path.html");
+ ResourceRequest request(url);
+ request.SetRequestContext(mojom::blink::RequestContextType::FETCH);
+
+ // Create the resource and loader.
+ Resource* resource = CreateResource(std::move(request));
+ ResourceLoader* loader = resource->Loader();
+
+ // Create the response.
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+
+ // Set the CNAME aliases.
+ Vector<String> aliases({"ad.com", "", "alias3.com", "bad-ad.com"});
+ response.SetDnsAliases(aliases);
+
+ // Give the response to the loader.
+ GiveResponseToLoader(response, loader);
+
+ // Test the histograms to verify that the CNAME aliases were detected.
+ // Expect that the resource was tagged, due to fourth alias.
+ // Expect that the invalid empty alias is counted as such.
+ CnameAliasMetricInfo info = {.has_aliases = true,
+ .was_ad_tagged_based_on_alias = true,
+ .was_blocked_based_on_alias = false,
+ .list_length = 4,
+ .invalid_count = 1,
+ .redundant_count = 0};
+
+ ExpectHistogramsMatching(info);
+}
+
+TEST_F(ResourceLoaderSubresourceFilterCnameAliasTest,
+ DnsAliasesCheckedBySubresourceFilterAllowed_NotBlockedOrTagged) {
+ // Set the blocklists: the first for blocking, the second for ad-tagging.
+ Vector<String> blocked_urls = {};
+ Vector<String> tagged_urls = {};
+ SetMockSubresourceFilterBlockLists(blocked_urls, tagged_urls);
+
+ // Create the request.
+ KURL url("https://www.example.com/some_path.html");
+ ResourceRequest request(url);
+ request.SetRequestContext(mojom::blink::RequestContextType::FETCH);
+
+ // Create the resource and loader.
+ Resource* resource = CreateResource(std::move(request));
+ ResourceLoader* loader = resource->Loader();
+
+ // Create the response.
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+
+ // Set the CNAME aliases.
+ Vector<String> aliases(
+ {"non-ad.com", "?", "alias3.com", "not-an-ad.com", "www.example.com"});
+ response.SetDnsAliases(aliases);
+
+ // Give the response to the loader.
+ GiveResponseToLoader(response, loader);
+
+ // Test the histograms to verify that the CNAME aliases were detected.
+ // Expect that the resource was neither tagged nor blocked.
+ // Expect that the invalid alias is counted as such.
+ // Expect that the redundant (i.e. matching the request URL) fifth alias to be
+ // counted as such.
+ CnameAliasMetricInfo info = {.has_aliases = true,
+ .was_ad_tagged_based_on_alias = false,
+ .was_blocked_based_on_alias = false,
+ .list_length = 5,
+ .invalid_count = 1,
+ .redundant_count = 1};
+
+ ExpectHistogramsMatching(info);
+}
+
+TEST_F(ResourceLoaderSubresourceFilterCnameAliasTest,
+ DnsAliasesCheckedBySubresourceFilterNoAliases_NoneDetected) {
+ // Set the blocklists: the first for blocking, the second for ad-tagging.
+ Vector<String> blocked_urls = {};
+ Vector<String> tagged_urls = {};
+ SetMockSubresourceFilterBlockLists(blocked_urls, tagged_urls);
+
+ // Create the request.
+ KURL url("https://www.example.com/some_path.html");
+ ResourceRequest request(url);
+ request.SetRequestContext(mojom::blink::RequestContextType::FETCH);
+
+ // Create the resource and loader.
+ Resource* resource = CreateResource(std::move(request));
+ ResourceLoader* loader = resource->Loader();
+
+ // Create the response.
+ ResourceResponse response(url);
+ response.SetHttpStatusCode(200);
+
+ // Set the CNAME aliases.
+ Vector<String> aliases;
+ response.SetDnsAliases(aliases);
+
+ // Give the response to the loader.
+ GiveResponseToLoader(response, loader);
+
+ // Test the histogram to verify that no aliases were detected.
+ CnameAliasMetricInfo info = {.has_aliases = false};
+
+ ExpectHistogramsMatching(info);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h
index 62435966a4b..1be57a1ab0f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h
@@ -9,7 +9,7 @@
#if DCHECK_IS_ON()
// We can see logs with |--v=N| or |--vmodule=ResourceLoadingLog=N| where N is a
-// verbose level.
+// verbose level, as well as the |--enable-logging=stderr| CLI argument.
#define RESOURCE_LOADING_DVLOG(verbose_level) \
LAZY_STREAM( \
VLOG_STREAM(verbose_level), \
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
index 792cbebbfd1..7a460830b6b 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -30,6 +30,7 @@
#include "base/unguessable_token.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "services/network/public/mojom/web_bundle_handle.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
@@ -40,6 +41,42 @@
namespace blink {
+ResourceRequestHead::WebBundleTokenParams&
+ResourceRequestHead::WebBundleTokenParams::operator=(
+ const WebBundleTokenParams& other) {
+ bundle_url = other.bundle_url;
+ token = other.token;
+ handle = other.CloneHandle();
+ return *this;
+}
+
+ResourceRequestHead::WebBundleTokenParams::WebBundleTokenParams(
+ const WebBundleTokenParams& other) {
+ *this = other;
+}
+
+ResourceRequestHead::WebBundleTokenParams::WebBundleTokenParams(
+ const KURL& bundle_url,
+ const base::UnguessableToken& web_bundle_token,
+ mojo::PendingRemote<network::mojom::WebBundleHandle> web_bundle_handle)
+ : bundle_url(bundle_url),
+ token(web_bundle_token),
+ handle(std::move(web_bundle_handle)) {}
+
+mojo::PendingRemote<network::mojom::WebBundleHandle>
+ResourceRequestHead::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;
+}
+
const base::TimeDelta ResourceRequestHead::default_timeout_interval_ =
base::TimeDelta::Max();
@@ -127,26 +164,12 @@ ResourceRequest::ResourceRequest(const KURL& url) : ResourceRequestHead(url) {}
ResourceRequest::ResourceRequest(const ResourceRequestHead& head)
: ResourceRequestHead(head) {}
-ResourceRequest& ResourceRequest::operator=(const ResourceRequest& src) {
- DCHECK(!body_.StreamBody().is_valid());
- DCHECK(!src.body_.StreamBody().is_valid());
- this->ResourceRequestHead::operator=(src);
- body_.SetFormBody(src.body_.FormBody());
- return *this;
-}
-
ResourceRequest::ResourceRequest(ResourceRequest&&) = default;
ResourceRequest& ResourceRequest::operator=(ResourceRequest&&) = default;
ResourceRequest::~ResourceRequest() = default;
-void ResourceRequest::CopyFrom(const ResourceRequest& src) {
- DCHECK(!body_.StreamBody().is_valid());
- DCHECK(!src.body_.StreamBody().is_valid());
- *this = src;
-}
-
void ResourceRequest::CopyHeadFrom(const ResourceRequestHead& src) {
this->ResourceRequestHead::operator=(src);
}
@@ -197,6 +220,7 @@ std::unique_ptr<ResourceRequest> ResourceRequestHead::CreateRedirectRequest(
IsSignedExchangePrefetchCacheEnabled());
request->SetRecursivePrefetchToken(RecursivePrefetchToken());
request->SetFetchLikeAPI(IsFetchLikeAPI());
+ request->SetFavicon(IsFavicon());
return request;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index d55e1fae866..3290fa3a99e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -41,9 +41,12 @@
#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
+#include "services/network/public/mojom/url_loader.mojom-blink.h"
+#include "services/network/public/mojom/web_bundle_handle.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/web_url_request_extra_data.h"
+#include "third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
@@ -80,6 +83,23 @@ class PLATFORM_EXPORT ResourceRequestHead {
: original_url(original_url), previous_url(previous_url) {}
};
+ struct PLATFORM_EXPORT WebBundleTokenParams {
+ WebBundleTokenParams() = delete;
+ WebBundleTokenParams(const WebBundleTokenParams& other);
+ WebBundleTokenParams& operator=(const WebBundleTokenParams& other);
+
+ WebBundleTokenParams(
+ const KURL& bundle_url,
+ const base::UnguessableToken& token,
+ mojo::PendingRemote<network::mojom::WebBundleHandle> handle);
+
+ mojo::PendingRemote<network::mojom::WebBundleHandle> CloneHandle() const;
+
+ KURL bundle_url;
+ base::UnguessableToken token;
+ mojo::PendingRemote<network::mojom::WebBundleHandle> handle;
+ };
+
ResourceRequestHead();
explicit ResourceRequestHead(const KURL&);
@@ -457,6 +477,10 @@ class PLATFORM_EXPORT ResourceRequestHead {
void SetFetchLikeAPI(bool enabled) { is_fetch_like_api_ = enabled; }
+ bool IsFavicon() const { return is_favicon_; }
+
+ void SetFavicon(bool enabled) { is_favicon_ = enabled; }
+
bool PrefetchMaybeForTopLeveNavigation() const {
return prefetch_maybe_for_top_level_navigation_;
}
@@ -486,6 +510,23 @@ class PLATFORM_EXPORT ResourceRequestHead {
return allowHTTP1ForStreamingUpload_;
}
+ const base::Optional<ResourceRequestHead::WebBundleTokenParams>&
+ GetWebBundleTokenParams() const {
+ return web_bundle_token_params_;
+ }
+
+ void SetWebBundleTokenParams(
+ ResourceRequestHead::WebBundleTokenParams params) {
+ web_bundle_token_params_ = params;
+ }
+
+ void SetRenderBlockingBehavior(RenderBlockingBehavior behavior) {
+ render_blocking_behavior_ = behavior;
+ }
+ RenderBlockingBehavior GetRenderBlockingBehavior() const {
+ return render_blocking_behavior_;
+ }
+
private:
const CacheControlHeader& GetCacheControlHeader() const;
@@ -569,6 +610,8 @@ class PLATFORM_EXPORT ResourceRequestHead {
bool is_fetch_like_api_ = false;
+ bool is_favicon_ = false;
+
// Currently this is only used when a prefetch request has `as=document`
// specified. If true, and the request is cross-origin, the browser will cache
// the request under the cross-origin's partition. Furthermore, its reuse from
@@ -581,6 +624,16 @@ class PLATFORM_EXPORT ResourceRequestHead {
// prefetch responses. The browser process uses this token to ensure the
// request is cached correctly.
base::Optional<base::UnguessableToken> recursive_prefetch_token_;
+
+ // This is used when fetching either a WebBundle or a subresrouce in the
+ // WebBundle. The network process uses this token to associate the request to
+ // the bundle.
+ base::Optional<WebBundleTokenParams> web_bundle_token_params_;
+
+ // Render blocking behavior of the resource. Used in maintaining correct
+ // reporting for redirects.
+ RenderBlockingBehavior render_blocking_behavior_ =
+ RenderBlockingBehavior::kUnset;
};
class PLATFORM_EXPORT ResourceRequestBody {
@@ -644,13 +697,11 @@ class PLATFORM_EXPORT ResourceRequest final : public ResourceRequestHead {
ResourceRequest(const ResourceRequest&) = delete;
ResourceRequest(ResourceRequest&&);
+ ResourceRequest& operator=(const ResourceRequest&) = delete;
ResourceRequest& operator=(ResourceRequest&&);
~ResourceRequest();
- // TODO(yoichio): Use move semantics as much as possible.
- // See crbug.com/787704.
- void CopyFrom(const ResourceRequest&);
void CopyHeadFrom(const ResourceRequestHead&);
const scoped_refptr<EncodedFormData>& HttpBody() const;
@@ -659,8 +710,6 @@ class PLATFORM_EXPORT ResourceRequest final : public ResourceRequestHead {
ResourceRequestBody& MutableBody() { return body_; }
private:
- ResourceRequest& operator=(const ResourceRequest&);
-
ResourceRequestBody body_;
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
index 5fadb1c34d9..cbec9d25317 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -321,6 +321,9 @@ class PLATFORM_EXPORT ResourceResponse final {
app_cache_manifest_url_ = url;
}
+ const KURL& WebBundleURL() const { return web_bundle_url_; }
+ void SetWebBundleURL(const KURL& url) { web_bundle_url_ = url; }
+
bool WasFetchedViaSPDY() const { return was_fetched_via_spdy_; }
void SetWasFetchedViaSPDY(bool value) { was_fetched_via_spdy_ = value; }
@@ -358,6 +361,9 @@ class PLATFORM_EXPORT ResourceResponse final {
// https://html.spec.whatwg.org/C/#cors-cross-origin
bool IsCorsCrossOrigin() const;
+ int64_t GetPadding() const { return padding_; }
+ void SetPadding(int64_t padding) { padding_ = padding; }
+
// See network::ResourceResponseInfo::url_list_via_service_worker.
const Vector<KURL>& UrlListViaServiceWorker() const {
return url_list_via_service_worker_;
@@ -494,9 +500,23 @@ class PLATFORM_EXPORT ResourceResponse final {
was_cookie_in_request_ = was_cookie_in_request;
}
+ const Vector<String>& DnsAliases() const { return dns_aliases_; }
+
+ void SetDnsAliases(Vector<String> aliases) {
+ dns_aliases_ = std::move(aliases);
+ }
+
network::mojom::CrossOriginEmbedderPolicyValue GetCrossOriginEmbedderPolicy()
const;
+ const base::Optional<net::AuthChallengeInfo>& AuthChallengeInfo() const {
+ return auth_challenge_info_;
+ }
+ void SetAuthChallengeInfo(
+ const base::Optional<net::AuthChallengeInfo>& value) {
+ auth_challenge_info_ = value;
+ }
+
private:
void UpdateHeaderParsedState(const AtomicString& name);
@@ -597,6 +617,11 @@ class PLATFORM_EXPORT ResourceResponse final {
network::mojom::FetchResponseType response_type_ =
network::mojom::FetchResponseType::kDefault;
+ // Pre-computed padding. This should only be non-zero if |response_type| is
+ // set to kOpaque. In addition, it is only set if the response was provided
+ // by a service worker FetchEvent handler.
+ int64_t padding_ = 0;
+
// HTTP version used in the response, if known.
HTTPVersion http_version_ = kHTTPVersionUnknown;
@@ -666,6 +691,17 @@ class PLATFORM_EXPORT ResourceResponse final {
// cross-origin prefetch responses. It is used to pass the token along to
// preload header requests from these responses.
base::Optional<base::UnguessableToken> recursive_prefetch_token_;
+
+ // Any DNS aliases for the requested URL, as read from CNAME records.
+ // The alias chain order is preserved in reverse, from canonical name (i.e.
+ // address record name) through to query name.
+ Vector<String> dns_aliases_;
+
+ // The URL of WebBundle this response was loaded from. This value is only
+ // populated for resources loaded from a WebBundle.
+ KURL web_bundle_url_;
+
+ base::Optional<net::AuthChallengeInfo> auth_challenge_info_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc
index 1e2d9198ec8..ce3b6c5e949 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
@@ -102,4 +103,15 @@ TEST(ResourceResponseTest, AddHttpHeaderFieldWithMultipleValues) {
EXPECT_EQ("a=1, b=2, c=3", response.HttpHeaderField("set-cookie"));
}
+TEST(ResourceResponseTest, DnsAliasesCanBeSetAndAccessed) {
+ ResourceResponse response(CreateTestResponse());
+
+ EXPECT_TRUE(response.DnsAliases().IsEmpty());
+
+ Vector<String> aliases({"alias1", "alias2"});
+ response.SetDnsAliases(aliases);
+
+ EXPECT_THAT(response.DnsAliases(), testing::ElementsAre("alias1", "alias2"));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
index 4353c202b8a..7bbd1ee946e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
@@ -12,137 +12,13 @@
#include "third_party/blink/renderer/platform/loader/testing/mock_resource.h"
#include "third_party/blink/renderer/platform/loader/testing/mock_resource_client.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
-#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
namespace {
-class MockPlatform final : public TestingPlatformSupportWithMockScheduler {
- public:
- MockPlatform() = default;
- ~MockPlatform() override = default;
-
- // From blink::Platform:
- void CacheMetadata(blink::mojom::CodeCacheType cache_type,
- const WebURL& url,
- base::Time,
- const uint8_t*,
- size_t) override {
- cached_urls_.push_back(url);
- }
-
- void CacheMetadataInCacheStorage(const blink::WebURL& url,
- base::Time,
- const uint8_t*,
- size_t,
- const blink::WebSecurityOrigin&,
- const blink::WebString&) override {
- cache_storage_cached_urls_.push_back(url);
- }
-
- const Vector<WebURL>& CachedURLs() const { return cached_urls_; }
- const Vector<WebURL>& CacheStorageCachedURLs() const {
- return cache_storage_cached_urls_;
- }
-
- private:
- Vector<WebURL> cached_urls_;
- Vector<WebURL> cache_storage_cached_urls_;
-};
-
-ResourceResponse CreateTestResourceResponse() {
- ResourceResponse response(url_test_helpers::ToKURL("https://example.com/"));
- response.SetHttpStatusCode(200);
- return response;
-}
-
-void CreateTestResourceAndSetCachedMetadata(const ResourceResponse& response) {
- const uint8_t kTestData[] = {1, 2, 3, 4, 5};
- ResourceRequest request(response.CurrentRequestUrl());
- request.SetRequestorOrigin(
- SecurityOrigin::Create(response.CurrentRequestUrl()));
- auto* resource = MakeGarbageCollected<MockResource>(request);
- resource->SetResponse(response);
- resource->SendCachedMetadata(kTestData, sizeof(kTestData));
- return;
-}
-
-} // anonymous namespace
-
-TEST(ResourceTest, SetCachedMetadata_SendsMetadataToPlatform) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
- ResourceResponse response(CreateTestResourceResponse());
- CreateTestResourceAndSetCachedMetadata(response);
- EXPECT_EQ(1u, mock->CachedURLs().size());
- EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
-}
-
-TEST(
- ResourceTest,
- SetCachedMetadata_DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithSyntheticResponse) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
-
- // Equivalent to service worker calling respondWith(new Response(...))
- ResourceResponse response(CreateTestResourceResponse());
- response.SetWasFetchedViaServiceWorker(true);
-
- CreateTestResourceAndSetCachedMetadata(response);
- EXPECT_EQ(0u, mock->CachedURLs().size());
- EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
-}
-
-TEST(
- ResourceTest,
- SetCachedMetadata_SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithPassThroughResponse) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
-
- // Equivalent to service worker calling respondWith(fetch(evt.request.url));
- ResourceResponse response(CreateTestResourceResponse());
- response.SetWasFetchedViaServiceWorker(true);
- response.SetUrlListViaServiceWorker(
- Vector<KURL>(1, response.CurrentRequestUrl()));
-
- CreateTestResourceAndSetCachedMetadata(response);
- EXPECT_EQ(1u, mock->CachedURLs().size());
- EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
-}
-
-TEST(
- ResourceTest,
- SetCachedMetadata_DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithDifferentURLResponse) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
-
- // Equivalent to service worker calling respondWith(fetch(some_different_url))
- ResourceResponse response(CreateTestResourceResponse());
- response.SetWasFetchedViaServiceWorker(true);
- response.SetUrlListViaServiceWorker(Vector<KURL>(
- 1, url_test_helpers::ToKURL("https://example.com/different/url")));
-
- CreateTestResourceAndSetCachedMetadata(response);
- EXPECT_EQ(0u, mock->CachedURLs().size());
- EXPECT_EQ(0u, mock->CacheStorageCachedURLs().size());
-}
-
-TEST(
- ResourceTest,
- SetCachedMetadata_SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithCacheResponse) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
-
- // Equivalent to service worker calling respondWith(cache.match(some_url));
- ResourceResponse response(CreateTestResourceResponse());
- response.SetWasFetchedViaServiceWorker(true);
- response.SetCacheStorageCacheName("dummy");
-
- CreateTestResourceAndSetCachedMetadata(response);
- EXPECT_EQ(0u, mock->CachedURLs().size());
- EXPECT_EQ(1u, mock->CacheStorageCachedURLs().size());
-}
-
TEST(ResourceTest, RevalidateWithFragment) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
KURL url("http://127.0.0.1:8000/foo.html");
ResourceResponse response(url);
response.SetHttpStatusCode(200);
@@ -160,7 +36,6 @@ TEST(ResourceTest, RevalidateWithFragment) {
}
TEST(ResourceTest, Vary) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
const KURL url("http://127.0.0.1:8000/foo.html");
ResourceResponse response(url);
response.SetHttpStatusCode(200);
@@ -228,14 +103,9 @@ TEST(ResourceTest, RevalidationFailed) {
resource->FinishForTest();
GetMemoryCache()->Add(resource);
- MockCacheHandler* original_cache_handler = resource->CacheHandler();
- EXPECT_TRUE(original_cache_handler);
-
// Simulate revalidation start.
resource->SetRevalidatingRequest(ResourceRequest(url));
- EXPECT_EQ(original_cache_handler, resource->CacheHandler());
-
Persistent<MockResourceClient> client =
MakeGarbageCollected<MockResourceClient>();
resource->AddClient(client, nullptr);
@@ -247,8 +117,6 @@ TEST(ResourceTest, RevalidationFailed) {
EXPECT_FALSE(resource->IsCacheValidator());
EXPECT_EQ(200, resource->GetResponse().HttpStatusCode());
EXPECT_FALSE(resource->ResourceBuffer());
- EXPECT_TRUE(resource->CacheHandler());
- EXPECT_NE(original_cache_handler, resource->CacheHandler());
EXPECT_EQ(resource, GetMemoryCache()->ResourceForURL(url));
resource->AppendData(kData, 4);
@@ -265,7 +133,7 @@ TEST(ResourceTest, RevalidationFailed) {
TEST(ResourceTest, RevalidationSucceeded) {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
- platform_;
+ platform;
const KURL url("http://test.example.com/");
auto* resource = MakeGarbageCollected<MockResource>(url);
ResourceResponse response(url);
@@ -276,14 +144,9 @@ TEST(ResourceTest, RevalidationSucceeded) {
resource->FinishForTest();
GetMemoryCache()->Add(resource);
- MockCacheHandler* original_cache_handler = resource->CacheHandler();
- EXPECT_TRUE(original_cache_handler);
-
// Simulate a successful revalidation.
resource->SetRevalidatingRequest(ResourceRequest(url));
- EXPECT_EQ(original_cache_handler, resource->CacheHandler());
-
Persistent<MockResourceClient> client =
MakeGarbageCollected<MockResourceClient>();
resource->AddClient(client, nullptr);
@@ -295,7 +158,6 @@ TEST(ResourceTest, RevalidationSucceeded) {
EXPECT_FALSE(resource->IsCacheValidator());
EXPECT_EQ(200, resource->GetResponse().HttpStatusCode());
EXPECT_EQ(4u, resource->ResourceBuffer()->size());
- EXPECT_EQ(original_cache_handler, resource->CacheHandler());
EXPECT_EQ(resource, GetMemoryCache()->ResourceForURL(url));
GetMemoryCache()->Remove(resource);
@@ -307,7 +169,7 @@ TEST(ResourceTest, RevalidationSucceeded) {
TEST(ResourceTest, RevalidationSucceededForResourceWithoutBody) {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
- platform_;
+ platform;
const KURL url("http://test.example.com/");
auto* resource = MakeGarbageCollected<MockResource>(url);
ResourceResponse response(url);
@@ -339,7 +201,7 @@ TEST(ResourceTest, RevalidationSucceededForResourceWithoutBody) {
TEST(ResourceTest, RevalidationSucceededUpdateHeaders) {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
- platform_;
+ platform;
const KURL url("http://test.example.com/");
auto* resource = MakeGarbageCollected<MockResource>(url);
ResourceResponse response(url);
@@ -415,7 +277,7 @@ TEST(ResourceTest, RevalidationSucceededUpdateHeaders) {
TEST(ResourceTest, RedirectDuringRevalidation) {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
- platform_;
+ platform;
const KURL url("http://test.example.com/1");
const KURL redirect_target_url("http://test.example.com/2");
@@ -432,15 +294,11 @@ TEST(ResourceTest, RedirectDuringRevalidation) {
EXPECT_EQ(url, resource->GetResourceRequest().Url());
EXPECT_EQ(url, resource->LastResourceRequest().Url());
- MockCacheHandler* original_cache_handler = resource->CacheHandler();
- EXPECT_TRUE(original_cache_handler);
-
// Simulate a revalidation.
resource->SetRevalidatingRequest(ResourceRequest(url));
EXPECT_TRUE(resource->IsCacheValidator());
EXPECT_EQ(url, resource->GetResourceRequest().Url());
EXPECT_EQ(url, resource->LastResourceRequest().Url());
- EXPECT_EQ(original_cache_handler, resource->CacheHandler());
Persistent<MockResourceClient> client =
MakeGarbageCollected<MockResourceClient>();
@@ -457,15 +315,12 @@ TEST(ResourceTest, RedirectDuringRevalidation) {
EXPECT_FALSE(resource->IsCacheValidator());
EXPECT_EQ(url, resource->GetResourceRequest().Url());
EXPECT_EQ(redirect_target_url, resource->LastResourceRequest().Url());
- EXPECT_FALSE(resource->CacheHandler());
// The final response is received.
ResourceResponse revalidating_response(redirect_target_url);
revalidating_response.SetHttpStatusCode(200);
resource->ResponseReceived(revalidating_response);
- EXPECT_TRUE(resource->CacheHandler());
-
const char kData2[4] = "xyz";
resource->AppendData(kData2, 3);
resource->FinishForTest();
@@ -482,13 +337,11 @@ TEST(ResourceTest, RedirectDuringRevalidation) {
// Test the case where a client is added after revalidation is completed.
Persistent<MockResourceClient> client2 =
MakeGarbageCollected<MockResourceClient>();
- auto* platform = static_cast<TestingPlatformSupportWithMockScheduler*>(
- Platform::Current());
resource->AddClient(client2, platform->test_task_runner().get());
// Because the client is added asynchronously,
// |runUntilIdle()| is called to make |client2| to be notified.
- platform_->RunUntilIdle();
+ platform->RunUntilIdle();
EXPECT_TRUE(client2->NotifyFinishedCalled());
@@ -508,7 +361,7 @@ class ScopedResourceMockClock {
};
TEST(ResourceTest, StaleWhileRevalidateCacheControl) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
+ ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> mock;
ScopedResourceMockClock clock(mock->test_task_runner()->GetMockClock());
const KURL url("http://127.0.0.1:8000/foo.html");
ResourceResponse response(url);
@@ -536,7 +389,7 @@ TEST(ResourceTest, StaleWhileRevalidateCacheControl) {
}
TEST(ResourceTest, StaleWhileRevalidateCacheControlWithRedirect) {
- ScopedTestingPlatformSupport<MockPlatform> mock;
+ ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> mock;
ScopedResourceMockClock clock(mock->test_task_runner()->GetMockClock());
const KURL url("http://127.0.0.1:8000/foo.html");
const KURL redirect_target_url("http://127.0.0.1:8000/food.html");
@@ -582,4 +435,13 @@ TEST(ResourceTest, DefaultOverheadSize) {
EXPECT_EQ(resource->CalculateOverheadSizeForTest(), resource->OverheadSize());
}
+TEST(ResourceTest, SetIsAdResource) {
+ const KURL url("http://127.0.0.1:8000/foo.html");
+ auto* resource = MakeGarbageCollected<MockResource>(url);
+ EXPECT_FALSE(resource->GetResourceRequest().IsAdResource());
+ resource->SetIsAdResource();
+ EXPECT_TRUE(resource->GetResourceRequest().IsAdResource());
+}
+
+} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
index 611a1701ad6..1bd85bd0f18 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
@@ -9,6 +9,8 @@
#include "base/auto_reset.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink.h"
+#include "third_party/blink/renderer/platform/back_forward_cache_utils.h"
+#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
@@ -18,7 +20,7 @@ namespace blink {
constexpr size_t ResponseBodyLoader::kMaxNumConsumedBytesInTask;
-constexpr size_t kDefaultMaxBufferedBodyBytes = 100 * 1000;
+constexpr size_t kDefaultMaxBufferedBodyBytesPerRequest = 100 * 1000;
class ResponseBodyLoader::DelegatingBytesConsumer final
: public BytesConsumer,
@@ -286,10 +288,9 @@ class ResponseBodyLoader::Buffer final
public:
explicit Buffer(ResponseBodyLoader* owner)
: owner_(owner),
- max_bytes_to_read_(base::GetFieldTrialParamByFeatureAsInt(
- blink::features::kLoadingTasksUnfreezable,
+ max_bytes_to_read_(GetLoadingTasksUnfreezableParamAsInt(
"max_buffered_bytes",
- kDefaultMaxBufferedBodyBytes)) {}
+ kDefaultMaxBufferedBodyBytesPerRequest)) {}
bool IsEmpty() const { return buffered_data_.IsEmpty(); }
@@ -297,6 +298,9 @@ class ResponseBodyLoader::Buffer final
// exceeds |max_bytes_to_read_| bytes.
bool AddChunk(const char* buffer, size_t available) {
total_bytes_read_ += available;
+ TRACE_EVENT2("loading", "ResponseBodyLoader::Buffer::AddChunk",
+ "total_bytes_read", static_cast<int>(total_bytes_read_),
+ "added_bytes", static_cast<int>(available));
if (total_bytes_read_ > max_bytes_to_read_)
return false;
Vector<char> new_chunk;
@@ -344,9 +348,11 @@ class ResponseBodyLoader::Buffer final
ResponseBodyLoader::ResponseBodyLoader(
BytesConsumer& bytes_consumer,
ResponseBodyLoaderClient& client,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ BackForwardCacheLoaderHelper* back_forward_cache_loader_helper)
: bytes_consumer_(bytes_consumer),
client_(client),
+ back_forward_cache_loader_helper_(back_forward_cache_loader_helper),
task_runner_(std::move(task_runner)) {
bytes_consumer_->SetClient(this);
body_buffer_ = MakeGarbageCollected<Buffer>(this);
@@ -433,10 +439,26 @@ void ResponseBodyLoader::DidCancelLoadingBody() {
client_->DidCancelLoadingBody();
}
-// TODO(yuzus): Remove this and provide the capability to the loader.
void ResponseBodyLoader::EvictFromBackForwardCache(
mojom::blink::RendererEvictionReason reason) {
- client_->EvictFromBackForwardCache(reason);
+ if (!back_forward_cache_loader_helper_)
+ return;
+ back_forward_cache_loader_helper_->EvictFromBackForwardCache(reason);
+}
+
+void ResponseBodyLoader::DidBufferLoadWhileInBackForwardCache(
+ size_t num_bytes) {
+ if (!back_forward_cache_loader_helper_)
+ return;
+ back_forward_cache_loader_helper_->DidBufferLoadWhileInBackForwardCache(
+ num_bytes);
+}
+
+bool ResponseBodyLoader::CanContinueBufferingWhileInBackForwardCache() {
+ if (!back_forward_cache_loader_helper_)
+ return false;
+ return back_forward_cache_loader_helper_
+ ->CanContinueBufferingWhileInBackForwardCache();
}
void ResponseBodyLoader::Start() {
@@ -470,7 +492,7 @@ void ResponseBodyLoader::Suspend(WebURLLoader::DeferType suspended_state) {
suspended_state_ = suspended_state;
if (IsSuspendedForBackForwardCache()) {
- DCHECK(base::FeatureList::IsEnabled(features::kLoadingTasksUnfreezable));
+ DCHECK(IsInflightNetworkRequestBackForwardCacheSupportEnabled());
// If we're already suspended (but not for back-forward cache), we might've
// ignored some OnStateChange calls.
if (was_suspended) {
@@ -483,7 +505,7 @@ void ResponseBodyLoader::Suspend(WebURLLoader::DeferType suspended_state) {
void ResponseBodyLoader::EvictFromBackForwardCacheIfDrained() {
if (IsDrained()) {
- client_->EvictFromBackForwardCache(
+ EvictFromBackForwardCache(
mojom::blink::RendererEvictionReason::kNetworkRequestDatapipeDrained);
}
}
@@ -554,7 +576,9 @@ void ResponseBodyLoader::OnStateChange() {
std::min(available, kMaxNumConsumedBytesInTask - num_bytes_consumed);
if (IsSuspendedForBackForwardCache()) {
// Save the read data into |body_buffer_| instead.
- if (!body_buffer_->AddChunk(buffer, available)) {
+ DidBufferLoadWhileInBackForwardCache(available);
+ if (!body_buffer_->AddChunk(buffer, available) ||
+ !CanContinueBufferingWhileInBackForwardCache()) {
// We've read too much data while suspended for back-forward cache.
// Evict the page from the back-forward cache.
result = bytes_consumer_->EndRead(available);
@@ -598,6 +622,7 @@ void ResponseBodyLoader::Trace(Visitor* visitor) const {
visitor->Trace(delegating_bytes_consumer_);
visitor->Trace(client_);
visitor->Trace(body_buffer_);
+ visitor->Trace(back_forward_cache_loader_helper_);
ResponseBodyLoaderDrainableInterface::Trace(visitor);
ResponseBodyLoaderClient::Trace(visitor);
BytesConsumer::Client::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
index 1589dfddbcd..4ca1a94aa88 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
@@ -9,6 +9,7 @@
#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink-forward.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/member.h"
@@ -24,6 +25,7 @@ class SingleThreadTaskRunner;
namespace blink {
+class BackForwardCacheLoaderHelper;
class ResponseBodyLoader;
// See ResponseBodyLoader for details. This is a virtual interface to expose
@@ -74,9 +76,11 @@ class PLATFORM_EXPORT ResponseBodyLoader final
private ResponseBodyLoaderClient,
private BytesConsumer::Client {
public:
- ResponseBodyLoader(BytesConsumer&,
- ResponseBodyLoaderClient&,
- scoped_refptr<base::SingleThreadTaskRunner>);
+ ResponseBodyLoader(
+ BytesConsumer&,
+ ResponseBodyLoaderClient&,
+ scoped_refptr<base::SingleThreadTaskRunner>,
+ BackForwardCacheLoaderHelper* back_forward_cache_loader_helper);
// ResponseBodyLoaderDrainableInterface implementation.
mojo::ScopedDataPipeConsumerHandle DrainAsDataPipe(
@@ -127,17 +131,19 @@ class PLATFORM_EXPORT ResponseBodyLoader final
void DidFinishLoadingBody() override;
void DidFailLoadingBody() override;
void DidCancelLoadingBody() override;
- void EvictFromBackForwardCache(mojom::blink::RendererEvictionReason) override;
+ void EvictFromBackForwardCache(mojom::blink::RendererEvictionReason);
+ void DidBufferLoadWhileInBackForwardCache(size_t num_bytes);
+ bool CanContinueBufferingWhileInBackForwardCache();
// BytesConsumer::Client implementation.
void OnStateChange() override;
String DebugName() const override { return "ResponseBodyLoader"; }
- // When |buffer_data_while_suspended_for_bfcache_| is true, we'll save the
- // response body read when suspended.
+
Member<Buffer> body_buffer_;
Member<BytesConsumer> bytes_consumer_;
Member<DelegatingBytesConsumer> delegating_bytes_consumer_;
const Member<ResponseBodyLoaderClient> client_;
+ WeakMember<BackForwardCacheLoaderHelper> back_forward_cache_loader_helper_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
WebURLLoader::DeferType suspended_state_ =
WebURLLoader::DeferType::kNotDeferred;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h
index ef9d2d87ea9..993a92f26e3 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h
@@ -27,10 +27,6 @@ class ResponseBodyLoaderClient : public GarbageCollectedMixin {
// Called when the loader cancelled loading the body.
virtual void DidCancelLoadingBody() = 0;
-
- // Called when the body loader is suspended and the data pipe is drained.
- virtual void EvictFromBackForwardCache(
- mojom::blink::RendererEvictionReason) = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
index 4c22d831f78..0b0d928c738 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
@@ -10,7 +10,9 @@
#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h"
#include "third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h"
#include "third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.h"
@@ -21,6 +23,15 @@ namespace blink {
namespace {
+class TestBackForwardCacheLoaderHelper : public BackForwardCacheLoaderHelper {
+ public:
+ TestBackForwardCacheLoaderHelper() = default;
+
+ bool CanContinueBufferingWhileInBackForwardCache() const override {
+ return true;
+ }
+};
+
class ResponseBodyLoaderTest : public testing::Test {
protected:
using Command = ReplayingBytesConsumer::Command;
@@ -74,7 +85,6 @@ class ResponseBodyLoaderTest : public testing::Test {
DCHECK(!failed_);
cancelled_ = true;
}
- void EvictFromBackForwardCache(mojom::RendererEvictionReason) override {}
void SetLoader(ResponseBodyLoader& loader) { loader_ = loader; }
void Trace(Visitor* visitor) const override { visitor->Trace(loader_); }
@@ -134,6 +144,15 @@ class ResponseBodyLoaderTest : public testing::Test {
const Member<BytesConsumer> bytes_consumer_;
const Member<TestClient> test_response_body_loader_client_;
};
+
+ ResponseBodyLoader* MakeResponseBodyLoader(
+ BytesConsumer& bytes_consumer,
+ ResponseBodyLoaderClient& client,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ return MakeGarbageCollected<ResponseBodyLoader>(
+ bytes_consumer, client, task_runner,
+ MakeGarbageCollected<TestBackForwardCacheLoaderHelper>());
+ }
};
class ResponseBodyLoaderDrainedBytesConsumerNotificationOutOfOnStateChangeTest
@@ -151,8 +170,7 @@ TEST_F(ResponseBodyLoaderTest, Load) {
consumer->Add(Command(Command::kDone));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
EXPECT_FALSE(client->LoadingIsFinished());
EXPECT_FALSE(client->LoadingIsFailed());
@@ -180,8 +198,7 @@ TEST_F(ResponseBodyLoaderTest, LoadFailure) {
consumer->Add(Command(Command::kError));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
EXPECT_FALSE(client->LoadingIsFinished());
EXPECT_FALSE(client->LoadingIsFailed());
@@ -208,8 +225,7 @@ TEST_F(ResponseBodyLoaderTest, LoadWithDataAndDone) {
consumer->Add(Command(Command::kDataAndDone, "llo"));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
EXPECT_FALSE(client->LoadingIsFinished());
EXPECT_FALSE(client->LoadingIsFailed());
@@ -238,8 +254,7 @@ TEST_F(ResponseBodyLoaderTest, Abort) {
auto* client = MakeGarbageCollected<TestClient>(
TestClient::Option::kAbortOnDidReceiveData);
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
client->SetLoader(*body_loader);
EXPECT_FALSE(client->LoadingIsFinished());
@@ -270,8 +285,7 @@ TEST_F(ResponseBodyLoaderTest, Suspend) {
auto* client = MakeGarbageCollected<TestClient>(
TestClient::Option::kSuspendOnDidReceiveData);
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
client->SetLoader(*body_loader);
EXPECT_FALSE(client->LoadingIsFinished());
@@ -335,8 +349,7 @@ TEST_F(ResponseBodyLoaderTest, ReadTooBigBuffer) {
consumer->Add(Command(Command::kDone));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
EXPECT_FALSE(client->LoadingIsFinished());
EXPECT_FALSE(client->LoadingIsFailed());
@@ -367,8 +380,7 @@ TEST_F(ResponseBodyLoaderTest, NotDrainable) {
consumer->Add(Command(Command::kDone));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
ResponseBodyLoaderClient* intermediate_client = nullptr;
auto data_pipe = body_loader->DrainAsDataPipe(&intermediate_client);
@@ -399,7 +411,7 @@ TEST_F(ResponseBodyLoaderTest, NotDrainable) {
TEST_F(ResponseBodyLoaderTest, DrainAsDataPipe) {
mojo::ScopedDataPipeConsumerHandle consumer_end;
mojo::ScopedDataPipeProducerHandle producer_end;
- auto result = mojo::CreateDataPipe(nullptr, &producer_end, &consumer_end);
+ auto result = mojo::CreateDataPipe(nullptr, producer_end, consumer_end);
ASSERT_EQ(result, MOJO_RESULT_OK);
@@ -410,8 +422,7 @@ TEST_F(ResponseBodyLoaderTest, DrainAsDataPipe) {
task_runner, std::move(consumer_end), &completion_notifier);
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
ResponseBodyLoaderClient* client_for_draining = nullptr;
auto data_pipe = body_loader->DrainAsDataPipe(&client_for_draining);
@@ -443,6 +454,8 @@ class ResponseBodyLoaderLoadingTasksUnfreezableTest
scoped_feature_list_.InitAndEnableFeature(
features::kLoadingTasksUnfreezable);
}
+ WebRuntimeFeatures::EnableBackForwardCache(
+ DeferWithBackForwardCacheEnabled());
}
bool DeferWithBackForwardCacheEnabled() { return GetParam(); }
@@ -458,8 +471,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
auto* consumer = MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
consumer->Add(Command(Command::kData, "he"));
body_loader->Start();
task_runner->RunUntilIdle();
@@ -517,8 +529,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
auto* consumer = MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
consumer->Add(Command(Command::kData, "he"));
body_loader->Start();
task_runner->RunUntilIdle();
@@ -571,8 +582,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
auto* consumer = MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
consumer->Add(Command(Command::kData, "he"));
body_loader->Start();
task_runner->RunUntilIdle();
@@ -634,8 +644,7 @@ TEST_P(ResponseBodyLoaderLoadingTasksUnfreezableTest,
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
auto* consumer = MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
body_loader->Start();
task_runner->RunUntilIdle();
EXPECT_EQ("", client->GetData());
@@ -675,7 +684,7 @@ INSTANTIATE_TEST_SUITE_P(All,
TEST_F(ResponseBodyLoaderTest, DrainAsDataPipeAndReportError) {
mojo::ScopedDataPipeConsumerHandle consumer_end;
mojo::ScopedDataPipeProducerHandle producer_end;
- auto result = mojo::CreateDataPipe(nullptr, &producer_end, &consumer_end);
+ auto result = mojo::CreateDataPipe(nullptr, producer_end, consumer_end);
ASSERT_EQ(result, MOJO_RESULT_OK);
@@ -686,8 +695,7 @@ TEST_F(ResponseBodyLoaderTest, DrainAsDataPipeAndReportError) {
task_runner, std::move(consumer_end), &completion_notifier);
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader =
- MakeGarbageCollected<ResponseBodyLoader>(*consumer, *client, task_runner);
+ auto* body_loader = MakeResponseBodyLoader(*consumer, *client, task_runner);
ResponseBodyLoaderClient* client_for_draining = nullptr;
auto data_pipe = body_loader->DrainAsDataPipe(&client_for_draining);
@@ -721,8 +729,9 @@ TEST_F(ResponseBodyLoaderTest, DrainAsBytesConsumer) {
original_consumer->Add(Command(Command::kDone));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
@@ -750,8 +759,9 @@ TEST_F(ResponseBodyLoaderTest, CancelDrainedBytesConsumer) {
original_consumer->Add(Command(Command::kDone));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
@@ -786,8 +796,9 @@ TEST_F(ResponseBodyLoaderTest, DrainAsBytesConsumerWithError) {
original_consumer->Add(Command(Command::kError));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
@@ -814,8 +825,9 @@ TEST_F(ResponseBodyLoaderTest, AbortAfterBytesConsumerIsDrained) {
original_consumer->Add(Command(Command::kDone));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
auto* bytes_consumer_client =
@@ -844,8 +856,9 @@ TEST_F(ResponseBodyLoaderTest, AbortAfterBytesConsumerIsDrainedIsNotified) {
MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
@@ -873,8 +886,9 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationOutOfOnStateChangeTest,
original_consumer->Add(Command(Command::kDone));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
const char* buffer = nullptr;
@@ -920,8 +934,9 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationOutOfOnStateChangeTest,
original_consumer->Add(Command(Command::kError));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
const char* buffer = nullptr;
@@ -972,8 +987,9 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationOutOfOnStateChangeTest,
original_consumer->Add(Command(Command::kDataAndDone, "hello"));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
const char* buffer = nullptr;
@@ -1019,7 +1035,7 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationOutOfOnStateChangeTest,
DrainAsDataPipe) {
mojo::ScopedDataPipeConsumerHandle consumer_end;
mojo::ScopedDataPipeProducerHandle producer_end;
- auto result = mojo::CreateDataPipe(nullptr, &producer_end, &consumer_end);
+ auto result = mojo::CreateDataPipe(nullptr, producer_end, consumer_end);
ASSERT_EQ(result, MOJO_RESULT_OK);
@@ -1030,8 +1046,8 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationOutOfOnStateChangeTest,
task_runner, std::move(consumer_end), &completion_notifier);
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
@@ -1058,8 +1074,9 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationOutOfOnStateChangeTest,
original_consumer->Add(Command(Command::kWait));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
task_runner->RunUntilIdle();
@@ -1087,8 +1104,9 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationInOnStateChangeTest,
original_consumer->Add(Command(Command::kDone));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
auto* reading_client = MakeGarbageCollected<ReadingClient>(consumer, *client);
@@ -1127,8 +1145,9 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationInOnStateChangeTest,
original_consumer->Add(Command(Command::kError));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
auto* reading_client = MakeGarbageCollected<ReadingClient>(consumer, *client);
@@ -1167,8 +1186,9 @@ TEST_F(ResponseBodyLoaderDrainedBytesConsumerNotificationInOnStateChangeTest,
original_consumer->Add(Command(Command::kDataAndDone, "hahaha"));
auto* client = MakeGarbageCollected<TestClient>();
- auto* body_loader = MakeGarbageCollected<ResponseBodyLoader>(
- *original_consumer, *client, task_runner);
+
+ auto* body_loader =
+ MakeResponseBodyLoader(*original_consumer, *client, task_runner);
BytesConsumer& consumer = body_loader->DrainAsBytesConsumer();
auto* reading_client = MakeGarbageCollected<ReadingClient>(consumer, *client);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc
index 6f58aa7b447..399d8302dd7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc
@@ -30,6 +30,7 @@ FetchParameters ScriptFetchOptions::CreateFetchParameters(
FetchParameters params(std::move(resource_request), resource_loader_options);
params.SetRequestContext(mojom::blink::RequestContextType::SCRIPT);
params.SetRequestDestination(network::mojom::RequestDestination::kScript);
+ params.SetRenderBlockingBehavior(render_blocking_behavior_);
// Step 1. ... and CORS setting. [spec text]
if (cross_origin != kCrossOriginAttributeNotSet)
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
index 13a4cbd2c6f..74cff0cd404 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
+#include "third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -47,6 +48,7 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
network::mojom::CredentialsMode credentials_mode,
network::mojom::ReferrerPolicy referrer_policy,
mojom::FetchImportanceMode importance,
+ RenderBlockingBehavior render_blocking_behavior,
RejectCoepUnsafeNone reject_coep_unsafe_none =
RejectCoepUnsafeNone(false))
: nonce_(nonce),
@@ -56,6 +58,7 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
credentials_mode_(credentials_mode),
referrer_policy_(referrer_policy),
importance_(importance),
+ render_blocking_behavior_(render_blocking_behavior),
reject_coep_unsafe_none_(reject_coep_unsafe_none) {}
~ScriptFetchOptions() = default;
@@ -111,6 +114,8 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
// "importance" member to the script fetch options struct.
const mojom::FetchImportanceMode importance_;
+ const RenderBlockingBehavior render_blocking_behavior_ =
+ RenderBlockingBehavior::kUnset;
// True when we should reject a response with COEP: none.
// https://wicg.github.io/cross-origin-embedder-policy/#integration-html
// This is for dedicated workers.
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
index 2d1bb0e5f9b..2a3447539ff 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
@@ -11,7 +11,7 @@ namespace blink {
StaleRevalidationResourceClient::StaleRevalidationResourceClient(
Resource* stale_resource)
- : start_time_(base::TimeTicks::Now()), stale_resource_(stale_resource) {}
+ : stale_resource_(stale_resource) {}
StaleRevalidationResourceClient::~StaleRevalidationResourceClient() = default;
@@ -20,13 +20,6 @@ void StaleRevalidationResourceClient::NotifyFinished(Resource* resource) {
if (stale_resource_ && IsMainThread())
GetMemoryCache()->Remove(stale_resource_);
ClearResource();
-
- base::TimeTicks response_end = resource->LoadResponseEnd();
- if (!response_end.is_null()) {
- UMA_HISTOGRAM_LONG_TIMES(
- "Blink.ResourceFetcher.StaleWhileRevalidateDuration",
- response_end - start_time_);
- }
}
void StaleRevalidationResourceClient::Trace(Visitor* visitor) const {
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
index 889f68ba8c1..036b13a7bab 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
@@ -26,7 +26,6 @@ class StaleRevalidationResourceClient
String DebugName() const override;
private:
- base::TimeTicks start_time_;
// |stale_resource_| is the original resource that will be removed from the
// MemoryCache when this revalidation request is completed. Note that it is
// different than the active resource for this resource client which accessed
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/subresource_web_bundle.h b/chromium/third_party/blink/renderer/platform/loader/fetch/subresource_web_bundle.h
index 2971478b1b4..e44eaffab65 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/subresource_web_bundle.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/subresource_web_bundle.h
@@ -10,20 +10,24 @@
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+namespace base {
+class UnguessableToken;
+}
+
namespace blink {
class KURL;
-// SubresourceWebBundle is attached to ResourceFetcher and used to intercept
-// subresource requests for a certain set of URLs and serve responses from a
+// SubresourceWebBundle is attached to ResourceFetcher and used to set
+// WebBundleToken to subresource requests which should be served from a
// WebBundle. This is used for Subresource loading with Web Bundles
// (https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md).
class PLATFORM_EXPORT SubresourceWebBundle : public GarbageCollectedMixin {
public:
void Trace(Visitor* visitor) const override {}
virtual bool CanHandleRequest(const KURL& url) const = 0;
- virtual mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
- GetURLLoaderFactory() = 0;
+ virtual const KURL& GetBundleUrl() const = 0;
+ virtual const base::UnguessableToken& WebBundleToken() const = 0;
virtual String GetCacheIdentifier() const = 0;
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS
index cb1e4f6caaa..d1edc9d3dec 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/DEPS
@@ -1,14 +1,31 @@
+include_rules = [
+ "+base/atomic_sequence_num.h",
+ "+net/base/registry_controlled_domains/registry_controlled_domain.h",
+ "+net/base/request_priority.h",
+ "+net/base/host_port_pair.h",
+ "+net/cert/cert_status_flags.h",
+ "+net/cert/ct_sct_to_string.h",
+ "+net/cert/x509_certificate.h",
+ "+net/cert/x509_util.h",
+ "+net/ssl/ssl_cipher_suite_names.h",
+ "+net/ssl/ssl_connection_status_flags.h",
+ "+net/ssl/ssl_info.h",
+ "+net/traffic_annotation/network_traffic_annotation.h",
+ "+net/url_request/referrer_policy.h",
+ "+services/network/public/mojom/url_loader.mojom.h",
+ "+services/network/public/mojom/url_response_head.mojom.h",
+ "+third_party/blink/public/mojom/loader/code_cache.mojom-shared.h"
+]
+
specific_include_rules = {
"request_conversion.cc" : [
"+media/media_buildflags.h"
],
- "web_bundle_subresource_loader.cc" : [
- "+components/web_package",
- "+net/http/http_status_code.h",
+ "sync_load_context_unittest.cc": [
+ "+base/threading/thread.h",
+ "+services/network/test/test_url_loader_factory.h"
],
- "web_bundle_subresource_loader_test.cc" : [
- "+components/web_package",
- "+net/traffic_annotation/network_traffic_annotation_test_helper.h",
- "+services/network/test/test_url_loader_client.h",
+ "web_url_loader_unittest.cc": [
+ "+net/test/cert_test_util.h"
],
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc
new file mode 100644
index 00000000000..18ae7873f82
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.cc
@@ -0,0 +1,594 @@
+// Copyright 2016 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 "third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h"
+
+#include <iterator>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
+#include "mojo/public/cpp/system/data_pipe_drainer.h"
+#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_resource_request_sender.h"
+#include "third_party/blink/renderer/platform/back_forward_cache_utils.h"
+#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+namespace {
+
+constexpr size_t kDefaultMaxBufferedBodyBytesPerRequest = 100 * 1000;
+constexpr base::TimeDelta kGracePeriodToFinishLoadingWhileInBackForwardCache =
+ base::TimeDelta::FromSeconds(15);
+
+} // namespace
+
+class MojoURLLoaderClient::DeferredMessage {
+ public:
+ DeferredMessage() = default;
+ virtual void HandleMessage(
+ WebResourceRequestSender* resource_request_sender) = 0;
+ virtual bool IsCompletionMessage() const = 0;
+ virtual ~DeferredMessage() = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DeferredMessage);
+};
+
+class MojoURLLoaderClient::DeferredOnReceiveResponse final
+ : public DeferredMessage {
+ public:
+ explicit DeferredOnReceiveResponse(
+ network::mojom::URLResponseHeadPtr response_head)
+ : response_head_(std::move(response_head)) {}
+
+ void HandleMessage(
+ WebResourceRequestSender* resource_request_sender) override {
+ resource_request_sender->OnReceivedResponse(std::move(response_head_));
+ }
+ bool IsCompletionMessage() const override { return false; }
+
+ private:
+ network::mojom::URLResponseHeadPtr response_head_;
+};
+
+class MojoURLLoaderClient::DeferredOnReceiveRedirect final
+ : public DeferredMessage {
+ public:
+ DeferredOnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr response_head,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : redirect_info_(redirect_info),
+ response_head_(std::move(response_head)),
+ task_runner_(std::move(task_runner)) {}
+
+ void HandleMessage(
+ WebResourceRequestSender* resource_request_sender) override {
+ resource_request_sender->OnReceivedRedirect(
+ redirect_info_, std::move(response_head_), task_runner_);
+ }
+ bool IsCompletionMessage() const override { return false; }
+
+ private:
+ const net::RedirectInfo redirect_info_;
+ network::mojom::URLResponseHeadPtr response_head_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+class MojoURLLoaderClient::DeferredOnUploadProgress final
+ : public DeferredMessage {
+ public:
+ DeferredOnUploadProgress(int64_t current, int64_t total)
+ : current_(current), total_(total) {}
+
+ void HandleMessage(
+ WebResourceRequestSender* resource_request_sender) override {
+ resource_request_sender->OnUploadProgress(current_, total_);
+ }
+ bool IsCompletionMessage() const override { return false; }
+
+ private:
+ const int64_t current_;
+ const int64_t total_;
+};
+
+class MojoURLLoaderClient::DeferredOnReceiveCachedMetadata final
+ : public DeferredMessage {
+ public:
+ explicit DeferredOnReceiveCachedMetadata(mojo_base::BigBuffer data)
+ : data_(std::move(data)) {}
+
+ void HandleMessage(
+ WebResourceRequestSender* resource_request_sender) override {
+ resource_request_sender->OnReceivedCachedMetadata(std::move(data_));
+ }
+ bool IsCompletionMessage() const override { return false; }
+
+ private:
+ mojo_base::BigBuffer data_;
+};
+
+class MojoURLLoaderClient::DeferredOnStartLoadingResponseBody final
+ : public DeferredMessage {
+ public:
+ explicit DeferredOnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body)
+ : body_(std::move(body)) {}
+
+ void HandleMessage(
+ WebResourceRequestSender* resource_request_sender) override {
+ resource_request_sender->OnStartLoadingResponseBody(std::move(body_));
+ }
+ bool IsCompletionMessage() const override { return false; }
+
+ private:
+ mojo::ScopedDataPipeConsumerHandle body_;
+};
+
+class MojoURLLoaderClient::DeferredOnComplete final : public DeferredMessage {
+ public:
+ explicit DeferredOnComplete(const network::URLLoaderCompletionStatus& status)
+ : status_(status) {}
+
+ void HandleMessage(
+ WebResourceRequestSender* resource_request_sender) override {
+ resource_request_sender->OnRequestComplete(status_);
+ }
+ bool IsCompletionMessage() const override { return true; }
+
+ private:
+ const network::URLLoaderCompletionStatus status_;
+};
+
+class MojoURLLoaderClient::BodyBuffer final
+ : public mojo::DataPipeDrainer::Client {
+ public:
+ BodyBuffer(MojoURLLoaderClient* owner,
+ mojo::ScopedDataPipeConsumerHandle readable,
+ mojo::ScopedDataPipeProducerHandle writable,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : owner_(owner),
+ writable_(std::move(writable)),
+ writable_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+ std::move(task_runner)),
+ max_bytes_drained_(GetLoadingTasksUnfreezableParamAsInt(
+ "max_buffered_bytes",
+ kDefaultMaxBufferedBodyBytesPerRequest)) {
+ pipe_drainer_ =
+ std::make_unique<mojo::DataPipeDrainer>(this, std::move(readable));
+ writable_watcher_.Watch(
+ writable_.get(),
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ base::BindRepeating(&BodyBuffer::WriteBufferedBody,
+ base::Unretained(this)));
+ }
+
+ bool active() const { return writable_watcher_.IsWatching(); }
+
+ // mojo::DataPipeDrainer::Client
+ void OnDataAvailable(const void* data, size_t num_bytes) override {
+ DCHECK(draining_);
+ SCOPED_CRASH_KEY_NUMBER("OnDataAvailable", "buffered_body_size",
+ buffered_body_.size());
+ SCOPED_CRASH_KEY_NUMBER("OnDataAvailable", "data_bytes", num_bytes);
+ SCOPED_CRASH_KEY_STRING256("OnDataAvailable", "last_loaded_url",
+ owner_->last_loaded_url().GetString().Utf8());
+
+ total_bytes_drained_ += num_bytes;
+ TRACE_EVENT2("loading", "MojoURLLoaderClient::BodyBuffer::OnDataAvailable",
+ "total_bytes_drained", static_cast<int>(total_bytes_drained_),
+ "added_bytes", static_cast<int>(num_bytes));
+
+ if (owner_->IsDeferredWithBackForwardCache()) {
+ owner_->DidBufferLoadWhileInBackForwardCache(num_bytes);
+ if (total_bytes_drained_ > max_bytes_drained_ ||
+ !owner_->CanContinueBufferingWhileInBackForwardCache()) {
+ owner_->EvictFromBackForwardCache(
+ blink::mojom::RendererEvictionReason::kNetworkExceedsBufferLimit);
+ return;
+ }
+ }
+ buffered_body_.emplace(static_cast<const char*>(data),
+ static_cast<const char*>(data) + num_bytes);
+ WriteBufferedBody(MOJO_RESULT_OK);
+ }
+
+ void OnDataComplete() override {
+ DCHECK(draining_);
+ draining_ = false;
+ WriteBufferedBody(MOJO_RESULT_OK);
+ }
+
+ private:
+ void WriteBufferedBody(MojoResult) {
+ // Try to write all the remaining chunks in |buffered_body_|.
+ while (!buffered_body_.empty()) {
+ // Write the chunk at the front of |buffered_body_|.
+ const std::vector<char>& current_chunk = buffered_body_.front();
+ DCHECK_LE(offset_in_current_chunk_, current_chunk.size());
+ uint32_t bytes_sent = base::saturated_cast<uint32_t>(
+ current_chunk.size() - offset_in_current_chunk_);
+ MojoResult result =
+ writable_->WriteData(current_chunk.data() + offset_in_current_chunk_,
+ &bytes_sent, MOJO_WRITE_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // The pipe is closed unexpectedly, finish writing now.
+ draining_ = false;
+ Finish();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ writable_watcher_.ArmOrNotify();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+ // We've sent |bytes_sent| bytes, update the current offset in the
+ // frontmost chunk.
+ offset_in_current_chunk_ += bytes_sent;
+ DCHECK_LE(offset_in_current_chunk_, current_chunk.size());
+ if (offset_in_current_chunk_ == current_chunk.size()) {
+ // We've finished writing the chunk at the front of the queue, pop it so
+ // that we'll write the next chunk next time.
+ buffered_body_.pop();
+ offset_in_current_chunk_ = 0;
+ }
+ }
+ // We're finished if we've drained the original pipe and sent all the
+ // buffered body.
+ if (!draining_)
+ Finish();
+ }
+
+ void Finish() {
+ DCHECK(!draining_);
+ // We've read and written all the data from the original pipe.
+ writable_watcher_.Cancel();
+ writable_.reset();
+ // There might be a deferred OnComplete message waiting for us to finish
+ // draining the response body, so flush the deferred messages in
+ // the owner MojoURLLoaderClient.
+ owner_->FlushDeferredMessages();
+ }
+
+ MojoURLLoaderClient* const owner_;
+ mojo::ScopedDataPipeProducerHandle writable_;
+ mojo::SimpleWatcher writable_watcher_;
+ std::unique_ptr<mojo::DataPipeDrainer> pipe_drainer_;
+ // We save the received response body as a queue of chunks so that we can free
+ // memory as soon as we finish sending a chunk completely.
+ base::queue<std::vector<char>> buffered_body_;
+ uint32_t offset_in_current_chunk_ = 0;
+ size_t total_bytes_drained_ = 0;
+ const size_t max_bytes_drained_;
+ bool draining_ = true;
+};
+
+MojoURLLoaderClient::MojoURLLoaderClient(
+ WebResourceRequestSender* resource_request_sender,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ bool bypass_redirect_checks,
+ const GURL& request_url,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
+ : back_forward_cache_timeout_(
+ base::TimeDelta::FromSeconds(GetLoadingTasksUnfreezableParamAsInt(
+ "grace_period_to_finish_loading_in_seconds",
+ static_cast<int>(
+ kGracePeriodToFinishLoadingWhileInBackForwardCache
+ .InSeconds())))),
+ resource_request_sender_(resource_request_sender),
+ task_runner_(std::move(task_runner)),
+ bypass_redirect_checks_(bypass_redirect_checks),
+ last_loaded_url_(request_url),
+ back_forward_cache_loader_helper_(back_forward_cache_loader_helper) {}
+
+MojoURLLoaderClient::~MojoURLLoaderClient() = default;
+
+void MojoURLLoaderClient::SetDefersLoading(WebURLLoader::DeferType value) {
+ deferred_state_ = value;
+ if (value == WebURLLoader::DeferType::kNotDeferred) {
+ StopBackForwardCacheEvictionTimer();
+ task_runner_->PostTask(
+ FROM_HERE, WTF::Bind(&MojoURLLoaderClient::FlushDeferredMessages,
+ weak_factory_.GetWeakPtr()));
+ } else if (IsDeferredWithBackForwardCache() && !has_received_complete_ &&
+ !back_forward_cache_eviction_timer_.IsRunning()) {
+ // We should evict the page associated with this load if the connection
+ // takes too long until it either finished or failed.
+ back_forward_cache_eviction_timer_.SetTaskRunner(task_runner_);
+ back_forward_cache_eviction_timer_.Start(
+ FROM_HERE, back_forward_cache_timeout_,
+ WTF::Bind(&MojoURLLoaderClient::EvictFromBackForwardCacheDueToTimeout,
+ weak_factory_.GetWeakPtr()));
+ }
+}
+
+void MojoURLLoaderClient::OnReceiveResponse(
+ network::mojom::URLResponseHeadPtr response_head) {
+ TRACE_EVENT1("loading", "MojoURLLoaderClient::OnReceiveResponse", "url",
+ last_loaded_url_.GetString().Utf8());
+
+ has_received_response_head_ = true;
+ on_receive_response_time_ = base::TimeTicks::Now();
+
+ if (NeedsStoringMessage()) {
+ StoreAndDispatch(
+ std::make_unique<DeferredOnReceiveResponse>(std::move(response_head)));
+ } else {
+ resource_request_sender_->OnReceivedResponse(std::move(response_head));
+ }
+}
+
+BackForwardCacheLoaderHelper*
+MojoURLLoaderClient::GetBackForwardCacheLoaderHelper() {
+ return back_forward_cache_loader_helper_.GetBackForwardCacheLoaderHelper();
+}
+
+void MojoURLLoaderClient::EvictFromBackForwardCache(
+ blink::mojom::RendererEvictionReason reason) {
+ StopBackForwardCacheEvictionTimer();
+ auto* back_forward_cache_loader_helper = GetBackForwardCacheLoaderHelper();
+ if (!back_forward_cache_loader_helper)
+ return;
+ back_forward_cache_loader_helper->EvictFromBackForwardCache(reason);
+}
+
+void MojoURLLoaderClient::DidBufferLoadWhileInBackForwardCache(
+ size_t num_bytes) {
+ auto* back_forward_cache_loader_helper = GetBackForwardCacheLoaderHelper();
+ if (!back_forward_cache_loader_helper)
+ return;
+ back_forward_cache_loader_helper->DidBufferLoadWhileInBackForwardCache(
+ num_bytes);
+}
+
+bool MojoURLLoaderClient::CanContinueBufferingWhileInBackForwardCache() {
+ auto* back_forward_cache_loader_helper = GetBackForwardCacheLoaderHelper();
+ if (!back_forward_cache_loader_helper)
+ return false;
+ return back_forward_cache_loader_helper
+ ->CanContinueBufferingWhileInBackForwardCache();
+}
+
+void MojoURLLoaderClient::EvictFromBackForwardCacheDueToTimeout() {
+ EvictFromBackForwardCache(
+ blink::mojom::RendererEvictionReason::kNetworkRequestTimeout);
+}
+
+void MojoURLLoaderClient::StopBackForwardCacheEvictionTimer() {
+ back_forward_cache_eviction_timer_.Stop();
+}
+
+void MojoURLLoaderClient::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr response_head) {
+ DCHECK(!has_received_response_head_);
+ if (deferred_state_ ==
+ blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache) {
+ EvictFromBackForwardCache(
+ blink::mojom::RendererEvictionReason::kNetworkRequestRedirected);
+
+ OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ return;
+ }
+ if (!bypass_redirect_checks_ &&
+ !Platform::Current()->IsRedirectSafe(last_loaded_url_,
+ redirect_info.new_url)) {
+ OnComplete(network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT));
+ return;
+ }
+
+ last_loaded_url_ = KURL(redirect_info.new_url);
+ if (NeedsStoringMessage()) {
+ StoreAndDispatch(std::make_unique<DeferredOnReceiveRedirect>(
+ redirect_info, std::move(response_head), task_runner_));
+ } else {
+ resource_request_sender_->OnReceivedRedirect(
+ redirect_info, std::move(response_head), task_runner_);
+ }
+}
+
+void MojoURLLoaderClient::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) {
+ if (NeedsStoringMessage()) {
+ StoreAndDispatch(std::make_unique<DeferredOnUploadProgress>(
+ current_position, total_size));
+ } else {
+ resource_request_sender_->OnUploadProgress(current_position, total_size);
+ }
+ std::move(ack_callback).Run();
+}
+
+void MojoURLLoaderClient::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
+ if (NeedsStoringMessage()) {
+ StoreAndDispatch(
+ std::make_unique<DeferredOnReceiveCachedMetadata>(std::move(data)));
+ } else {
+ resource_request_sender_->OnReceivedCachedMetadata(std::move(data));
+ }
+}
+
+void MojoURLLoaderClient::OnTransferSizeUpdated(int32_t transfer_size_diff) {
+ if (NeedsStoringMessage()) {
+ accumulated_transfer_size_diff_during_deferred_ += transfer_size_diff;
+ } else {
+ resource_request_sender_->OnTransferSizeUpdated(transfer_size_diff);
+ }
+}
+
+void MojoURLLoaderClient::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ TRACE_EVENT1("loading", "MojoURLLoaderClient::OnStartLoadingResponseBody",
+ "url", last_loaded_url_.GetString().Utf8());
+
+ DCHECK(has_received_response_head_);
+ DCHECK(!has_received_response_body_);
+ has_received_response_body_ = true;
+
+ if (!on_receive_response_time_.is_null()) {
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.OnReceiveResponseToOnStartLoadingResponseBody",
+ base::TimeTicks::Now() - on_receive_response_time_);
+ }
+
+ if (!NeedsStoringMessage()) {
+ // Send the message immediately.
+ resource_request_sender_->OnStartLoadingResponseBody(std::move(body));
+ return;
+ }
+
+ if (deferred_state_ !=
+ blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache) {
+ // Defer the message, storing the original body pipe.
+ StoreAndDispatch(
+ std::make_unique<DeferredOnStartLoadingResponseBody>(std::move(body)));
+ return;
+ }
+
+ DCHECK(IsInflightNetworkRequestBackForwardCacheSupportEnabled());
+ // We want to run loading tasks while deferred (but without dispatching the
+ // messages). Drain the original pipe containing the response body into a
+ // new pipe so that we won't block the network service if we're deferred for
+ // a long time.
+ mojo::ScopedDataPipeProducerHandle new_body_producer;
+ mojo::ScopedDataPipeConsumerHandle new_body_consumer;
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, new_body_producer, new_body_consumer);
+ if (result != MOJO_RESULT_OK) {
+ OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
+ return;
+ }
+ body_buffer_ = std::make_unique<BodyBuffer>(
+ this, std::move(body), std::move(new_body_producer), task_runner_);
+
+ StoreAndDispatch(std::make_unique<DeferredOnStartLoadingResponseBody>(
+ std::move(new_body_consumer)));
+}
+
+void MojoURLLoaderClient::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ has_received_complete_ = true;
+ StopBackForwardCacheEvictionTimer();
+
+ // Dispatch completion status to the WebResourceRequestSender.
+ // Except for errors, there must always be a response's body.
+ DCHECK(has_received_response_body_ || status.error_code != net::OK);
+ if (NeedsStoringMessage()) {
+ StoreAndDispatch(std::make_unique<DeferredOnComplete>(status));
+ } else {
+ resource_request_sender_->OnRequestComplete(status);
+ }
+}
+
+bool MojoURLLoaderClient::NeedsStoringMessage() const {
+ return deferred_state_ != WebURLLoader::DeferType::kNotDeferred ||
+ deferred_messages_.size() > 0 ||
+ accumulated_transfer_size_diff_during_deferred_ > 0;
+}
+
+void MojoURLLoaderClient::StoreAndDispatch(
+ std::unique_ptr<DeferredMessage> message) {
+ DCHECK(NeedsStoringMessage());
+ if (deferred_state_ != WebURLLoader::DeferType::kNotDeferred) {
+ deferred_messages_.emplace_back(std::move(message));
+ } else if (deferred_messages_.size() > 0 ||
+ accumulated_transfer_size_diff_during_deferred_ > 0) {
+ deferred_messages_.emplace_back(std::move(message));
+ FlushDeferredMessages();
+ } else {
+ NOTREACHED();
+ }
+}
+
+void MojoURLLoaderClient::OnConnectionClosed() {
+ // If the connection aborts before the load completes, mark it as aborted.
+ if (!has_received_complete_) {
+ OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ return;
+ }
+}
+
+void MojoURLLoaderClient::FlushDeferredMessages() {
+ if (deferred_state_ != WebURLLoader::DeferType::kNotDeferred)
+ return;
+ WebVector<std::unique_ptr<DeferredMessage>> messages;
+ messages.Swap(deferred_messages_);
+ bool has_completion_message = false;
+ base::WeakPtr<MojoURLLoaderClient> weak_this = weak_factory_.GetWeakPtr();
+ // First, dispatch all messages excluding the followings:
+ // - transfer size change
+ // - completion
+ // These two types of messages are dispatched later.
+ for (size_t index = 0; index < messages.size(); ++index) {
+ if (messages[index]->IsCompletionMessage()) {
+ // The completion message arrives at the end of the message queue.
+ DCHECK(!has_completion_message);
+ DCHECK_EQ(index, messages.size() - 1);
+ has_completion_message = true;
+ break;
+ }
+
+ messages[index]->HandleMessage(resource_request_sender_);
+ if (!weak_this)
+ return;
+ if (deferred_state_ != WebURLLoader::DeferType::kNotDeferred) {
+ deferred_messages_.reserve(messages.size() - index - 1);
+ for (size_t i = index + 1; i < messages.size(); ++i)
+ deferred_messages_.emplace_back(std::move(messages[i]));
+ return;
+ }
+ }
+
+ // Dispatch the transfer size update.
+ if (accumulated_transfer_size_diff_during_deferred_ > 0) {
+ auto transfer_size_diff = accumulated_transfer_size_diff_during_deferred_;
+ accumulated_transfer_size_diff_during_deferred_ = 0;
+ resource_request_sender_->OnTransferSizeUpdated(transfer_size_diff);
+ if (!weak_this)
+ return;
+ if (deferred_state_ != WebURLLoader::DeferType::kNotDeferred) {
+ if (has_completion_message) {
+ DCHECK_GT(messages.size(), 0u);
+ DCHECK(messages.back()->IsCompletionMessage());
+ deferred_messages_.emplace_back(std::move(messages.back()));
+ }
+ return;
+ }
+ }
+
+ // Dispatch the completion message.
+ if (has_completion_message) {
+ DCHECK_GT(messages.size(), 0u);
+ DCHECK(messages.back()->IsCompletionMessage());
+ if (body_buffer_ && body_buffer_->active()) {
+ // If we still have an active body buffer, it means we haven't drained all
+ // of the contents of the response body yet. We shouldn't dispatch the
+ // completion message now, so
+ // put the message back into |deferred_messages_| to be sent later after
+ // the body buffer is no longer active.
+ deferred_messages_.emplace_back(std::move(messages.back()));
+ return;
+ }
+ messages.back()->HandleMessage(resource_request_sender_);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h
new file mode 100644
index 00000000000..d2386cda8c2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h
@@ -0,0 +1,128 @@
+// Copyright 2016 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_MOJO_URL_LOADER_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_MOJO_URL_LOADER_CLIENT_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-forward.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_url_loader.h"
+#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace net {
+struct RedirectInfo;
+} // namespace net
+
+namespace network {
+struct URLLoaderCompletionStatus;
+} // namespace network
+
+namespace blink {
+class BackForwardCacheLoaderHelper;
+class WebResourceRequestSender;
+
+// MojoURLLoaderClient is an implementation of
+// network::mojom::URLLoaderClient to receive messages from a single URLLoader.
+class BLINK_PLATFORM_EXPORT MojoURLLoaderClient final
+ : public network::mojom::URLLoaderClient {
+ public:
+ MojoURLLoaderClient(
+ WebResourceRequestSender* resource_request_sender,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ bool bypass_redirect_checks,
+ const GURL& request_url,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper);
+ ~MojoURLLoaderClient() override;
+
+ // Set the defer status. If loading is deferred, received messages are not
+ // dispatched to clients until it is set not deferred.
+ void SetDefersLoading(WebURLLoader::DeferType value);
+
+ // network::mojom::URLLoaderClient implementation
+ void OnReceiveResponse(
+ network::mojom::URLResponseHeadPtr response_head) override;
+ void OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr response_head) override;
+ void OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override;
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+
+ void EvictFromBackForwardCache(blink::mojom::RendererEvictionReason reason);
+ void DidBufferLoadWhileInBackForwardCache(size_t num_bytes);
+ bool CanContinueBufferingWhileInBackForwardCache();
+ bool IsDeferredWithBackForwardCache() {
+ return deferred_state_ ==
+ blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache;
+ }
+
+ private:
+ class BodyBuffer;
+ class DeferredMessage;
+ class DeferredOnReceiveResponse;
+ class DeferredOnReceiveRedirect;
+ class DeferredOnUploadProgress;
+ class DeferredOnReceiveCachedMetadata;
+ class DeferredOnStartLoadingResponseBody;
+ class DeferredOnComplete;
+
+ bool NeedsStoringMessage() const;
+ void StoreAndDispatch(std::unique_ptr<DeferredMessage> message);
+ void OnConnectionClosed();
+ const KURL& last_loaded_url() const { return last_loaded_url_; }
+
+ // Dispatches the messages received after SetDefersLoading is called.
+ void FlushDeferredMessages();
+
+ void EvictFromBackForwardCacheDueToTimeout();
+ void StopBackForwardCacheEvictionTimer();
+ BackForwardCacheLoaderHelper* GetBackForwardCacheLoaderHelper();
+
+ WebVector<std::unique_ptr<DeferredMessage>> deferred_messages_;
+ std::unique_ptr<BodyBuffer> body_buffer_;
+ base::OneShotTimer back_forward_cache_eviction_timer_;
+ base::TimeDelta back_forward_cache_timeout_;
+ bool has_received_response_head_ = false;
+ bool has_received_response_body_ = false;
+ bool has_received_complete_ = false;
+ WebURLLoader::DeferType deferred_state_ =
+ WebURLLoader::DeferType::kNotDeferred;
+ int32_t accumulated_transfer_size_diff_during_deferred_ = 0;
+ WebResourceRequestSender* const resource_request_sender_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ bool bypass_redirect_checks_ = false;
+ KURL last_loaded_url_;
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper_;
+
+ // For UMA.
+ base::TimeTicks on_receive_response_time_;
+
+ base::WeakPtrFactory<MojoURLLoaderClient> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_MOJO_URL_LOADER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc
new file mode 100644
index 00000000000..caad3c87d67
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc
@@ -0,0 +1,898 @@
+// Copyright 2016 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 "third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h"
+
+#include <vector>
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/loader/throttling_url_loader.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_resource_request_sender.h"
+#include "third_party/blink/public/platform/web_runtime_features.h"
+#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+
+namespace blink {
+
+namespace {
+
+constexpr size_t kDataPipeCapacity = 4096;
+
+class MockWebResourceRequestSender : public WebResourceRequestSender {
+ public:
+ struct Context;
+ MockWebResourceRequestSender() : context_(new Context()) {}
+ ~MockWebResourceRequestSender() override = default;
+
+ void OnUploadProgress(int64_t position, int64_t size) override {
+ EXPECT_FALSE(context_->complete);
+ }
+
+ void OnReceivedRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
+ EXPECT_FALSE(context_->cancelled);
+ EXPECT_FALSE(context_->complete);
+ ++context_->seen_redirects;
+ context_->last_load_timing = head->load_timing;
+ if (context_->defer_on_redirect) {
+ context_->url_laoder_client->SetDefersLoading(
+ blink::WebURLLoader::DeferType::kDeferred);
+ }
+ }
+
+ void OnReceivedResponse(network::mojom::URLResponseHeadPtr head) override {
+ EXPECT_FALSE(context_->cancelled);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ context_->received_response = true;
+ context_->last_load_timing = head->load_timing;
+ if (context_->cancel_on_receive_response)
+ context_->cancelled = true;
+ }
+
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override {
+ if (context_->cancelled)
+ return;
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ context_->body_handle = std::move(body);
+ }
+
+ void OnTransferSizeUpdated(int transfer_size_diff) override {
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ if (context_->cancelled)
+ return;
+ context_->total_encoded_data_length += transfer_size_diff;
+ if (context_->defer_on_transfer_size_updated) {
+ context_->url_laoder_client->SetDefersLoading(
+ blink::WebURLLoader::DeferType::kDeferred);
+ }
+ }
+
+ void OnReceivedCachedMetadata(mojo_base::BigBuffer data) override {
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ if (context_->cancelled)
+ return;
+ context_->cached_metadata = std::move(data);
+ }
+
+ void OnRequestComplete(
+ const network::URLLoaderCompletionStatus& status) override {
+ if (context_->cancelled)
+ return;
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ context_->complete = true;
+ context_->completion_status = status;
+ }
+
+ Context* context() { return context_.get(); }
+
+ struct Context final {
+ Context() = default;
+ ~Context() = default;
+ Context(const Context&) = delete;
+ Context& operator=(const Context&) = delete;
+
+ // True if should follow redirects, false if should cancel them.
+ bool follow_redirects = true;
+ // True if the request should be deferred on redirects.
+ bool defer_on_redirect = false;
+
+ // Number of total redirects seen.
+ int seen_redirects = 0;
+
+ bool cancel_on_receive_response = false;
+ bool cancel_on_receive_data = false;
+ bool received_response = false;
+
+ mojo_base::BigBuffer cached_metadata;
+ // Data received. If downloading to file, remains empty.
+ std::string data;
+
+ // Mojo's data pipe passed on OnStartLoadingResponseBody.
+ mojo::ScopedDataPipeConsumerHandle body_handle;
+
+ // Total encoded data length, regardless of whether downloading to a file or
+ // not.
+ int total_encoded_data_length = 0;
+ bool defer_on_transfer_size_updated = false;
+
+ bool complete = false;
+ bool cancelled = false;
+ int request_id = -1;
+
+ net::LoadTimingInfo last_load_timing;
+ network::URLLoaderCompletionStatus completion_status;
+ MojoURLLoaderClient* url_laoder_client;
+ };
+
+ private:
+ std::unique_ptr<Context> context_;
+};
+
+std::string ReadOneChunk(mojo::ScopedDataPipeConsumerHandle* handle) {
+ char buffer[kDataPipeCapacity];
+ uint32_t read_bytes = kDataPipeCapacity;
+ MojoResult result =
+ (*handle)->ReadData(buffer, &read_bytes, MOJO_READ_DATA_FLAG_NONE);
+ if (result != MOJO_RESULT_OK)
+ return "";
+ return std::string(buffer, read_bytes);
+}
+
+std::string GetRequestPeerContextBody(
+ MockWebResourceRequestSender::Context* context) {
+ if (context->body_handle) {
+ context->data += ReadOneChunk(&context->body_handle);
+ }
+ return context->data;
+}
+
+class TestBackForwardCacheLoaderHelper : public BackForwardCacheLoaderHelper {
+ public:
+ TestBackForwardCacheLoaderHelper() = default;
+
+ bool CanContinueBufferingWhileInBackForwardCache() const override {
+ return true;
+ }
+};
+
+} // namespace
+
+class WebMojoURLLoaderClientTest : public ::testing::Test,
+ public network::mojom::URLLoaderFactory,
+ public ::testing::WithParamInterface<bool> {
+ protected:
+ WebMojoURLLoaderClientTest()
+ : resource_request_sender_(new MockWebResourceRequestSender()) {
+ if (DeferWithBackForwardCacheEnabled()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ blink::features::kLoadingTasksUnfreezable);
+ }
+
+ WebRuntimeFeatures::EnableBackForwardCache(
+ DeferWithBackForwardCacheEnabled());
+
+ auto url_loader_factory =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(this);
+ auto request = std::make_unique<network::ResourceRequest>();
+ auto loading_task_runner =
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+
+ client_ = std::make_unique<MojoURLLoaderClient>(
+ resource_request_sender_.get(), loading_task_runner,
+ url_loader_factory->BypassRedirectChecks(), request->url,
+ WebBackForwardCacheLoaderHelper(
+ MakeGarbageCollected<TestBackForwardCacheLoaderHelper>()));
+ context_ = resource_request_sender_->context();
+ context_->url_laoder_client = client_.get();
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ std::move(url_loader_factory),
+ std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(),
+ /*routing_id=*/0, request_id_, /*loader_options=0*/ 0, request.get(),
+ client_.get(), TRAFFIC_ANNOTATION_FOR_TESTS,
+ std::move(loading_task_runner),
+ base::make_optional(std::vector<std::string>()));
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(url_loader_client_);
+ }
+
+ bool DeferWithBackForwardCacheEnabled() { return GetParam(); }
+
+ void TearDown() override { url_loader_client_.reset(); }
+
+ void CreateLoaderAndStart(
+ mojo::PendingReceiver<network::mojom::URLLoader> receiver,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
+ override {
+ url_loader_client_.Bind(std::move(client));
+ }
+
+ void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
+ override {
+ NOTREACHED();
+ }
+
+ static MojoCreateDataPipeOptions DataPipeOptions() {
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = kDataPipeCapacity;
+ return options;
+ }
+
+ class TestPlatform final : public TestingPlatformSupport {
+ public:
+ bool IsRedirectSafe(const GURL& from_url, const GURL& to_url) override {
+ return true;
+ }
+ };
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ ScopedTestingPlatformSupport<TestPlatform> platform_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+ std::unique_ptr<ThrottlingURLLoader> url_loader_;
+ std::unique_ptr<MojoURLLoaderClient> client_;
+ std::unique_ptr<MockWebResourceRequestSender> resource_request_sender_;
+ MockWebResourceRequestSender::Context* context_;
+ int request_id_ = 0;
+ mojo::Remote<network::mojom::URLLoaderClient> url_loader_client_;
+};
+
+TEST_P(WebMojoURLLoaderClientTest, OnReceiveResponse) {
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+
+ EXPECT_FALSE(context_->received_response);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+}
+
+TEST_P(WebMojoURLLoaderClientTest, ResponseBody) {
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+
+ EXPECT_FALSE(context_->received_response);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+ uint32_t size = 5;
+ MojoResult result =
+ data_pipe_producer->WriteData("hello", &size, MOJO_WRITE_DATA_FLAG_NONE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(5u, size);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+}
+
+TEST_P(WebMojoURLLoaderClientTest, OnReceiveRedirect) {
+ net::RedirectInfo redirect_info;
+
+ url_loader_client_->OnReceiveRedirect(redirect_info,
+ network::mojom::URLResponseHead::New());
+
+ EXPECT_EQ(0, context_->seen_redirects);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, context_->seen_redirects);
+}
+
+TEST_P(WebMojoURLLoaderClientTest, OnReceiveCachedMetadata) {
+ std::vector<uint8_t> data;
+ data.push_back('a');
+ mojo_base::BigBuffer metadata(data);
+
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ url_loader_client_->OnReceiveCachedMetadata(std::move(metadata));
+
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_EQ(0u, context_->cached_metadata.size());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ ASSERT_EQ(1u, context_->cached_metadata.size());
+ EXPECT_EQ('a', context_->cached_metadata.data()[0]);
+}
+
+TEST_P(WebMojoURLLoaderClientTest, OnTransferSizeUpdated) {
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ url_loader_client_->OnTransferSizeUpdated(4);
+ url_loader_client_->OnTransferSizeUpdated(4);
+
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_EQ(8, context_->total_encoded_data_length);
+}
+
+TEST_P(WebMojoURLLoaderClientTest, OnCompleteWithResponseBody) {
+ network::URLLoaderCompletionStatus status;
+
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+ uint32_t size = 5;
+ MojoResult result =
+ data_pipe_producer->WriteData("hello", &size, MOJO_WRITE_DATA_FLAG_NONE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(5u, size);
+ data_pipe_producer.reset();
+
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+
+ url_loader_client_->OnComplete(status);
+
+ EXPECT_FALSE(context_->complete);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+ EXPECT_TRUE(context_->complete);
+}
+
+// Due to the lack of ordering guarantee, it is possible that the response body
+// bytes arrives after the completion message. URLLoaderClientImpl should
+// restore the order.
+TEST_P(WebMojoURLLoaderClientTest, OnCompleteShouldBeTheLastMessage) {
+ network::URLLoaderCompletionStatus status;
+
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+ url_loader_client_->OnComplete(status);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_TRUE(context_->complete);
+
+ uint32_t size = 5;
+ MojoResult result =
+ data_pipe_producer->WriteData("hello", &size, MOJO_WRITE_DATA_FLAG_NONE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(5u, size);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+}
+
+TEST_P(WebMojoURLLoaderClientTest, CancelOnReceiveResponse) {
+ context_->cancel_on_receive_response = true;
+
+ network::URLLoaderCompletionStatus status;
+
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+ url_loader_client_->OnComplete(status);
+
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_FALSE(context_->cancelled);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_TRUE(context_->cancelled);
+}
+
+TEST_P(WebMojoURLLoaderClientTest, Defer) {
+ network::URLLoaderCompletionStatus status;
+
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ data_pipe_producer.reset(); // Empty body.
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+ url_loader_client_->OnComplete(status);
+
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_TRUE(context_->complete);
+}
+
+TEST_P(WebMojoURLLoaderClientTest, DeferWithResponseBody) {
+ network::URLLoaderCompletionStatus status;
+
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ std::string msg1 = "hello";
+ uint32_t size = msg1.size();
+ ASSERT_EQ(MOJO_RESULT_OK, data_pipe_producer->WriteData(
+ msg1.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(msg1.size(), size);
+ data_pipe_producer.reset();
+
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+ url_loader_client_->OnComplete(status);
+
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_TRUE(context_->complete);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+}
+
+TEST_P(WebMojoURLLoaderClientTest,
+ DeferredAndDeferredWithBackForwardCacheTransitions) {
+ if (!DeferWithBackForwardCacheEnabled())
+ return;
+ // Call OnReceiveResponse and OnStartLoadingResponseBody while
+ // deferred (not for back-forward cache).
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle));
+ url_loader_client_->OnStartLoadingResponseBody(std::move(consumer_handle));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Write data to the response body pipe.
+ std::string msg1 = "he";
+ uint32_t size = msg1.size();
+ ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
+ msg1.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(msg1.size(), size);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Defer for back-forward cache.
+ client_->SetDefersLoading(
+ blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ std::string msg2 = "ll";
+ size = msg2.size();
+ ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
+ msg2.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(msg2.size(), size);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Defer not for back-forward cache again.
+ client_->SetDefersLoading(
+ blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ std::string msg3 = "o";
+ size = msg3.size();
+ ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
+ msg3.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(msg3.size(), size);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Stop deferring.
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+
+ // Write more data to the pipe while not deferred.
+ std::string msg4 = "world";
+ size = msg4.size();
+ ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
+ msg4.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(msg4.size(), size);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("helloworld", GetRequestPeerContextBody(context_));
+}
+
+TEST_P(WebMojoURLLoaderClientTest,
+ DeferredWithBackForwardCacheStoppedDeferringBeforeClosing) {
+ if (!DeferWithBackForwardCacheEnabled())
+ return;
+ // Call OnReceiveResponse, OnStartLoadingResponseBody, OnComplete while
+ // deferred.
+ client_->SetDefersLoading(
+ blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle));
+ url_loader_client_->OnStartLoadingResponseBody(std::move(consumer_handle));
+ network::URLLoaderCompletionStatus status;
+ url_loader_client_->OnComplete(status);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Write data to the response body pipe, but don't close the connection yet.
+ std::string msg1 = "hello";
+ uint32_t size = msg1.size();
+ // We expect that the other end of the pipe to be ready to read the data
+ // immediately.
+ ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
+ msg1.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(msg1.size(), size);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Stop deferring. OnComplete message shouldn't be dispatched yet because
+ // we're still waiting for the response body pipe to be closed.
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ // When the body is buffered, we'll wait until the pipe is closed before
+ // sending the OnComplete message.
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+
+ // Write more data to the pipe while not deferred.
+ std::string msg2 = "world";
+ size = msg2.size();
+ ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
+ msg2.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(msg2.size(), size);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("helloworld", GetRequestPeerContextBody(context_));
+
+ // Close the response body pipe.
+ producer_handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_TRUE(context_->complete);
+ EXPECT_EQ("helloworld", GetRequestPeerContextBody(context_));
+}
+
+TEST_P(WebMojoURLLoaderClientTest, DeferBodyWithoutOnComplete) {
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ // Call OnStartLoadingResponseBody while deferred.
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle));
+ url_loader_client_->OnStartLoadingResponseBody(std::move(consumer_handle));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Write data to the response body pipe, but don't close the connection yet.
+ std::string msg1 = "hello";
+ uint32_t size = msg1.size();
+ // We expect that the other end of the pipe to be ready to read the data
+ // immediately.
+ ASSERT_EQ(MOJO_RESULT_OK, producer_handle->WriteData(
+ msg1.data(), &size, MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(msg1.size(), size);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Stop deferring.
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+
+ // Close the response body pipe.
+ producer_handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+}
+
+TEST_P(WebMojoURLLoaderClientTest,
+ DeferredWithBackForwardCacheLongResponseBody) {
+ if (!DeferWithBackForwardCacheEnabled())
+ return;
+ // Call OnReceiveResponse, OnStartLoadingResponseBody, OnComplete while
+ // deferred.
+ client_->SetDefersLoading(
+ blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache);
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle));
+ url_loader_client_->OnStartLoadingResponseBody(std::move(consumer_handle));
+ network::URLLoaderCompletionStatus status;
+ url_loader_client_->OnComplete(status);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+
+ // Write to the response body pipe. It will take several writes.
+ const uint32_t body_size = 70000;
+ uint32_t bytes_remaining = body_size;
+ std::string body(body_size, '*');
+ while (bytes_remaining > 0) {
+ uint32_t start_position = body_size - bytes_remaining;
+ uint32_t bytes_sent = bytes_remaining;
+ MojoResult result = producer_handle->WriteData(
+ body.c_str() + start_position, &bytes_sent, MOJO_WRITE_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ // When we buffer the body the pipe gets drained asynchronously, so it's
+ // possible to keep writing to the pipe if we wait.
+ base::RunLoop().RunUntilIdle();
+ continue;
+ }
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_GE(bytes_remaining, bytes_sent);
+ bytes_remaining -= bytes_sent;
+ }
+ // Ensure we've written all that we can write. When buffering is disabled, we
+ // can only write |body_size| - |bytes_remaining| bytes.
+ const uint32_t bytes_written = body_size - bytes_remaining;
+ EXPECT_EQ(body_size, bytes_written);
+ producer_handle.reset();
+
+ // Stop deferring.
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ // When the body is buffered, BodyBuffer shouldn't be finished writing to the
+ // new response body pipe at this point (because nobody is reading it).
+ EXPECT_FALSE(context_->complete);
+
+ // Calling GetRequestPeerContextBody to read data from the new response body
+ // pipe will make BodyBuffer write the rest of the body to the pipe.
+ uint32_t bytes_read = 0;
+ while (bytes_read < bytes_written) {
+ bytes_read = GetRequestPeerContextBody(context_).size();
+ base::RunLoop().RunUntilIdle();
+ }
+ // Ensure that we've read everything we've written.
+ EXPECT_EQ(bytes_written, bytes_read);
+ EXPECT_EQ(body, GetRequestPeerContextBody(context_));
+ EXPECT_TRUE(context_->complete);
+}
+
+// As "transfer size update" message is handled specially in the implementation,
+// we have a separate test.
+TEST_P(WebMojoURLLoaderClientTest, DeferWithTransferSizeUpdated) {
+ network::URLLoaderCompletionStatus status;
+
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ uint32_t size = 5;
+ MojoResult result =
+ data_pipe_producer->WriteData("hello", &size, MOJO_WRITE_DATA_FLAG_NONE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(5u, size);
+ data_pipe_producer.reset();
+
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+ url_loader_client_->OnTransferSizeUpdated(4);
+ url_loader_client_->OnComplete(status);
+
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_TRUE(context_->complete);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(4, context_->total_encoded_data_length);
+}
+
+TEST_P(WebMojoURLLoaderClientTest, SetDeferredDuringFlushingDeferredMessage) {
+ context_->defer_on_redirect = true;
+
+ net::RedirectInfo redirect_info;
+ network::URLLoaderCompletionStatus status;
+
+ url_loader_client_->OnReceiveRedirect(redirect_info,
+ network::mojom::URLResponseHead::New());
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ uint32_t size = 5;
+ MojoResult result =
+ data_pipe_producer->WriteData("hello", &size, MOJO_WRITE_DATA_FLAG_NONE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(5u, size);
+ data_pipe_producer.reset();
+
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+ url_loader_client_->OnTransferSizeUpdated(4);
+ url_loader_client_->OnComplete(status);
+
+ EXPECT_EQ(0, context_->seen_redirects);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, context_->seen_redirects);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ EXPECT_EQ(0, context_->seen_redirects);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, context_->seen_redirects);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ("", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+ EXPECT_FALSE(context_->cancelled);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, context_->seen_redirects);
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_TRUE(context_->complete);
+ EXPECT_EQ("hello", GetRequestPeerContextBody(context_));
+ EXPECT_EQ(4, context_->total_encoded_data_length);
+ EXPECT_FALSE(context_->cancelled);
+}
+
+TEST_P(WebMojoURLLoaderClientTest,
+ SetDeferredDuringFlushingDeferredMessageOnTransferSizeUpdated) {
+ context_->defer_on_transfer_size_updated = true;
+
+ network::URLLoaderCompletionStatus status;
+
+ url_loader_client_->OnReceiveResponse(network::mojom::URLResponseHead::New());
+ MojoCreateDataPipeOptions options = DataPipeOptions();
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, data_pipe_producer,
+ data_pipe_consumer));
+ data_pipe_producer.reset(); // Empty body.
+ url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe_consumer));
+
+ url_loader_client_->OnTransferSizeUpdated(4);
+ url_loader_client_->OnComplete(status);
+
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kDeferred);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ EXPECT_FALSE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ(0, context_->total_encoded_data_length);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ EXPECT_EQ(4, context_->total_encoded_data_length);
+ EXPECT_FALSE(context_->cancelled);
+
+ client_->SetDefersLoading(blink::WebURLLoader::DeferType::kNotDeferred);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_TRUE(context_->complete);
+ EXPECT_EQ(4, context_->total_encoded_data_length);
+ EXPECT_FALSE(context_->cancelled);
+}
+
+INSTANTIATE_TEST_SUITE_P(All, WebMojoURLLoaderClientTest, ::testing::Bool());
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
index fb258384b40..47dae6851d3 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
@@ -8,6 +8,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
+#include "net/base/load_flags.h"
#include "net/base/request_priority.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_util.h"
@@ -19,10 +20,10 @@
#include "services/network/public/mojom/data_pipe_getter.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
-#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
+#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -35,19 +36,13 @@
namespace blink {
-const char* ImageAcceptHeader() {
- static constexpr char kImageAcceptHeaderWithAvif[] =
- "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8";
- static constexpr size_t kOffset = sizeof("image/avif,") - 1;
#if BUILDFLAG(ENABLE_AV1_DECODER)
- static const char* header = base::FeatureList::IsEnabled(features::kAVIF)
- ? kImageAcceptHeaderWithAvif
- : kImageAcceptHeaderWithAvif + kOffset;
+constexpr char kImageAcceptHeader[] =
+ "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8";
#else
- static const char* header = kImageAcceptHeaderWithAvif + kOffset;
+constexpr char kImageAcceptHeader[] =
+ "image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8";
#endif
- return header;
-}
namespace {
@@ -153,6 +148,7 @@ mojom::ResourceType RequestContextToResourceType(
case mojom::blink::RequestContextType::DOWNLOAD:
case mojom::blink::RequestContextType::MANIFEST:
case mojom::blink::RequestContextType::SUBRESOURCE:
+ case mojom::blink::RequestContextType::SUBRESOURCE_WEBBUNDLE:
return mojom::ResourceType::kSubResource;
// TextTrack
@@ -216,26 +212,23 @@ void PopulateResourceRequestBody(const EncodedFormData& src,
break;
case FormDataElement::kEncodedBlob: {
DCHECK(element.optional_blob_data_handle_);
- mojo::Remote<mojom::Blob> blob_remote(mojo::PendingRemote<mojom::Blob>(
- element.optional_blob_data_handle_->CloneBlobRemote().PassPipe(),
- mojom::Blob::Version_));
- mojo::PendingRemote<network::mojom::DataPipeGetter>
+ mojo::Remote<mojom::blink::Blob> blob_remote(
+ element.optional_blob_data_handle_->CloneBlobRemote());
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
data_pipe_getter_remote;
blob_remote->AsDataPipeGetter(
data_pipe_getter_remote.InitWithNewPipeAndPassReceiver());
- dest->AppendDataPipe(std::move(data_pipe_getter_remote));
+ dest->AppendDataPipe(
+ ToCrossVariantMojoType(std::move(data_pipe_getter_remote)));
break;
}
case FormDataElement::kDataPipe: {
- // Convert network::mojom::blink::DataPipeGetter to
- // network::mojom::DataPipeGetter through a raw message pipe.
mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
pending_data_pipe_getter;
element.data_pipe_getter_->GetDataPipeGetter()->Clone(
pending_data_pipe_getter.InitWithNewPipeAndPassReceiver());
dest->AppendDataPipe(
- mojo::PendingRemote<network::mojom::DataPipeGetter>(
- pending_data_pipe_getter.PassPipe(), 0u));
+ ToCrossVariantMojoType(std::move(pending_data_pipe_getter)));
break;
}
}
@@ -244,6 +237,27 @@ void PopulateResourceRequestBody(const EncodedFormData& src,
} // namespace
+scoped_refptr<network::ResourceRequestBody> NetworkResourceRequestBodyFor(
+ ResourceRequestBody src_body,
+ bool allow_http1_for_streaming_upload) {
+ scoped_refptr<network::ResourceRequestBody> dest_body;
+ if (const EncodedFormData* form_body = src_body.FormBody().get()) {
+ dest_body = base::MakeRefCounted<network::ResourceRequestBody>();
+
+ PopulateResourceRequestBody(*form_body, dest_body.get());
+ } else if (src_body.StreamBody().is_valid()) {
+ mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>
+ stream_body = src_body.TakeStreamBody();
+ dest_body = base::MakeRefCounted<network::ResourceRequestBody>();
+ dest_body->SetToChunkedDataPipe(
+ ToCrossVariantMojoType(std::move(stream_body)),
+ network::ResourceRequestBody::ReadOnlyOnce(true));
+ dest_body->SetAllowHTTP1ForStreamingUpload(
+ allow_http1_for_streaming_upload);
+ }
+ return dest_body;
+}
+
void PopulateResourceRequest(const ResourceRequestHead& src,
ResourceRequestBody src_body,
network::ResourceRequest* dest) {
@@ -305,19 +319,24 @@ void PopulateResourceRequest(const ResourceRequestHead& src,
dest->credentials_mode = src.GetCredentialsMode();
dest->redirect_mode = src.GetRedirectMode();
dest->fetch_integrity = src.GetFetchIntegrity().Utf8();
-
- mojom::ResourceType resource_type =
- RequestContextToResourceType(src.GetRequestContext());
+ if (src.GetWebBundleTokenParams().has_value()) {
+ dest->web_bundle_token_params =
+ base::make_optional(network::ResourceRequest::WebBundleTokenParams(
+ src.GetWebBundleTokenParams()->bundle_url,
+ src.GetWebBundleTokenParams()->token,
+ src.GetWebBundleTokenParams()->CloneHandle()));
+ }
// TODO(kinuko): Deprecate this.
- dest->resource_type = static_cast<int>(resource_type);
+ dest->resource_type =
+ static_cast<int>(RequestContextToResourceType(src.GetRequestContext()));
- if (resource_type == mojom::ResourceType::kXhr &&
+ if (src.IsFetchLikeAPI() &&
(dest->url.has_username() || dest->url.has_password())) {
dest->do_not_prompt_for_login = true;
}
- if (resource_type == mojom::ResourceType::kPrefetch ||
- resource_type == mojom::ResourceType::kFavicon) {
+ if (src.GetRequestContext() == mojom::blink::RequestContextType::PREFETCH ||
+ src.IsFavicon()) {
dest->do_not_prompt_for_login = true;
}
@@ -351,32 +370,25 @@ void PopulateResourceRequest(const ResourceRequestHead& src,
dest->is_fetch_like_api = src.IsFetchLikeAPI();
- if (const EncodedFormData* body = src_body.FormBody().get()) {
- DCHECK_NE(dest->method, net::HttpRequestHeaders::kGetMethod);
- DCHECK_NE(dest->method, net::HttpRequestHeaders::kHeadMethod);
- dest->request_body = base::MakeRefCounted<network::ResourceRequestBody>();
+ dest->is_favicon = src.IsFavicon();
- PopulateResourceRequestBody(*body, dest->request_body.get());
- } else if (src_body.StreamBody().is_valid()) {
+ dest->request_body = NetworkResourceRequestBodyFor(
+ std::move(src_body), src.AllowHTTP1ForStreamingUpload());
+ if (dest->request_body) {
DCHECK_NE(dest->method, net::HttpRequestHeaders::kGetMethod);
DCHECK_NE(dest->method, net::HttpRequestHeaders::kHeadMethod);
- mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>
- stream_body = src_body.TakeStreamBody();
- dest->request_body = base::MakeRefCounted<network::ResourceRequestBody>();
- mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
- network_stream_body(stream_body.PassPipe(), 0u);
- dest->request_body->SetToReadOnceStream(std::move(network_stream_body));
- dest->request_body->SetAllowHTTP1ForStreamingUpload(
- src.AllowHTTP1ForStreamingUpload());
}
- if (resource_type == mojom::ResourceType::kStylesheet) {
+ network::mojom::RequestDestination request_destination =
+ src.GetRequestDestination();
+ if (request_destination == network::mojom::RequestDestination::kStyle ||
+ request_destination == network::mojom::RequestDestination::kXslt) {
dest->headers.SetHeader(net::HttpRequestHeaders::kAccept,
kStylesheetAcceptHeader);
- } else if (resource_type == mojom::ResourceType::kImage ||
- resource_type == mojom::ResourceType::kFavicon) {
+ } else if (request_destination ==
+ network::mojom::RequestDestination::kImage) {
dest->headers.SetHeaderIfMissing(net::HttpRequestHeaders::kAccept,
- ImageAcceptHeader());
+ kImageAcceptHeader);
} else {
// Calling SetHeaderIfMissing() instead of SetHeader() because JS can
// manually set an accept header on an XHR.
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h
index f80cd23c0f2..329b583e5be 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h
@@ -7,19 +7,25 @@
// This file consists of request conversion functions between blink and network.
+#include "base/memory/ref_counted.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace network {
+class ResourceRequestBody;
struct ResourceRequest;
} // namespace network
namespace blink {
-PLATFORM_EXPORT const char* ImageAcceptHeader();
+PLATFORM_EXPORT extern const char kImageAcceptHeader[];
class ResourceRequestHead;
class ResourceRequestBody;
+scoped_refptr<network::ResourceRequestBody> NetworkResourceRequestBodyFor(
+ const ResourceRequestBody src_body,
+ bool allow_http1_for_streaming_upload);
+
void PopulateResourceRequest(const ResourceRequestHead& src,
ResourceRequestBody src_body,
network::ResourceRequest* dest);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
new file mode 100644
index 00000000000..0cf43dcc510
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
@@ -0,0 +1,335 @@
+// Copyright 2017 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 "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/check_op.h"
+#include "base/memory/ptr_util.h"
+#include "base/optional.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/common/client_hints/client_hints.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+
+// An inner helper class to manage the SyncLoadContext's events and timeouts,
+// so that we can stop or resumse all of them at once.
+class SyncLoadContext::SignalHelper final {
+ public:
+ SignalHelper(SyncLoadContext* context,
+ base::WaitableEvent* redirect_or_response_event,
+ base::WaitableEvent* abort_event,
+ base::TimeDelta timeout)
+ : context_(context),
+ redirect_or_response_event_(redirect_or_response_event),
+ abort_event_(abort_event) {
+ // base::TimeDelta::Max() means no timeout.
+ if (timeout != base::TimeDelta::Max()) {
+ // Instantiate a base::OneShotTimer instance.
+ timeout_timer_.emplace();
+ }
+ Start(timeout);
+ }
+
+ void SignalRedirectOrResponseComplete() {
+ abort_watcher_.StopWatching();
+ if (timeout_timer_)
+ timeout_timer_->AbandonAndStop();
+ redirect_or_response_event_->Signal();
+ }
+
+ bool RestartAfterRedirect() {
+ if (abort_event_ && abort_event_->IsSignaled())
+ return false;
+
+ base::TimeDelta timeout_remainder = base::TimeDelta::Max();
+ if (timeout_timer_) {
+ timeout_remainder =
+ timeout_timer_->desired_run_time() - base::TimeTicks::Now();
+ if (timeout_remainder <= base::TimeDelta())
+ return false;
+ }
+ Start(timeout_remainder);
+ return true;
+ }
+
+ private:
+ void Start(base::TimeDelta timeout) {
+ DCHECK(!redirect_or_response_event_->IsSignaled());
+ if (abort_event_) {
+ abort_watcher_.StartWatching(
+ abort_event_,
+ base::BindOnce(&SyncLoadContext::OnAbort, base::Unretained(context_)),
+ context_->task_runner_);
+ }
+ if (timeout_timer_) {
+ DCHECK_NE(base::TimeDelta::Max(), timeout);
+ timeout_timer_->Start(FROM_HERE, timeout, context_,
+ &SyncLoadContext::OnTimeout);
+ }
+ }
+
+ SyncLoadContext* context_;
+ base::WaitableEvent* redirect_or_response_event_;
+ base::WaitableEvent* abort_event_;
+ base::WaitableEventWatcher abort_watcher_;
+ base::Optional<base::OneShotTimer> timeout_timer_;
+};
+
+// static
+void SyncLoadContext::StartAsyncWithWaitableEvent(
+ std::unique_ptr<network::ResourceRequest> request,
+ int routing_id,
+ scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ uint32_t loader_options,
+ std::unique_ptr<network::PendingSharedURLLoaderFactory>
+ pending_url_loader_factory,
+ WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
+ SyncLoadResponse* response,
+ SyncLoadContext** context_for_redirect,
+ base::WaitableEvent* redirect_or_response_event,
+ base::WaitableEvent* abort_event,
+ base::TimeDelta timeout,
+ mojo::PendingRemote<mojom::BlobRegistry> download_to_blob_registry,
+ const WebVector<WebString>& cors_exempt_header_list,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper) {
+ scoped_refptr<SyncLoadContext> context(new SyncLoadContext(
+ request.get(), std::move(pending_url_loader_factory), response,
+ context_for_redirect, redirect_or_response_event, abort_event, timeout,
+ std::move(download_to_blob_registry), loading_task_runner));
+ context->resource_request_sender_->SendAsync(
+ std::move(request), routing_id, std::move(loading_task_runner),
+ traffic_annotation, loader_options, cors_exempt_header_list,
+ context, context->url_loader_factory_, std::move(throttles),
+ std::move(resource_load_info_notifier_wrapper),
+ WebBackForwardCacheLoaderHelper());
+}
+
+SyncLoadContext::SyncLoadContext(
+ network::ResourceRequest* request,
+ std::unique_ptr<network::PendingSharedURLLoaderFactory> url_loader_factory,
+ SyncLoadResponse* response,
+ SyncLoadContext** context_for_redirect,
+ base::WaitableEvent* redirect_or_response_event,
+ base::WaitableEvent* abort_event,
+ base::TimeDelta timeout,
+ mojo::PendingRemote<mojom::BlobRegistry> download_to_blob_registry,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : response_(response),
+ context_for_redirect_(context_for_redirect),
+ body_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+ download_to_blob_registry_(std::move(download_to_blob_registry)),
+ task_runner_(std::move(task_runner)),
+ signals_(std::make_unique<SignalHelper>(this,
+ redirect_or_response_event,
+ abort_event,
+ timeout)) {
+ if (download_to_blob_registry_)
+ mode_ = Mode::kBlob;
+
+ url_loader_factory_ =
+ network::SharedURLLoaderFactory::Create(std::move(url_loader_factory));
+
+ // Constructs a new WebResourceRequestSender specifically for this request.
+ resource_request_sender_ = std::make_unique<WebResourceRequestSender>();
+
+ // Initialize the final URL with the original request URL. It will be
+ // overwritten on redirects.
+ response_->url = request->url;
+}
+
+SyncLoadContext::~SyncLoadContext() {}
+
+void SyncLoadContext::OnUploadProgress(uint64_t position, uint64_t size) {}
+
+bool SyncLoadContext::OnReceivedRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head,
+ std::vector<std::string>* removed_headers) {
+ DCHECK(!Completed());
+ if (removed_headers) {
+ // TODO(yoav): Get the actual FeaturePolicy here to support selective
+ // removal for sync XHR.
+ FindClientHintsToRemove(nullptr /* feature_policy */, redirect_info.new_url,
+ removed_headers);
+ }
+
+ response_->url = redirect_info.new_url;
+ response_->head = std::move(head);
+ response_->redirect_info = redirect_info;
+ *context_for_redirect_ = this;
+ resource_request_sender_->SetDefersLoading(
+ WebURLLoader::DeferType::kDeferred);
+ signals_->SignalRedirectOrResponseComplete();
+ return true;
+}
+
+void SyncLoadContext::FollowRedirect() {
+ if (!signals_->RestartAfterRedirect()) {
+ CancelRedirect();
+ return;
+ }
+
+ response_->redirect_info = net::RedirectInfo();
+ *context_for_redirect_ = nullptr;
+
+ resource_request_sender_->SetDefersLoading(
+ WebURLLoader::DeferType::kNotDeferred);
+}
+
+void SyncLoadContext::CancelRedirect() {
+ response_->redirect_info = net::RedirectInfo();
+ *context_for_redirect_ = nullptr;
+
+ response_->error_code = net::ERR_ABORTED;
+ CompleteRequest();
+}
+
+void SyncLoadContext::OnReceivedResponse(
+ network::mojom::URLResponseHeadPtr head) {
+ DCHECK(!Completed());
+ response_->head = std::move(head);
+}
+
+void SyncLoadContext::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ if (mode_ == Mode::kBlob) {
+ DCHECK(download_to_blob_registry_);
+ DCHECK(!blob_response_started_);
+
+ blob_response_started_ = true;
+
+ download_to_blob_registry_->RegisterFromStream(
+ response_->head->mime_type, "",
+ std::max<int64_t>(0, response_->head->content_length), std::move(body),
+ mojo::NullAssociatedRemote(),
+ base::BindOnce(&SyncLoadContext::OnFinishCreatingBlob,
+ base::Unretained(this)));
+ return;
+ }
+ DCHECK_EQ(Mode::kInitial, mode_);
+ mode_ = Mode::kDataPipe;
+ // setup datapipe to read.
+ body_handle_ = std::move(body);
+ body_watcher_.Watch(
+ body_handle_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(&SyncLoadContext::OnBodyReadable,
+ base::Unretained(this)));
+ body_watcher_.ArmOrNotify();
+}
+
+void SyncLoadContext::OnTransferSizeUpdated(int transfer_size_diff) {}
+
+void SyncLoadContext::OnCompletedRequest(
+ const network::URLLoaderCompletionStatus& status) {
+ if (Completed()) {
+ // It means the response has been aborted due to an error before finishing
+ // the response.
+ return;
+ }
+ request_completed_ = true;
+ response_->error_code = status.error_code;
+ response_->extended_error_code = status.extended_error_code;
+ response_->resolve_error_info = status.resolve_error_info;
+ response_->cors_error = status.cors_error_status;
+ response_->head->encoded_data_length = status.encoded_data_length;
+ response_->head->encoded_body_length = status.encoded_body_length;
+ if ((blob_response_started_ && !blob_finished_) || body_handle_.is_valid()) {
+ // The body is still begin downloaded as a Blob, or being read through the
+ // handle. Wait until it's completed.
+ return;
+ }
+ CompleteRequest();
+}
+
+void SyncLoadContext::OnFinishCreatingBlob(mojom::SerializedBlobPtr blob) {
+ DCHECK(!Completed());
+ blob_finished_ = true;
+ response_->downloaded_blob = std::move(blob);
+ if (request_completed_)
+ CompleteRequest();
+}
+
+void SyncLoadContext::OnBodyReadable(MojoResult,
+ const mojo::HandleSignalsState&) {
+ DCHECK_EQ(Mode::kDataPipe, mode_);
+ DCHECK(body_handle_.is_valid());
+ const void* buffer = nullptr;
+ uint32_t read_bytes = 0;
+ MojoResult result = body_handle_->BeginReadData(&buffer, &read_bytes,
+ MOJO_READ_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ body_watcher_.ArmOrNotify();
+ return;
+ }
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) {
+ // Whole body has been read.
+ body_handle_.reset();
+ body_watcher_.Cancel();
+ if (request_completed_)
+ CompleteRequest();
+ return;
+ }
+ if (result != MOJO_RESULT_OK) {
+ // Something went wrong.
+ body_handle_.reset();
+ body_watcher_.Cancel();
+ response_->error_code = net::ERR_FAILED;
+ CompleteRequest();
+ return;
+ }
+
+ response_->data.Append(static_cast<const char*>(buffer), read_bytes);
+ body_handle_->EndReadData(read_bytes);
+ body_watcher_.ArmOrNotify();
+}
+
+void SyncLoadContext::OnAbort(base::WaitableEvent* event) {
+ DCHECK(!Completed());
+ response_->error_code = net::ERR_ABORTED;
+ CompleteRequest();
+}
+
+void SyncLoadContext::OnTimeout() {
+ // OnTimeout() must not be called after CompleteRequest() was called, because
+ // the OneShotTimer must have been stopped.
+ DCHECK(!Completed());
+ response_->error_code = net::ERR_TIMED_OUT;
+ CompleteRequest();
+}
+
+void SyncLoadContext::CompleteRequest() {
+ DCHECK(blob_finished_ || (mode_ != Mode::kBlob));
+ DCHECK(!body_handle_.is_valid());
+ body_watcher_.Cancel();
+ signals_->SignalRedirectOrResponseComplete();
+ signals_ = nullptr;
+ response_ = nullptr;
+
+ // This will indirectly cause this object to be deleted.
+ resource_request_sender_->DeletePendingRequest(task_runner_);
+}
+
+bool SyncLoadContext::Completed() const {
+ DCHECK_EQ(!signals_, !response_);
+ return !response_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
new file mode 100644
index 00000000000..7f30c10962e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
@@ -0,0 +1,155 @@
+// Copyright 2017 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_SYNC_LOAD_CONTEXT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_SYNC_LOAD_CONTEXT_H_
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event_watcher.h"
+#include "base/timer/timer.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_request_peer.h"
+#include "third_party/blink/public/platform/web_resource_request_sender.h"
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace network {
+struct ResourceRequest;
+}
+
+namespace blink {
+class ResourceLoadInfoNotifierWrapper;
+class URLLoaderThrottle;
+struct SyncLoadResponse;
+
+// This class owns the context necessary to perform an asynchronous request
+// while the main thread is blocked so that it appears to be synchronous.
+// There are a couple of modes to load a request:
+// 1) kDataPipe; body is received on a data pipe passed on
+// OnStartLoadingResponseBody(), and the body is set to response_.data.
+// 2) kBlob: body is received on a data pipe passed on
+// OnStartLoadingResponseBody(), and wraps the data pipe with a
+// SerializedBlobPtr.
+class BLINK_PLATFORM_EXPORT SyncLoadContext : public WebRequestPeer {
+ public:
+ // Begins a new asynchronous request on whatever sequence this method is
+ // called on. |completed_event| will be signalled when the request is complete
+ // and |response| will be populated with the response data. |abort_event|
+ // will be signalled from the main thread to abort the sync request on a
+ // worker thread when the worker thread is being terminated.
+ // The pointer whose address is `context_for_redirect` is held by the caller
+ // that is blocked on this method, so it will remain valid until the operation
+ // completes. If there are redirects, `context_for_redirect` will point to the
+ // callee context.
+ // If |download_to_blob_registry| is not null, it is used to
+ // redirect the download to a blob, with the resulting blob populated in
+ // |response|.
+ static void StartAsyncWithWaitableEvent(
+ std::unique_ptr<network::ResourceRequest> request,
+ int routing_id,
+ scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ uint32_t loader_options,
+ std::unique_ptr<network::PendingSharedURLLoaderFactory>
+ pending_url_loader_factory,
+ WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
+ SyncLoadResponse* response,
+ SyncLoadContext** context_for_redirect,
+ base::WaitableEvent* completed_event,
+ base::WaitableEvent* abort_event,
+ base::TimeDelta timeout,
+ mojo::PendingRemote<mojom::BlobRegistry> download_to_blob_registry,
+ const WebVector<WebString>& cors_exempt_header_list,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper);
+
+ ~SyncLoadContext() override;
+
+ void FollowRedirect();
+ void CancelRedirect();
+
+ private:
+ friend class SyncLoadContextTest;
+
+ SyncLoadContext(
+ network::ResourceRequest* request,
+ std::unique_ptr<network::PendingSharedURLLoaderFactory>
+ url_loader_factory,
+ SyncLoadResponse* response,
+ SyncLoadContext** context_for_redirect,
+ base::WaitableEvent* completed_event,
+ base::WaitableEvent* abort_event,
+ base::TimeDelta timeout,
+ mojo::PendingRemote<mojom::BlobRegistry> download_to_blob_registry,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ // WebRequestPeer implementation:
+ void OnUploadProgress(uint64_t position, uint64_t size) override;
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head,
+ std::vector<std::string>*) override;
+ void OnReceivedResponse(network::mojom::URLResponseHeadPtr head) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override;
+ void OnTransferSizeUpdated(int transfer_size_diff) override;
+ void OnCompletedRequest(
+ const network::URLLoaderCompletionStatus& status) override;
+ void OnFinishCreatingBlob(mojom::SerializedBlobPtr blob);
+
+ void OnBodyReadable(MojoResult, const mojo::HandleSignalsState&);
+
+ void OnAbort(base::WaitableEvent* event);
+ void OnTimeout();
+
+ void CompleteRequest();
+ bool Completed() const;
+
+ // This raw pointer will remain valid for the lifetime of this object because
+ // it remains on the stack until |event_| is signaled.
+ // Set to null after CompleteRequest() is called.
+ SyncLoadResponse* response_;
+
+ // This raw pointer will be set to `this` when receiving redirects on
+ // independent thread and set to nullptr in `FollowRedirect()` or
+ // `CancelRedirect()` on the same thread after `redirect_or_response_event_`
+ // is signaled, which protects it against race condition.
+ SyncLoadContext** context_for_redirect_;
+
+ enum class Mode { kInitial, kDataPipe, kBlob };
+ Mode mode_ = Mode::kInitial;
+
+ // Used when Mode::kDataPipe.
+ mojo::ScopedDataPipeConsumerHandle body_handle_;
+ mojo::SimpleWatcher body_watcher_;
+
+ // State necessary to run a request on an independent thread.
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+ std::unique_ptr<WebResourceRequestSender> resource_request_sender_;
+
+ // State for downloading to a blob.
+ mojo::Remote<mojom::BlobRegistry> download_to_blob_registry_;
+ bool blob_response_started_ = false;
+ bool blob_finished_ = false;
+ bool request_completed_ = false;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ class SignalHelper;
+ std::unique_ptr<SignalHelper> signals_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncLoadContext);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_SYNC_LOAD_CONTEXT_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc
new file mode 100644
index 00000000000..836fde66b6d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc
@@ -0,0 +1,219 @@
+// 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 "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h"
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/task_environment.h"
+#include "base/threading/thread.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_resource_request_sender.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
+
+namespace blink {
+
+namespace {
+
+class TestSharedURLLoaderFactory : public network::TestURLLoaderFactory,
+ public network::SharedURLLoaderFactory {
+ public:
+ // mojom::URLLoaderFactory implementation.
+ void CreateLoaderAndStart(
+ mojo::PendingReceiver<network::mojom::URLLoader> receiver,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
+ override {
+ network::TestURLLoaderFactory::CreateLoaderAndStart(
+ std::move(receiver), routing_id, request_id, options, url_request,
+ std::move(client), traffic_annotation);
+ }
+
+ void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory>) override {
+ NOTREACHED();
+ }
+
+ std::unique_ptr<network::PendingSharedURLLoaderFactory> Clone() override {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ private:
+ friend class base::RefCounted<TestSharedURLLoaderFactory>;
+ ~TestSharedURLLoaderFactory() override = default;
+};
+
+class MockPendingSharedURLLoaderFactory
+ : public network::PendingSharedURLLoaderFactory {
+ public:
+ explicit MockPendingSharedURLLoaderFactory()
+ : factory_(base::MakeRefCounted<TestSharedURLLoaderFactory>()) {}
+
+ scoped_refptr<TestSharedURLLoaderFactory> factory() const { return factory_; }
+
+ protected:
+ scoped_refptr<network::SharedURLLoaderFactory> CreateFactory() override {
+ return factory_;
+ }
+
+ scoped_refptr<TestSharedURLLoaderFactory> factory_;
+};
+
+class MockResourceRequestSender : public WebResourceRequestSender {
+ public:
+ void CreatePendingRequest(scoped_refptr<WebRequestPeer> peer) {
+ peer_ = std::move(peer);
+ }
+
+ void DeletePendingRequest(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
+ peer_.reset();
+ }
+
+ private:
+ scoped_refptr<WebRequestPeer> peer_;
+};
+
+} // namespace
+
+class SyncLoadContextTest : public testing::Test {
+ public:
+ SyncLoadContextTest() : loading_thread_("loading thread") {}
+
+ void SetUp() override {
+ ASSERT_TRUE(loading_thread_.StartAndWaitForTesting());
+ }
+
+ void StartAsyncWithWaitableEventOnLoadingThread(
+ std::unique_ptr<network::ResourceRequest> request,
+ std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_factory,
+ SyncLoadResponse* out_response,
+ SyncLoadContext** context_for_redirect,
+ base::WaitableEvent* redirect_or_response_event) {
+ loading_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request),
+ MSG_ROUTING_NONE, loading_thread_.task_runner(),
+ TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* loader_options */,
+ std::move(pending_factory),
+ WebVector<std::unique_ptr<URLLoaderThrottle>>(), out_response,
+ context_for_redirect, redirect_or_response_event,
+ nullptr /* terminate_sync_load_event */,
+ base::TimeDelta::FromSeconds(60) /* timeout */,
+ mojo::NullRemote() /* download_to_blob_registry */,
+ WebVector<WebString>() /* cors_exempt_header_list */,
+ std::make_unique<ResourceLoadInfoNotifierWrapper>(
+ /*resource_load_info_notifier=*/nullptr,
+ task_environment_.GetMainThreadTaskRunner())));
+ }
+
+ static void RunSyncLoadContextViaDataPipe(
+ network::ResourceRequest* request,
+ SyncLoadResponse* response,
+ SyncLoadContext** context_for_redirect,
+ std::string expected_data,
+ base::WaitableEvent* redirect_or_response_event,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(task_runner->BelongsToCurrentThread());
+ auto* context = new SyncLoadContext(
+ request, std::make_unique<MockPendingSharedURLLoaderFactory>(),
+ response, context_for_redirect, redirect_or_response_event,
+ nullptr /* terminate_sync_load_event */,
+ base::TimeDelta::FromSeconds(60) /* timeout */,
+ mojo::NullRemote() /* download_to_blob_registry */, task_runner);
+
+ auto mock_resource_request_sender =
+ std::make_unique<MockResourceRequestSender>();
+ mock_resource_request_sender->CreatePendingRequest(
+ base::WrapRefCounted(context));
+ context->resource_request_sender_ = std::move(mock_resource_request_sender);
+
+ // Simulate the response.
+ context->OnReceivedResponse(network::mojom::URLResponseHead::New());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ mojo::CreateDataPipe(nullptr /* options */, producer_handle,
+ consumer_handle));
+ context->OnStartLoadingResponseBody(std::move(consumer_handle));
+ context->OnCompletedRequest(network::URLLoaderCompletionStatus(net::OK));
+
+ mojo::BlockingCopyFromString(expected_data, producer_handle);
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+ base::Thread loading_thread_;
+};
+
+TEST_F(SyncLoadContextTest, StartAsyncWithWaitableEvent) {
+ GURL expected_url = GURL("https://example.com");
+ std::string expected_data = "foobarbaz";
+
+ // Create and exercise SyncLoadContext on the |loading_thread_|.
+ auto request = std::make_unique<network::ResourceRequest>();
+ request->url = expected_url;
+ auto pending_factory = std::make_unique<MockPendingSharedURLLoaderFactory>();
+ pending_factory->factory()->AddResponse(expected_url.spec(), expected_data);
+ SyncLoadResponse response;
+ SyncLoadContext* context_for_redirect = nullptr;
+ base::WaitableEvent redirect_or_response_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ StartAsyncWithWaitableEventOnLoadingThread(
+ std::move(request), std::move(pending_factory), &response,
+ &context_for_redirect, &redirect_or_response_event);
+
+ // Wait until the response is received.
+ redirect_or_response_event.Wait();
+
+ // Check if |response| is set properly after the WaitableEvent fires.
+ EXPECT_EQ(net::OK, response.error_code);
+ const char* response_data = nullptr;
+ size_t size = response.data.GetSomeData(response_data, 0);
+ EXPECT_EQ(expected_data, std::string(response_data, size));
+}
+
+TEST_F(SyncLoadContextTest, ResponseBodyViaDataPipe) {
+ GURL expected_url = GURL("https://example.com");
+ std::string expected_data = "foobarbaz";
+
+ // Create and exercise SyncLoadContext on the |loading_thread_|.
+ auto request = std::make_unique<network::ResourceRequest>();
+ request->url = expected_url;
+ SyncLoadResponse response;
+ base::WaitableEvent redirect_or_response_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ SyncLoadContext* context_for_redirect = nullptr;
+ loading_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SyncLoadContextTest::RunSyncLoadContextViaDataPipe,
+ request.get(), &response, &context_for_redirect,
+ expected_data, &redirect_or_response_event,
+ loading_thread_.task_runner()));
+
+ // Wait until the response is received.
+ redirect_or_response_event.Wait();
+
+ // Check if |response| is set properly after the WaitableEvent fires.
+ EXPECT_EQ(net::OK, response.error_code);
+ const char* response_data = nullptr;
+ size_t size = response.data.GetSomeData(response_data, 0);
+ EXPECT_EQ(expected_data, std::string(response_data, size));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.cc
new file mode 100644
index 00000000000..d57646a79e7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.cc
@@ -0,0 +1,18 @@
+// Copyright 2014 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 "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
+
+namespace blink {
+
+SyncLoadResponse::SyncLoadResponse() = default;
+
+SyncLoadResponse::SyncLoadResponse(SyncLoadResponse&& other) = default;
+
+SyncLoadResponse::~SyncLoadResponse() = default;
+
+SyncLoadResponse& SyncLoadResponse::operator=(SyncLoadResponse&& other) =
+ default;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h
new file mode 100644
index 00000000000..01203eb37f2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h
@@ -0,0 +1,60 @@
+// Copyright 2014 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_SYNC_LOAD_RESPONSE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_SYNC_LOAD_RESPONSE_H_
+
+#include "base/optional.h"
+#include "net/dns/public/resolve_error_info.h"
+#include "services/network/public/cpp/cors/cors_error_status.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_data.h"
+#include "url/gurl.h"
+
+namespace blink {
+
+// See the SyncLoad method. (The name of this struct is not
+// suffixed with "Info" because it also contains the response data.)
+struct BLINK_PLATFORM_EXPORT SyncLoadResponse {
+ SyncLoadResponse();
+ SyncLoadResponse(SyncLoadResponse&& other);
+ ~SyncLoadResponse();
+
+ SyncLoadResponse& operator=(SyncLoadResponse&& other);
+
+ base::Optional<net::RedirectInfo> redirect_info;
+
+ network::mojom::URLResponseHeadPtr head =
+ network::mojom::URLResponseHead::New();
+
+ // The response error code.
+ int error_code;
+
+ // The response extended error code.
+ int extended_error_code = 0;
+
+ // Detailed host resolution error information.
+ net::ResolveErrorInfo resolve_error_info;
+
+ // Optional CORS error details.
+ base::Optional<network::CorsErrorStatus> cors_error;
+
+ // The final URL of the response. This may differ from the request URL in
+ // the case of a server redirect.
+ // Use GURL to avoid extra conversion between KURL and GURL because non-blink
+ // types are allowed for loader here.
+ GURL url;
+
+ // The response data.
+ WebData data;
+
+ // Used for blob response type XMLHttpRequest.
+ mojom::SerializedBlobPtr downloaded_blob;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_SYNC_LOAD_RESPONSE_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.cc
deleted file mode 100644
index 1c96e428bca..00000000000
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.cc
+++ /dev/null
@@ -1,459 +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 "third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.h"
-
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
-#include "components/web_package/web_bundle_parser.h"
-#include "components/web_package/web_bundle_utils.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "mojo/public/cpp/system/data_pipe.h"
-#include "mojo/public/cpp/system/data_pipe_drainer.h"
-#include "mojo/public/cpp/system/data_pipe_producer.h"
-#include "net/http/http_status_code.h"
-#include "services/network/public/mojom/url_loader.mojom.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-
-namespace blink {
-
-namespace {
-
-class WebBundleSubresourceLoader : public network::mojom::URLLoader {
- public:
- WebBundleSubresourceLoader(
- mojo::PendingReceiver<network::mojom::URLLoader> loader,
- const network::ResourceRequest& request,
- mojo::PendingRemote<network::mojom::URLLoaderClient> client)
- : url_(request.url),
- receiver_(this, std::move(loader)),
- client_(std::move(client)) {
- receiver_.set_disconnect_handler(base::BindOnce(
- &WebBundleSubresourceLoader::OnMojoDisconnect, GetWeakPtr()));
- }
- WebBundleSubresourceLoader(const WebBundleSubresourceLoader&) = delete;
- WebBundleSubresourceLoader& operator=(const WebBundleSubresourceLoader&) =
- delete;
-
- const GURL& Url() const { return url_; }
-
- base::WeakPtr<WebBundleSubresourceLoader> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- void OnResponse(network::mojom::URLResponseHeadPtr response) {
- client_->OnReceiveResponse(std::move(response));
- }
-
- void OnData(mojo::ScopedDataPipeConsumerHandle consumer) {
- client_->OnStartLoadingResponseBody(std::move(consumer));
- }
-
- void OnFail(net::Error error) {
- client_->OnComplete(network::URLLoaderCompletionStatus(error));
- delete this;
- }
-
- void OnWriteCompleted(MojoResult result) {
- network::URLLoaderCompletionStatus status(
- result == MOJO_RESULT_OK ? net::OK : net::ERR_INVALID_WEB_BUNDLE);
- client_->OnComplete(status);
- delete this;
- }
-
- private:
- // network::mojom::URLLoader
- void FollowRedirect(
- const std::vector<std::string>& removed_headers,
- const net::HttpRequestHeaders& modified_headers,
- const net::HttpRequestHeaders& modified_cors_exempt_headers,
- const base::Optional<GURL>& new_url) override {
- NOTREACHED();
- }
-
- void SetPriority(net::RequestPriority priority,
- int32_t intra_priority_value) override {
- // Not supported (do nothing).
- }
-
- void PauseReadingBodyFromNet() override {}
- void ResumeReadingBodyFromNet() override {}
-
- void OnMojoDisconnect() { delete this; }
-
- const GURL url_;
- mojo::Receiver<network::mojom::URLLoader> receiver_;
- mojo::Remote<network::mojom::URLLoaderClient> client_;
- base::WeakPtrFactory<WebBundleSubresourceLoader> weak_ptr_factory_{this};
-};
-
-class PipeDataSource : public mojo::DataPipeProducer::DataSource {
- public:
- explicit PipeDataSource(std::vector<uint8_t> data) : data_(std::move(data)) {}
- uint64_t GetLength() const override { return data_.size(); }
-
- ReadResult Read(uint64_t uint64_offset, base::span<char> buffer) override {
- ReadResult result;
- if (uint64_offset > data_.size()) {
- result.result = MOJO_RESULT_OUT_OF_RANGE;
- return result;
- }
- size_t offset = base::checked_cast<size_t>(uint64_offset);
- size_t len = std::min(data_.size() - offset, buffer.size());
- if (len > 0) {
- DCHECK_LT(offset, data_.size());
- memcpy(buffer.data(), &data_[offset], len);
- }
- result.bytes_read = len;
- return result;
- }
-
- private:
- // Since mojo::DataPipeProducer runs in its own sequence, we can't just have
- // a reference to the SharedBuffer in LinkWebBundleDataSource.
- std::vector<uint8_t> data_;
-};
-
-void DeleteProducerAndRunCallback(
- std::unique_ptr<mojo::DataPipeProducer> producer,
- base::OnceCallback<void(MojoResult result)> callback,
- MojoResult result) {
- std::move(callback).Run(result);
-}
-
-class LinkWebBundleDataSource : public web_package::mojom::BundleDataSource,
- public mojo::DataPipeDrainer::Client {
- public:
- using ReadToDataPipeCallback = base::OnceCallback<void(MojoResult result)>;
-
- LinkWebBundleDataSource(
- mojo::PendingReceiver<web_package::mojom::BundleDataSource>
- data_source_receiver,
- mojo::ScopedDataPipeConsumerHandle bundle_body)
- : data_source_receiver_(this, std::move(data_source_receiver)),
- data_(SharedBuffer::Create()),
- pipe_drainer_(
- std::make_unique<mojo::DataPipeDrainer>(this,
- std::move(bundle_body))) {}
-
- ~LinkWebBundleDataSource() override {
- // The receiver must be closed before destructing pending callbacks in
- // |pending_reads_| / |pending_reads_to_data_pipe_|.
- data_source_receiver_.reset();
- }
-
- LinkWebBundleDataSource(const LinkWebBundleDataSource&) = delete;
- LinkWebBundleDataSource& operator=(const LinkWebBundleDataSource&) = delete;
-
- void ReadToDataPipe(mojo::ScopedDataPipeProducerHandle producer,
- uint64_t offset,
- uint64_t length,
- ReadToDataPipeCallback callback) {
- TRACE_EVENT0("loading", "LinkWebBundleDataSource::ReadToDataPipe");
- if (!finished_loading_ && offset + length > data_->size()) {
- // Current implementation does not support progressive loading of inner
- // response body.
- PendingReadToDataPipe pending;
- pending.producer = std::move(producer);
- pending.offset = offset;
- pending.length = length;
- pending.callback = std::move(callback);
- pending_reads_to_data_pipe_.push_back(std::move(pending));
- return;
- }
-
- auto writer = std::make_unique<mojo::DataPipeProducer>(std::move(producer));
- mojo::DataPipeProducer* raw_writer = writer.get();
- raw_writer->Write(std::make_unique<PipeDataSource>(GetData(offset, length)),
- base::BindOnce(&DeleteProducerAndRunCallback,
- std::move(writer), std::move(callback)));
- }
-
- // mojom::BundleDataSource
- void Read(uint64_t offset, uint64_t length, ReadCallback callback) override {
- TRACE_EVENT0("loading", "LinkWebBundleDataSource::Read");
- if (!finished_loading_ && offset + length > data_->size()) {
- PendingRead pending;
- pending.offset = offset;
- pending.length = length;
- pending.callback = std::move(callback);
- pending_reads_.push_back(std::move(pending));
- return;
- }
- std::move(callback).Run(GetData(offset, length));
- }
-
- // mojo::DataPipeDrainer::Client
- void OnDataAvailable(const void* data, size_t num_bytes) override {
- DCHECK(!finished_loading_);
- data_->Append(reinterpret_cast<const char*>(data), num_bytes);
- ProcessPendingReads();
- }
-
- void OnDataComplete() override {
- DCHECK(!finished_loading_);
- finished_loading_ = true;
- ProcessPendingReads();
- }
-
- private:
- void ProcessPendingReads() {
- std::vector<PendingRead> pendings;
- pendings.swap(pending_reads_);
- for (auto& pending : pendings)
- Read(pending.offset, pending.length, std::move(pending.callback));
-
- std::vector<PendingReadToDataPipe> pipe_pendings;
- pipe_pendings.swap(pending_reads_to_data_pipe_);
- for (auto& pending : pipe_pendings) {
- ReadToDataPipe(std::move(pending.producer), pending.offset,
- pending.length, std::move(pending.callback));
- }
- }
-
- std::vector<uint8_t> GetData(uint64_t uint64_offset, uint64_t uint64_length) {
- size_t offset = base::checked_cast<size_t>(uint64_offset);
- size_t length = base::checked_cast<size_t>(uint64_length);
- std::vector<uint8_t> output(length);
- size_t bytes_copied = 0;
- for (auto it = data_->GetIteratorAt(offset);
- bytes_copied < length && it != data_->cend(); it++) {
- size_t n = std::min(it->size(), length - bytes_copied);
- memcpy(output.data() + bytes_copied, it->data(), n);
- bytes_copied += n;
- }
- output.resize(bytes_copied);
- return output;
- }
-
- struct PendingRead {
- uint64_t offset;
- uint64_t length;
- ReadCallback callback;
- };
- struct PendingReadToDataPipe {
- mojo::ScopedDataPipeProducerHandle producer;
- uint64_t offset;
- uint64_t length;
- ReadToDataPipeCallback callback;
- };
-
- mojo::Receiver<web_package::mojom::BundleDataSource> data_source_receiver_;
- scoped_refptr<SharedBuffer> data_;
- std::vector<PendingRead> pending_reads_;
- std::vector<PendingReadToDataPipe> pending_reads_to_data_pipe_;
- bool finished_loading_ = false;
- std::unique_ptr<mojo::DataPipeDrainer> pipe_drainer_;
-};
-
-// Self destroys when no more bindings exist.
-class WebBundleSubresourceLoaderFactory
- : public network::mojom::URLLoaderFactory {
- public:
- WebBundleSubresourceLoaderFactory(
- mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
- mojo::ScopedDataPipeConsumerHandle bundle_body,
- scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner,
- WebBundleErrorCallback error_callback)
- : callback_task_runner_(callback_task_runner),
- error_callback_(error_callback) {
- receivers_.Add(this, std::move(receiver));
- receivers_.set_disconnect_handler(base::BindRepeating(
- &WebBundleSubresourceLoaderFactory::OnMojoDisconnect,
- base::Unretained(this)));
- mojo::PendingRemote<web_package::mojom::BundleDataSource> data_source;
- source_ = std::make_unique<LinkWebBundleDataSource>(
- data_source.InitWithNewPipeAndPassReceiver(), std::move(bundle_body));
- // WebBundleParser will self-destruct on remote mojo ends' disconnection.
- new web_package::WebBundleParser(parser_.BindNewPipeAndPassReceiver(),
- std::move(data_source));
-
- parser_->ParseMetadata(
- WTF::Bind(&WebBundleSubresourceLoaderFactory::OnMetadataParsed,
- weak_ptr_factory_.GetWeakPtr()));
- }
-
- ~WebBundleSubresourceLoaderFactory() override {
- for (auto loader : pending_loaders_) {
- if (loader)
- loader->OnFail(net::ERR_FAILED);
- }
- }
-
- WebBundleSubresourceLoaderFactory(const WebBundleSubresourceLoaderFactory&) =
- delete;
- WebBundleSubresourceLoaderFactory& operator=(
- const WebBundleSubresourceLoaderFactory&) = delete;
-
- void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory)
- override {
- receivers_.Add(this, std::move(factory));
- }
-
- void CreateLoaderAndStart(
- mojo::PendingReceiver<network::mojom::URLLoader> pending_receiver,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const network::ResourceRequest& request,
- mojo::PendingRemote<network::mojom::URLLoaderClient> client,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
- override {
- TRACE_EVENT0("loading",
- "WebBundleSubresourceLoaderFactory::CreateLoaderAndStart");
- WebBundleSubresourceLoader* loader = new WebBundleSubresourceLoader(
- std::move(pending_receiver), request, std::move(client));
- if (metadata_error_) {
- loader->OnFail(net::ERR_INVALID_WEB_BUNDLE);
- return;
- }
- if (!metadata_) {
- pending_loaders_.push_back(loader->GetWeakPtr());
- return;
- }
- StartLoad(loader);
- }
-
- private:
- void OnMojoDisconnect() {
- if (!receivers_.empty())
- return;
- delete this;
- }
-
- void StartLoad(WebBundleSubresourceLoader* loader) {
- DCHECK(metadata_);
- if (!loader)
- return;
- auto it = metadata_->requests.find(loader->Url());
- if (it == metadata_->requests.end()) {
- RunErrorCallback(WebBundleErrorType::kResourceNotFound,
- loader->Url().possibly_invalid_spec() +
- " is not found in the WebBundle.");
- loader->OnFail(net::ERR_INVALID_WEB_BUNDLE);
- return;
- }
- // Currently, we just return the first response for the URL.
- // TODO(crbug.com/1082020): Support variant matching.
- auto& location = it->second->response_locations[0];
- parser_->ParseResponse(
- location->offset, location->length,
- WTF::Bind(&WebBundleSubresourceLoaderFactory::OnResponseParsed,
- weak_ptr_factory_.GetWeakPtr(), loader->GetWeakPtr()));
- }
-
- void OnMetadataParsed(web_package::mojom::BundleMetadataPtr metadata,
- web_package::mojom::BundleMetadataParseErrorPtr error) {
- TRACE_EVENT0("loading",
- "WebBundleSubresourceLoaderFactory::OnMetadataParsed");
- if (error) {
- metadata_error_ = std::move(error);
- RunErrorCallback(WebBundleErrorType::kMetadataParseError,
- metadata_error_->message);
- for (auto loader : pending_loaders_) {
- if (loader)
- loader->OnFail(net::ERR_INVALID_WEB_BUNDLE);
- }
- pending_loaders_.clear();
- return;
- }
-
- metadata_ = std::move(metadata);
- for (auto loader : pending_loaders_)
- StartLoad(loader.get());
- pending_loaders_.clear();
- }
-
- void OnResponseParsed(base::WeakPtr<WebBundleSubresourceLoader> loader,
- web_package::mojom::BundleResponsePtr response,
- web_package::mojom::BundleResponseParseErrorPtr error) {
- TRACE_EVENT0("loading",
- "WebBundleSubresourceLoaderFactory::OnResponseParsed");
- if (!loader)
- return;
- if (error) {
- RunErrorCallback(WebBundleErrorType::kResponseParseError, error->message);
- loader->OnFail(net::ERR_INVALID_WEB_BUNDLE);
- return;
- }
- // Currently we allow only net::HTTP_OK responses in bundles.
- // TODO(crbug.com/990733): Revisit this once
- // https://github.com/WICG/webpackage/issues/478 is resolved.
- if (response->response_code != net::HTTP_OK) {
- RunErrorCallback(WebBundleErrorType::kResponseParseError,
- "Invalid response code " +
- base::NumberToString(response->response_code));
- loader->OnFail(net::ERR_INVALID_WEB_BUNDLE);
- return;
- }
-
- loader->OnResponse(web_package::CreateResourceResponse(response));
-
- mojo::ScopedDataPipeProducerHandle producer;
- mojo::ScopedDataPipeConsumerHandle consumer;
- if (CreateDataPipe(nullptr, &producer, &consumer) != MOJO_RESULT_OK) {
- loader->OnFail(net::ERR_INSUFFICIENT_RESOURCES);
- return;
- }
- loader->OnData(std::move(consumer));
- source_->ReadToDataPipe(
- std::move(producer), response->payload_offset, response->payload_length,
- base::BindOnce(&WebBundleSubresourceLoader::OnWriteCompleted,
- loader->GetWeakPtr()));
- }
-
- void RunErrorCallback(WebBundleErrorType type, const std::string& message) {
- PostCrossThreadTask(*callback_task_runner_, FROM_HERE,
- WTF::CrossThreadBindOnce(error_callback_, type,
- String(message.c_str())));
- }
-
- mojo::ReceiverSet<network::mojom::URLLoaderFactory> receivers_;
- std::unique_ptr<LinkWebBundleDataSource> source_;
- mojo::Remote<web_package::mojom::WebBundleParser> parser_;
- web_package::mojom::BundleMetadataPtr metadata_;
- web_package::mojom::BundleMetadataParseErrorPtr metadata_error_;
- std::vector<base::WeakPtr<WebBundleSubresourceLoader>> pending_loaders_;
- scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_;
- WebBundleErrorCallback error_callback_;
-
- base::WeakPtrFactory<WebBundleSubresourceLoaderFactory> weak_ptr_factory_{
- this};
-};
-
-// Runs on a background thread.
-void CreateFactoryOnBackground(
- mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
- mojo::ScopedDataPipeConsumerHandle bundle_body,
- scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner,
- WebBundleErrorCallback error_callback) {
- new WebBundleSubresourceLoaderFactory(
- std::move(receiver), std::move(bundle_body), callback_task_runner,
- std::move(error_callback));
-}
-
-} // namespace
-
-void CreateWebBundleSubresourceLoaderFactory(
- CrossVariantMojoReceiver<network::mojom::URLLoaderFactoryInterfaceBase>
- factory_receiver,
- mojo::ScopedDataPipeConsumerHandle bundle_body,
- WebBundleErrorCallback error_callback) {
- auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
- {base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
- task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(&CreateFactoryOnBackground, std::move(factory_receiver),
- std::move(bundle_body),
- base::ThreadTaskRunnerHandle::Get(),
- std::move(error_callback)));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.h
deleted file mode 100644
index 82866299c59..00000000000
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.h
+++ /dev/null
@@ -1,39 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_WEB_BUNDLE_SUBRESOURCE_LOADER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_WEB_BUNDLE_SUBRESOURCE_LOADER_H_
-
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "services/network/public/mojom/url_loader_factory.mojom-shared.h"
-#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace WTF {
-class String;
-} // namespace WTF
-
-namespace blink {
-
-enum class WebBundleErrorType {
- kMetadataParseError,
- kResponseParseError,
- kResourceNotFound,
-};
-
-using WebBundleErrorCallback =
- base::RepeatingCallback<void(WebBundleErrorType,
- const WTF::String& message)>;
-
-// Creates a network::mojom::URLLoaderFactory that can load resources from a
-// WebBundle, and binds it to |factory_receiver|.
-PLATFORM_EXPORT void CreateWebBundleSubresourceLoaderFactory(
- CrossVariantMojoReceiver<network::mojom::URLLoaderFactoryInterfaceBase>
- factory_receiver,
- mojo::ScopedDataPipeConsumerHandle bundle_body,
- WebBundleErrorCallback error_callback);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_WEB_BUNDLE_SUBRESOURCE_LOADER_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader_test.cc
deleted file mode 100644
index 545ffebb7ac..00000000000
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader_test.cc
+++ /dev/null
@@ -1,336 +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 "third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.h"
-
-#include "base/test/task_environment.h"
-#include "components/web_package/test_support/web_bundle_builder.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "mojo/public/cpp/system/data_pipe_utils.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "services/network/public/mojom/url_loader.mojom.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "services/network/test/test_url_loader_client.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-namespace {
-
-const char kResourceUrl[] = "https://example.com/";
-const char kResourceUrl2[] = "https://example.com/another";
-const char kResourceUrl3[] = "https://example.com/yetanother";
-
-std::vector<uint8_t> CreateSmallBundle() {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
- builder.AddExchange(kResourceUrl,
- {{":status", "200"}, {"content-type", "text/plain"}},
- "body");
- return builder.CreateBundle();
-}
-
-std::vector<uint8_t> CreateLargeBundle() {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
- builder.AddExchange(kResourceUrl,
- {{":status", "200"}, {"content-type", "text/plain"}},
- "body");
- builder.AddExchange(kResourceUrl2,
- {{":status", "200"}, {"content-type", "text/plain"}},
- std::string(10000, 'a'));
- builder.AddExchange(kResourceUrl3,
- {{":status", "200"}, {"content-type", "text/plain"}},
- "body");
- return builder.CreateBundle();
-}
-
-} // namespace
-
-class WebBundleSubresourceLoaderFactoryTest : public ::testing::Test {
- public:
- void SetUp() override {
- mojo::ScopedDataPipeConsumerHandle consumer;
- ASSERT_EQ(CreateDataPipe(nullptr, &bundle_data_destination_, &consumer),
- MOJO_RESULT_OK);
- CreateWebBundleSubresourceLoaderFactory(
- loader_factory_.BindNewPipeAndPassReceiver(), std::move(consumer),
- base::BindRepeating(
- &WebBundleSubresourceLoaderFactoryTest::OnWebBundleError,
- base::Unretained(this)));
- }
-
- void WriteBundle(base::span<const uint8_t> data) {
- mojo::BlockingCopyFromString(
- std::string(reinterpret_cast<const char*>(data.data()), data.size()),
- bundle_data_destination_);
- }
-
- void FinishWritingBundle() { bundle_data_destination_.reset(); }
-
- struct StartRequestResult {
- mojo::Remote<network::mojom::URLLoader> loader;
- std::unique_ptr<network::TestURLLoaderClient> client;
- };
-
- StartRequestResult StartRequest(const GURL& url) {
- return StartRequestWithLoaderFactory(loader_factory_, url);
- }
-
- void RunUntilBundleError() {
- if (last_bundle_error_.has_value())
- return;
- base::RunLoop run_loop;
- quit_closure_for_bundle_error_ = run_loop.QuitClosure();
- run_loop.Run();
- }
-
- const base::Optional<std::pair<WebBundleErrorType, WTF::String>>&
- last_bundle_error() const {
- return last_bundle_error_;
- }
-
- protected:
- StartRequestResult StartRequestWithLoaderFactory(
- mojo::Remote<network::mojom::URLLoaderFactory>& factory,
- const GURL& url) {
- network::ResourceRequest request;
- request.url = url;
- request.method = "GET";
- StartRequestResult result;
- result.client = std::make_unique<network::TestURLLoaderClient>();
- factory->CreateLoaderAndStart(
- result.loader.BindNewPipeAndPassReceiver(), 0 /* routing_id */,
- 0 /* request_id */, 0 /* options */, request,
- result.client->CreateRemote(),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- return result;
- }
-
- mojo::Remote<network::mojom::URLLoaderFactory> loader_factory_;
-
- private:
- void OnWebBundleError(WebBundleErrorType type, const WTF::String& message) {
- last_bundle_error_ = std::make_pair(type, message);
- if (quit_closure_for_bundle_error_)
- std::move(quit_closure_for_bundle_error_).Run();
- }
-
- mojo::ScopedDataPipeProducerHandle bundle_data_destination_;
- base::test::TaskEnvironment task_environment;
- base::Optional<std::pair<WebBundleErrorType, WTF::String>> last_bundle_error_;
- base::OnceClosure quit_closure_for_bundle_error_;
-};
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, Basic) {
- WriteBundle(CreateSmallBundle());
- FinishWritingBundle();
-
- auto request = StartRequest(GURL(kResourceUrl));
- request.client->RunUntilComplete();
-
- EXPECT_EQ(net::OK, request.client->completion_status().error_code);
- EXPECT_FALSE(last_bundle_error().has_value());
- std::string body;
- EXPECT_TRUE(mojo::BlockingCopyToString(
- request.client->response_body_release(), &body));
- EXPECT_EQ("body", body);
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, Clone) {
- mojo::Remote<network::mojom::URLLoaderFactory> cloned_factory_;
- loader_factory_->Clone(cloned_factory_.BindNewPipeAndPassReceiver());
-
- WriteBundle(CreateSmallBundle());
- FinishWritingBundle();
-
- auto request =
- StartRequestWithLoaderFactory(cloned_factory_, GURL(kResourceUrl));
- request.client->RunUntilComplete();
-
- EXPECT_EQ(net::OK, request.client->completion_status().error_code);
- EXPECT_FALSE(last_bundle_error().has_value());
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, MetadataParseError) {
- auto request = StartRequest(GURL(kResourceUrl));
-
- std::vector<uint8_t> bundle = CreateSmallBundle();
- bundle[4] ^= 1; // Mutate magic bytes.
- WriteBundle(bundle);
- FinishWritingBundle();
-
- request.client->RunUntilComplete();
- RunUntilBundleError();
-
- EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
- request.client->completion_status().error_code);
- EXPECT_EQ(last_bundle_error()->first,
- WebBundleErrorType::kMetadataParseError);
- EXPECT_EQ(last_bundle_error()->second, "Wrong magic bytes.");
-
- // Requests made after metadata parse error should also fail.
- auto request2 = StartRequest(GURL(kResourceUrl));
- request2.client->RunUntilComplete();
-
- EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
- request2.client->completion_status().error_code);
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, ResponseParseError) {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
- // An invalid response.
- builder.AddExchange(kResourceUrl, {{":status", "0"}}, "body");
- WriteBundle(builder.CreateBundle());
- FinishWritingBundle();
-
- auto request = StartRequest(GURL(kResourceUrl));
- request.client->RunUntilComplete();
- RunUntilBundleError();
-
- EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
- request.client->completion_status().error_code);
- EXPECT_EQ(last_bundle_error()->first,
- WebBundleErrorType::kResponseParseError);
- EXPECT_EQ(last_bundle_error()->second,
- ":status must be 3 ASCII decimal digits.");
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, ResourceNotFoundInBundle) {
- WriteBundle(CreateSmallBundle());
- FinishWritingBundle();
-
- auto request = StartRequest(GURL("https://example.com/no-such-resource"));
- request.client->RunUntilComplete();
- RunUntilBundleError();
-
- EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
- request.client->completion_status().error_code);
- EXPECT_EQ(last_bundle_error()->first, WebBundleErrorType::kResourceNotFound);
- EXPECT_EQ(
- last_bundle_error()->second,
- "https://example.com/no-such-resource is not found in the WebBundle.");
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, RedirectResponseIsNotAllowed) {
- web_package::test::WebBundleBuilder builder(kResourceUrl,
- "" /* manifest_url */);
- builder.AddExchange(kResourceUrl,
- {{":status", "301"}, {"location", kResourceUrl2}}, "");
- builder.AddExchange(kResourceUrl2,
- {{":status", "200"}, {"content-type", "text/plain"}},
- "body");
- WriteBundle(builder.CreateBundle());
- FinishWritingBundle();
-
- auto request = StartRequest(GURL(kResourceUrl));
- request.client->RunUntilComplete();
- RunUntilBundleError();
-
- EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
- request.client->completion_status().error_code);
- EXPECT_EQ(last_bundle_error()->first,
- WebBundleErrorType::kResponseParseError);
- EXPECT_EQ(last_bundle_error()->second, "Invalid response code 301");
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, StartRequestBeforeReadingBundle) {
- auto request = StartRequest(GURL(kResourceUrl));
-
- WriteBundle(CreateSmallBundle());
- FinishWritingBundle();
- request.client->RunUntilComplete();
-
- EXPECT_EQ(net::OK, request.client->completion_status().error_code);
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, MultipleRequests) {
- auto request1 = StartRequest(GURL(kResourceUrl));
- auto request2 = StartRequest(GURL(kResourceUrl2));
-
- std::vector<uint8_t> bundle = CreateLargeBundle();
- // Write the first 10kB of the bundle in which the bundle's metadata and the
- // response for kResourceUrl are included.
- ASSERT_GT(bundle.size(), 10000U);
- WriteBundle(base::make_span(bundle).subspan(0, 10000));
- request1.client->RunUntilComplete();
-
- EXPECT_EQ(net::OK, request1.client->completion_status().error_code);
- EXPECT_FALSE(request2.client->has_received_completion());
-
- // Write the rest of the data.
- WriteBundle(base::make_span(bundle).subspan(10000));
- FinishWritingBundle();
- request2.client->RunUntilComplete();
-
- EXPECT_EQ(net::OK, request2.client->completion_status().error_code);
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, CancelRequest) {
- auto request_to_complete1 = StartRequest(GURL(kResourceUrl));
- auto request_to_complete2 = StartRequest(GURL(kResourceUrl2));
- auto request_to_cancel1 = StartRequest(GURL(kResourceUrl));
- auto request_to_cancel2 = StartRequest(GURL(kResourceUrl2));
- auto request_to_cancel3 = StartRequest(GURL(kResourceUrl3));
-
- // Cancel request before getting metadata.
- request_to_cancel1.loader.reset();
-
- std::vector<uint8_t> bundle = CreateLargeBundle();
- // Write the first 10kB of the bundle in which the bundle's metadata, response
- // for kResourceUrl, and response header for kResourceUrl2 are included.
- ASSERT_GT(bundle.size(), 10000U);
- WriteBundle(base::make_span(bundle).subspan(0, 10000));
-
- // This makes sure the bytes written above are consumed by WebBundle parser.
- request_to_complete1.client->RunUntilComplete();
-
- // Cancel request after reading response header, but before reading body.
- request_to_cancel2.loader.reset();
-
- // Cancel request after getting metadata, but before reading response header.
- request_to_cancel3.loader.reset();
-
- // Write the rest of the data.
- WriteBundle(base::make_span(bundle).subspan(10000));
- FinishWritingBundle();
- request_to_complete2.client->RunUntilComplete();
- EXPECT_EQ(net::OK,
- request_to_complete2.client->completion_status().error_code);
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest,
- FactoryDestructionCancelsInflightRequests) {
- auto request = StartRequest(GURL(kResourceUrl));
-
- loader_factory_.reset();
-
- WriteBundle(CreateSmallBundle());
- FinishWritingBundle();
- request.client->RunUntilComplete();
-
- EXPECT_EQ(net::ERR_FAILED, request.client->completion_status().error_code);
-}
-
-TEST_F(WebBundleSubresourceLoaderFactoryTest, TruncatedBundle) {
- std::vector<uint8_t> bundle = CreateSmallBundle();
- // Truncate in the middle of responses section.
- bundle.resize(bundle.size() - 10);
- WriteBundle(std::move(bundle));
- FinishWritingBundle();
-
- auto request = StartRequest(GURL(kResourceUrl));
- request.client->RunUntilComplete();
- RunUntilBundleError();
-
- EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
- request.client->completion_status().error_code);
- EXPECT_EQ(last_bundle_error()->first,
- WebBundleErrorType::kResponseParseError);
- EXPECT_EQ(last_bundle_error()->second, "Error reading response header.");
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc
new file mode 100644
index 00000000000..dee858aaca9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc
@@ -0,0 +1,630 @@
+// 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 "third_party/blink/public/platform/web_resource_request_sender.h"
+
+#include <utility>
+
+#include "base/atomic_sequence_num.h"
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/debug/alias.h"
+#include "base/files/file_path.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/rand_util.h"
+#include "base/strings/string_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/referrer_policy.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/common/client_hints/client_hints.h"
+#include "third_party/blink/public/common/loader/inter_process_time_ticks_converter.h"
+#include "third_party/blink/public/common/loader/network_utils.h"
+#include "third_party/blink/public/common/loader/referrer_utils.h"
+#include "third_party/blink/public/common/loader/resource_type_util.h"
+#include "third_party/blink/public/common/loader/throttling_url_loader.h"
+#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_request_peer.h"
+#include "third_party/blink/public/platform/web_resource_request_sender_delegate.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/back_forward_cache_utils.h"
+#include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+
+namespace WTF {
+
+template <>
+struct CrossThreadCopier<
+ blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>>> {
+ STATIC_ONLY(CrossThreadCopier);
+ using Type = blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>>;
+ static Type Copy(Type&& value) { return std::move(value); }
+};
+
+template <>
+struct CrossThreadCopier<net::NetworkTrafficAnnotationTag>
+ : public CrossThreadCopierPassThrough<net::NetworkTrafficAnnotationTag> {
+ STATIC_ONLY(CrossThreadCopier);
+ using Type = net::NetworkTrafficAnnotationTag;
+ static const Type& Copy(const Type& traffic_annotation) {
+ return traffic_annotation;
+ }
+};
+
+template <>
+struct CrossThreadCopier<blink::WebVector<blink::WebString>> {
+ STATIC_ONLY(CrossThreadCopier);
+ using Type = blink::WebVector<blink::WebString>;
+ static Type Copy(const Type& value) {
+ Type result;
+ result.reserve(value.size());
+ for (const auto& element : value)
+ result.emplace_back(element.IsolatedCopy());
+ return result;
+ }
+};
+
+} // namespace WTF
+
+namespace blink {
+
+namespace {
+
+// Converts |time| from a remote to local TimeTicks, overwriting the original
+// value.
+void RemoteToLocalTimeTicks(const InterProcessTimeTicksConverter& converter,
+ base::TimeTicks* time) {
+ RemoteTimeTicks remote_time = RemoteTimeTicks::FromTimeTicks(*time);
+ *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks();
+}
+
+void CheckSchemeForReferrerPolicy(const network::ResourceRequest& request) {
+ if ((request.referrer_policy ==
+ ReferrerUtils::GetDefaultNetReferrerPolicy() ||
+ request.referrer_policy ==
+ net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE) &&
+ request.referrer.SchemeIsCryptographic() &&
+ !url::Origin::Create(request.url).opaque() &&
+ !network::IsUrlPotentiallyTrustworthy(request.url)) {
+ LOG(FATAL) << "Trying to send secure referrer for insecure request "
+ << "without an appropriate referrer policy.\n"
+ << "URL = " << request.url << "\n"
+ << "URL's Origin = "
+ << url::Origin::Create(request.url).Serialize() << "\n"
+ << "Referrer = " << request.referrer;
+ }
+}
+
+int GetInitialRequestID() {
+ // Starting with a random number speculatively avoids RDH_INVALID_REQUEST_ID
+ // which are assumed to have been caused by restarting RequestID at 0 when
+ // restarting a renderer after a crash - this would cause collisions if
+ // requests from the previously crashed renderer are still active. See
+ // https://crbug.com/614281#c61 for more details about this hypothesis.
+ //
+ // To avoid increasing the likelihood of overflowing the range of available
+ // RequestIDs, kMax is set to a relatively low value of 2^20 (rather than
+ // to something higher like 2^31).
+ const int kMin = 0;
+ const int kMax = 1 << 20;
+ return base::RandInt(kMin, kMax);
+}
+
+// Determines if the loader should be restarted on a redirect using
+// ThrottlingURLLoader::FollowRedirectForcingRestart.
+bool RedirectRequiresLoaderRestart(const GURL& original_url,
+ const GURL& redirect_url) {
+ // Restart is needed if the URL is no longer handled by network service.
+ if (network_utils::IsURLHandledByNetworkService(original_url))
+ return !network_utils::IsURLHandledByNetworkService(redirect_url);
+
+ // If URL wasn't originally handled by network service, restart is needed if
+ // schemes are different.
+ return original_url.scheme_piece() != redirect_url.scheme_piece();
+}
+
+} // namespace
+
+// static
+int WebResourceRequestSender::MakeRequestID() {
+ static const int kInitialRequestID = GetInitialRequestID();
+ static base::AtomicSequenceNumber sequence;
+ return kInitialRequestID + sequence.GetNext();
+}
+
+WebResourceRequestSender::WebResourceRequestSender()
+ : delegate_(Platform::Current()->GetResourceRequestSenderDelegate()) {}
+
+WebResourceRequestSender::~WebResourceRequestSender() = default;
+
+void WebResourceRequestSender::SendSync(
+ std::unique_ptr<network::ResourceRequest> request,
+ int routing_id,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ uint32_t loader_options,
+ SyncLoadResponse* response,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
+ base::TimeDelta timeout,
+ const WebVector<WebString>& cors_exempt_header_list,
+ base::WaitableEvent* terminate_sync_load_event,
+ mojo::PendingRemote<mojom::BlobRegistry> download_to_blob_registry,
+ scoped_refptr<WebRequestPeer> peer,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper) {
+ if (IsInflightNetworkRequestBackForwardCacheSupportEnabled()) {
+ // Sync fetches are triggered by script, which should not run when a
+ // document is in back-forward cache. If we somehow made it here, we should
+ // trigger a back-forward cache eviction.
+ auto* helper =
+ back_forward_cache_loader_helper.GetBackForwardCacheLoaderHelper();
+ if (helper) {
+ helper->EvictFromBackForwardCache(
+ mojom::RendererEvictionReason::kJavaScriptExecution);
+ }
+ }
+
+ CheckSchemeForReferrerPolicy(*request);
+
+ DCHECK(loader_options & network::mojom::kURLLoadOptionSynchronous);
+ DCHECK(request->load_flags & net::LOAD_IGNORE_LIMITS);
+
+ std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_factory =
+ url_loader_factory->Clone();
+ base::WaitableEvent redirect_or_response_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ // Prepare the configured throttles for use on a separate thread.
+ for (const auto& throttle : throttles)
+ throttle->DetachFromCurrentSequence();
+
+ // A task is posted to a separate thread to execute the request so that
+ // this thread may block on a waitable event. It is safe to pass raw
+ // pointers to on-stack objects as this stack frame will
+ // survive until the request is complete.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ base::ThreadPool::CreateSingleThreadTaskRunner({});
+ SyncLoadContext* context_for_redirect = nullptr;
+ PostCrossThreadTask(
+ *task_runner, FROM_HERE,
+ WTF::CrossThreadBindOnce(
+ &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request),
+ routing_id, task_runner, traffic_annotation, loader_options,
+ std::move(pending_factory), std::move(throttles),
+ CrossThreadUnretained(response),
+ CrossThreadUnretained(&context_for_redirect),
+ CrossThreadUnretained(&redirect_or_response_event),
+ CrossThreadUnretained(terminate_sync_load_event), timeout,
+ std::move(download_to_blob_registry), cors_exempt_header_list,
+ std::move(resource_load_info_notifier_wrapper)));
+
+ // redirect_or_response_event will signal when each redirect completes, and
+ // when the final response is complete.
+ redirect_or_response_event.Wait();
+
+ while (context_for_redirect) {
+ DCHECK(response->redirect_info);
+ bool follow_redirect = peer->OnReceivedRedirect(
+ *response->redirect_info, response->head.Clone(),
+ nullptr /* removed_headers */);
+ redirect_or_response_event.Reset();
+ if (follow_redirect) {
+ task_runner->PostTask(
+ FROM_HERE, base::BindOnce(&SyncLoadContext::FollowRedirect,
+ base::Unretained(context_for_redirect)));
+ } else {
+ task_runner->PostTask(
+ FROM_HERE, base::BindOnce(&SyncLoadContext::CancelRedirect,
+ base::Unretained(context_for_redirect)));
+ }
+ redirect_or_response_event.Wait();
+ }
+}
+
+int WebResourceRequestSender::SendAsync(
+ std::unique_ptr<network::ResourceRequest> request,
+ int routing_id,
+ scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ uint32_t loader_options,
+ const WebVector<WebString>& cors_exempt_header_list,
+ scoped_refptr<WebRequestPeer> peer,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper) {
+ auto weak_this = weak_factory_.GetWeakPtr();
+
+ CheckSchemeForReferrerPolicy(*request);
+
+#if defined(OS_ANDROID)
+ // Main frame shouldn't come here.
+ DCHECK(!(request->is_main_frame &&
+ IsRequestDestinationFrame(request->destination)));
+ if (request->has_user_gesture) {
+ resource_load_info_notifier_wrapper->NotifyUpdateUserGestureCarryoverInfo();
+ }
+#endif
+
+ // Compute a unique request_id for this renderer process.
+ int request_id = MakeRequestID();
+ request_info_ = std::make_unique<PendingRequestInfo>(
+ std::move(peer), request->destination, request->render_frame_id,
+ request->url, std::move(resource_load_info_notifier_wrapper));
+
+ request_info_->resource_load_info_notifier_wrapper
+ ->NotifyResourceLoadInitiated(
+ request_id, request->url, request->method, request->referrer,
+ request_info_->request_destination, request->priority);
+
+ request_info_->previews_state = request->previews_state;
+
+ auto client = std::make_unique<MojoURLLoaderClient>(
+ this, loading_task_runner, url_loader_factory->BypassRedirectChecks(),
+ request->url, back_forward_cache_loader_helper);
+
+ std::vector<std::string> std_cors_exempt_header_list(
+ cors_exempt_header_list.size());
+ std::transform(cors_exempt_header_list.begin(), cors_exempt_header_list.end(),
+ std_cors_exempt_header_list.begin(),
+ [](const WebString& h) { return h.Latin1(); });
+ std::unique_ptr<ThrottlingURLLoader> url_loader =
+ ThrottlingURLLoader::CreateLoaderAndStart(
+ std::move(url_loader_factory), throttles.ReleaseVector(), routing_id,
+ request_id, loader_options, request.get(), client.get(),
+ traffic_annotation, std::move(loading_task_runner),
+ base::make_optional(std_cors_exempt_header_list));
+ // TODO(https://crbug.com/1175286): Remove this mitigation when we understand
+ // why `this` or `request_info_` is being destroyed.
+ if (!weak_this || !request_info_)
+ return request_id;
+
+ request_info_->url_loader = std::move(url_loader);
+ request_info_->url_loader_client = std::move(client);
+
+ return request_id;
+}
+
+void WebResourceRequestSender::Cancel(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ // Cancel the request if it didn't complete, and clean it up so the bridge
+ // will receive no more messages.
+ DeletePendingRequest(std::move(task_runner));
+}
+
+void WebResourceRequestSender::SetDefersLoading(WebURLLoader::DeferType value) {
+ if (!request_info_) {
+ DLOG(ERROR) << "unknown request";
+ return;
+ }
+ if (value != WebURLLoader::DeferType::kNotDeferred) {
+ request_info_->is_deferred = value;
+ request_info_->url_loader_client->SetDefersLoading(value);
+ } else if (request_info_->is_deferred !=
+ WebURLLoader::DeferType::kNotDeferred) {
+ request_info_->is_deferred = WebURLLoader::DeferType::kNotDeferred;
+ request_info_->url_loader_client->SetDefersLoading(
+ WebURLLoader::DeferType::kNotDeferred);
+
+ FollowPendingRedirect(request_info_.get());
+ }
+}
+
+void WebResourceRequestSender::DidChangePriority(
+ net::RequestPriority new_priority,
+ int intra_priority_value) {
+ if (!request_info_) {
+ DLOG(ERROR) << "unknown request";
+ return;
+ }
+
+ request_info_->url_loader->SetPriority(new_priority, intra_priority_value);
+}
+
+void WebResourceRequestSender::DeletePendingRequest(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ if (!request_info_)
+ return;
+
+ if (request_info_->net_error == net::ERR_IO_PENDING) {
+ request_info_->net_error = net::ERR_ABORTED;
+ request_info_->resource_load_info_notifier_wrapper
+ ->NotifyResourceLoadCanceled(request_info_->net_error);
+ }
+
+ // Cancel loading.
+ request_info_->url_loader.reset();
+
+ // Clear URLLoaderClient to stop receiving further Mojo IPC from the browser
+ // process.
+ request_info_->url_loader_client.reset();
+
+ // Always delete the `request_info_` asyncly so that cancelling the request
+ // doesn't delete the request context which the `request_info_->peer` points
+ // to while its response is still being handled.
+ task_runner->DeleteSoon(FROM_HERE, request_info_.release());
+}
+
+WebResourceRequestSender::PendingRequestInfo::PendingRequestInfo(
+ scoped_refptr<WebRequestPeer> peer,
+ network::mojom::RequestDestination request_destination,
+ int render_frame_id,
+ const GURL& request_url,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper)
+ : peer(std::move(peer)),
+ request_destination(request_destination),
+ render_frame_id(render_frame_id),
+ url(request_url),
+ response_url(request_url),
+ local_request_start(base::TimeTicks::Now()),
+ resource_load_info_notifier_wrapper(
+ std::move(resource_load_info_notifier_wrapper)) {}
+
+WebResourceRequestSender::PendingRequestInfo::~PendingRequestInfo() = default;
+
+void WebResourceRequestSender::FollowPendingRedirect(
+ PendingRequestInfo* request_info) {
+ if (request_info->has_pending_redirect &&
+ request_info->should_follow_redirect) {
+ request_info->has_pending_redirect = false;
+ // net::URLRequest clears its request_start on redirect, so should we.
+ request_info->local_request_start = base::TimeTicks::Now();
+ // Redirect URL may not be handled by the network service, so force a
+ // restart in case another URLLoaderFactory should handle the URL.
+ if (request_info->redirect_requires_loader_restart) {
+ request_info->url_loader->FollowRedirectForcingRestart();
+ } else {
+ std::vector<std::string> removed_headers(
+ request_info_->removed_headers.size());
+ std::transform(request_info_->removed_headers.begin(),
+ request_info_->removed_headers.end(),
+ removed_headers.begin(),
+ [](const WebString& h) { return h.Ascii(); });
+ request_info->url_loader->FollowRedirect(
+ removed_headers, {} /* modified_headers */,
+ {} /* modified_cors_exempt_headers */);
+ }
+ }
+}
+
+void WebResourceRequestSender::OnTransferSizeUpdated(
+ int32_t transfer_size_diff) {
+ DCHECK_GT(transfer_size_diff, 0);
+ if (!request_info_)
+ return;
+
+ // TODO(yhirano): Consider using int64_t in
+ // WebRequestPeer::OnTransferSizeUpdated.
+ request_info_->peer->OnTransferSizeUpdated(transfer_size_diff);
+ if (!request_info_)
+ return;
+ request_info_->resource_load_info_notifier_wrapper
+ ->NotifyResourceTransferSizeUpdated(transfer_size_diff);
+}
+
+void WebResourceRequestSender::OnUploadProgress(int64_t position,
+ int64_t size) {
+ if (!request_info_)
+ return;
+
+ request_info_->peer->OnUploadProgress(position, size);
+}
+
+void WebResourceRequestSender::OnReceivedResponse(
+ network::mojom::URLResponseHeadPtr response_head) {
+ TRACE_EVENT0("loading", "WebResourceRequestSender::OnReceivedResponse");
+ if (!request_info_)
+ return;
+ request_info_->local_response_start = base::TimeTicks::Now();
+ request_info_->remote_request_start =
+ response_head->load_timing.request_start;
+ // Now that response_start has been set, we can properly set the TimeTicks in
+ // the URLResponseHead.
+ ToLocalURLResponseHead(*request_info_, *response_head);
+ request_info_->load_timing_info = response_head->load_timing;
+ if (delegate_) {
+ scoped_refptr<WebRequestPeer> new_peer = delegate_->OnReceivedResponse(
+ std::move(request_info_->peer),
+ WebString::FromUTF8(response_head->mime_type),
+ KURL(request_info_->url));
+ DCHECK(new_peer);
+ request_info_->peer = std::move(new_peer);
+ }
+
+ request_info_->peer->OnReceivedResponse(response_head.Clone());
+ if (!request_info_)
+ return;
+
+ request_info_->resource_load_info_notifier_wrapper
+ ->NotifyResourceResponseReceived(std::move(response_head),
+ request_info_->previews_state);
+}
+
+void WebResourceRequestSender::OnReceivedCachedMetadata(
+ mojo_base::BigBuffer data) {
+ if (!request_info_)
+ return;
+
+ if (data.size()) {
+ request_info_->peer->OnReceivedCachedMetadata(std::move(data));
+ }
+}
+
+void WebResourceRequestSender::OnReceivedRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr response_head,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ TRACE_EVENT0("loading", "WebResourceRequestSender::OnReceivedRedirect");
+ if (!request_info_)
+ return;
+ if (!request_info_->url_loader && request_info_->should_follow_redirect) {
+ // This is a redirect that synchronously came as the loader is being
+ // constructed, due to a URLLoaderThrottle that changed the starting
+ // URL. Handle this in a posted task, as we don't have the loader
+ // pointer yet.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&WebResourceRequestSender::OnReceivedRedirect,
+ weak_factory_.GetWeakPtr(), redirect_info,
+ std::move(response_head), task_runner));
+ return;
+ }
+
+ request_info_->local_response_start = base::TimeTicks::Now();
+ request_info_->remote_request_start =
+ response_head->load_timing.request_start;
+ request_info_->redirect_requires_loader_restart =
+ RedirectRequiresLoaderRestart(request_info_->response_url,
+ redirect_info.new_url);
+
+ ToLocalURLResponseHead(*request_info_, *response_head);
+ std::vector<std::string> removed_headers;
+ if (request_info_->peer->OnReceivedRedirect(
+ redirect_info, response_head.Clone(), &removed_headers)) {
+ // Double-check if the request is still around. The call above could
+ // potentially remove it.
+ if (!request_info_)
+ return;
+ // TODO(yoav): If request_info doesn't change above, we could avoid this
+ // copy.
+ WebVector<WebString> vector(removed_headers.size());
+ std::transform(
+ removed_headers.begin(), removed_headers.end(), vector.begin(),
+ [](const std::string& h) { return WebString::FromASCII(h); });
+ request_info_->removed_headers = vector;
+ request_info_->response_url = redirect_info.new_url;
+ request_info_->has_pending_redirect = true;
+ request_info_->resource_load_info_notifier_wrapper
+ ->NotifyResourceRedirectReceived(redirect_info,
+ std::move(response_head));
+
+ if (request_info_->is_deferred == WebURLLoader::DeferType::kNotDeferred)
+ FollowPendingRedirect(request_info_.get());
+ } else {
+ Cancel(std::move(task_runner));
+ }
+}
+
+void WebResourceRequestSender::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ TRACE_EVENT0("loading",
+ "WebResourceRequestSender::OnStartLoadingResponseBody");
+
+ if (!request_info_)
+ return;
+ request_info_->peer->OnStartLoadingResponseBody(std::move(body));
+}
+
+void WebResourceRequestSender::OnRequestComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ TRACE_EVENT0("loading", "WebResourceRequestSender::OnRequestComplete");
+
+ if (!request_info_)
+ return;
+ request_info_->net_error = status.error_code;
+
+ request_info_->resource_load_info_notifier_wrapper
+ ->NotifyResourceLoadCompleted(status);
+
+ WebRequestPeer* peer = request_info_->peer.get();
+
+ if (delegate_) {
+ delegate_->OnRequestComplete();
+ }
+
+ network::URLLoaderCompletionStatus renderer_status(status);
+ if (status.completion_time.is_null()) {
+ // No completion timestamp is provided, leave it as is.
+ } else if (request_info_->remote_request_start.is_null() ||
+ request_info_->load_timing_info.request_start.is_null()) {
+ // We cannot convert the remote time to a local time, let's use the current
+ // timestamp. This happens when
+ // - We get an error before OnReceivedRedirect or OnReceivedResponse is
+ // called, or
+ // - Somehow such a timestamp was missing in the LoadTimingInfo.
+ renderer_status.completion_time = base::TimeTicks::Now();
+ } else {
+ // We have already converted the request start timestamp, let's use that
+ // conversion information.
+ // Note: We cannot create a InterProcessTimeTicksConverter with
+ // (local_request_start, now, remote_request_start, remote_completion_time)
+ // as that may result in inconsistent timestamps.
+ renderer_status.completion_time =
+ std::min(status.completion_time - request_info_->remote_request_start +
+ request_info_->load_timing_info.request_start,
+ base::TimeTicks::Now());
+ }
+ // The request ID will be removed from our pending list in the destructor.
+ // Normally, dispatching this message causes the reference-counted request to
+ // die immediately.
+ // TODO(kinuko): Revisit here. This probably needs to call request_info_->peer
+ // but the past attempt to change it seems to have caused crashes.
+ // (crbug.com/547047)
+ peer->OnCompletedRequest(renderer_status);
+}
+
+void WebResourceRequestSender::ToLocalURLResponseHead(
+ const PendingRequestInfo& request_info,
+ network::mojom::URLResponseHead& response_head) const {
+ if (base::TimeTicks::IsConsistentAcrossProcesses() ||
+ request_info.local_request_start.is_null() ||
+ request_info.local_response_start.is_null() ||
+ response_head.request_start.is_null() ||
+ response_head.response_start.is_null() ||
+ response_head.load_timing.request_start.is_null()) {
+ return;
+ }
+ InterProcessTimeTicksConverter converter(
+ LocalTimeTicks::FromTimeTicks(request_info.local_request_start),
+ LocalTimeTicks::FromTimeTicks(request_info.local_response_start),
+ RemoteTimeTicks::FromTimeTicks(response_head.request_start),
+ RemoteTimeTicks::FromTimeTicks(response_head.response_start));
+
+ net::LoadTimingInfo* load_timing = &response_head.load_timing;
+ RemoteToLocalTimeTicks(converter, &load_timing->request_start);
+ RemoteToLocalTimeTicks(converter, &load_timing->proxy_resolve_start);
+ RemoteToLocalTimeTicks(converter, &load_timing->proxy_resolve_end);
+ RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.dns_start);
+ RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.dns_end);
+ RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.connect_start);
+ RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.connect_end);
+ RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.ssl_start);
+ RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.ssl_end);
+ RemoteToLocalTimeTicks(converter, &load_timing->send_start);
+ RemoteToLocalTimeTicks(converter, &load_timing->send_end);
+ RemoteToLocalTimeTicks(converter, &load_timing->receive_headers_start);
+ RemoteToLocalTimeTicks(converter, &load_timing->receive_headers_end);
+ RemoteToLocalTimeTicks(converter, &load_timing->push_start);
+ RemoteToLocalTimeTicks(converter, &load_timing->push_end);
+ RemoteToLocalTimeTicks(converter, &load_timing->service_worker_start_time);
+ RemoteToLocalTimeTicks(converter, &load_timing->service_worker_ready_time);
+ RemoteToLocalTimeTicks(converter, &load_timing->service_worker_fetch_start);
+ RemoteToLocalTimeTicks(converter,
+ &load_timing->service_worker_respond_with_settled);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc
new file mode 100644
index 00000000000..48e373a8be6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc
@@ -0,0 +1,561 @@
+// Copyright (c) 2012 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 "third_party/blink/public/platform/web_resource_request_sender.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/feature_list.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_response_headers.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/loader/referrer_utils.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_request_peer.h"
+#include "third_party/blink/public/platform/web_resource_request_sender_delegate.h"
+#include "third_party/blink/public/platform/web_url_request_extra_data.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+#include "url/gurl.h"
+
+namespace blink {
+
+namespace {
+
+static constexpr char kTestPageUrl[] = "http://www.google.com/";
+static constexpr char kTestPageHeaders[] =
+ "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
+static constexpr char kTestPageMimeType[] = "text/html";
+static constexpr char kTestPageCharset[] = "";
+static constexpr char kTestPageContents[] =
+ "<html><head><title>Google</title></head><body><h1>Google</h1></body></"
+ "html>";
+
+constexpr size_t kDataPipeCapacity = 4096;
+
+std::string ReadOneChunk(mojo::ScopedDataPipeConsumerHandle* handle) {
+ char buffer[kDataPipeCapacity];
+ uint32_t read_bytes = kDataPipeCapacity;
+ MojoResult result =
+ (*handle)->ReadData(buffer, &read_bytes, MOJO_READ_DATA_FLAG_NONE);
+ if (result != MOJO_RESULT_OK)
+ return "";
+ return std::string(buffer, read_bytes);
+}
+
+// Returns a fake TimeTicks based on the given microsecond offset.
+base::TimeTicks TicksFromMicroseconds(int64_t micros) {
+ return base::TimeTicks() + base::TimeDelta::FromMicroseconds(micros);
+}
+
+} // namespace
+
+class TestResourceRequestSenderDelegate
+ : public WebResourceRequestSenderDelegate {
+ public:
+ TestResourceRequestSenderDelegate() = default;
+ ~TestResourceRequestSenderDelegate() override = default;
+
+ void OnRequestComplete() override {}
+
+ scoped_refptr<WebRequestPeer> OnReceivedResponse(
+ scoped_refptr<WebRequestPeer> current_peer,
+ const WebString& mime_type,
+ const WebURL& url) override {
+ return base::MakeRefCounted<WrapperPeer>(std::move(current_peer));
+ }
+
+ class WrapperPeer : public WebRequestPeer {
+ public:
+ explicit WrapperPeer(scoped_refptr<WebRequestPeer> original_peer)
+ : original_peer_(std::move(original_peer)) {}
+
+ // WebRequestPeer overrides:
+ void OnUploadProgress(uint64_t position, uint64_t size) override {}
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head,
+ std::vector<std::string>*) override {
+ return false;
+ }
+ void OnReceivedResponse(network::mojom::URLResponseHeadPtr head) override {
+ response_head_ = std::move(head);
+ }
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override {
+ body_handle_ = std::move(body);
+ }
+ void OnTransferSizeUpdated(int transfer_size_diff) override {}
+ void OnCompletedRequest(
+ const network::URLLoaderCompletionStatus& status) override {
+ original_peer_->OnReceivedResponse(std::move(response_head_));
+ original_peer_->OnStartLoadingResponseBody(std::move(body_handle_));
+ original_peer_->OnCompletedRequest(status);
+ }
+
+ private:
+ scoped_refptr<WebRequestPeer> original_peer_;
+ network::mojom::URLResponseHeadPtr response_head_;
+ mojo::ScopedDataPipeConsumerHandle body_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(WrapperPeer);
+ };
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestResourceRequestSenderDelegate);
+};
+
+// A mock WebRequestPeer to receive messages from the WebResourceRequestSender.
+class MockRequestPeer : public WebRequestPeer {
+ public:
+ explicit MockRequestPeer(WebResourceRequestSender* resource_request_sender)
+ : resource_request_sender_(resource_request_sender) {}
+
+ // WebRequestPeer overrides:
+ void OnUploadProgress(uint64_t position, uint64_t size) override {}
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head,
+ std::vector<std::string>* removed_headers) override {
+ last_load_timing_ = head->load_timing;
+ return true;
+ }
+ void OnReceivedResponse(network::mojom::URLResponseHeadPtr head) override {
+ last_load_timing_ = head->load_timing;
+ received_response_ = true;
+ if (cancel_on_receive_response_) {
+ resource_request_sender_->Cancel(
+ scheduler::GetSingleThreadTaskRunnerForTesting());
+ }
+ }
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override {
+ if (cancel_on_receive_response_)
+ return;
+ if (body) {
+ data_ += ReadOneChunk(&body);
+ }
+ }
+ void OnTransferSizeUpdated(int transfer_size_diff) override {}
+ void OnReceivedCachedMetadata(mojo_base::BigBuffer data) override {}
+ void OnCompletedRequest(
+ const network::URLLoaderCompletionStatus& status) override {
+ if (cancel_on_receive_response_)
+ return;
+ completion_status_ = status;
+ complete_ = true;
+ }
+
+ std::string data() { return data_; }
+ bool received_response() { return received_response_; }
+ bool complete() { return complete_; }
+ net::LoadTimingInfo last_load_timing() { return last_load_timing_; }
+ network::URLLoaderCompletionStatus completion_status() {
+ return completion_status_;
+ }
+
+ void SetCancelOnReceiveResponse(bool cancel_on_receive_response) {
+ cancel_on_receive_response_ = cancel_on_receive_response;
+ }
+
+ private:
+ // Data received. If downloading to file, remains empty.
+ std::string data_;
+
+ bool received_response_ = false;
+ bool complete_ = false;
+ bool cancel_on_receive_response_ = false;
+ net::LoadTimingInfo last_load_timing_;
+ network::URLLoaderCompletionStatus completion_status_;
+ WebResourceRequestSender* resource_request_sender_ = nullptr;
+}; // namespace blink
+
+// Sets up the message sender override for the unit test.
+class WebResourceRequestSenderTest : public testing::Test,
+ public network::mojom::URLLoaderFactory {
+ public:
+ explicit WebResourceRequestSenderTest()
+ : platform_(&delegate_),
+ resource_request_sender_(new WebResourceRequestSender()) {}
+
+ ~WebResourceRequestSenderTest() override {
+ resource_request_sender_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void CreateLoaderAndStart(
+ mojo::PendingReceiver<network::mojom::URLLoader> receiver,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+ const net::MutableNetworkTrafficAnnotationTag& annotation) override {
+ loader_and_clients_.emplace_back(std::move(receiver), std::move(client));
+ }
+
+ void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
+ override {
+ NOTREACHED();
+ }
+
+ void CallOnReceiveResponse(network::mojom::URLLoaderClient* client) {
+ auto head = network::mojom::URLResponseHead::New();
+ std::string raw_headers(kTestPageHeaders);
+ std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
+ head->headers = new net::HttpResponseHeaders(raw_headers);
+ head->mime_type = kTestPageMimeType;
+ head->charset = kTestPageCharset;
+ client->OnReceiveResponse(std::move(head));
+ }
+
+ std::unique_ptr<network::ResourceRequest> CreateResourceRequest() {
+ std::unique_ptr<network::ResourceRequest> request(
+ new network::ResourceRequest());
+
+ request->method = "GET";
+ request->url = GURL(kTestPageUrl);
+ request->site_for_cookies =
+ net::SiteForCookies::FromUrl(GURL(kTestPageUrl));
+ request->referrer_policy = ReferrerUtils::GetDefaultNetReferrerPolicy();
+ request->resource_type =
+ static_cast<int>(mojom::ResourceType::kSubResource);
+ request->priority = net::LOW;
+ request->mode = network::mojom::RequestMode::kNoCors;
+
+ auto url_request_extra_data =
+ base::MakeRefCounted<WebURLRequestExtraData>();
+ url_request_extra_data->CopyToResourceRequest(request.get());
+
+ return request;
+ }
+
+ WebResourceRequestSender* sender() { return resource_request_sender_.get(); }
+
+ void StartAsync(std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebRequestPeer> peer) {
+ sender()->SendAsync(
+ std::move(request), 0, scheduler::GetSingleThreadTaskRunnerForTesting(),
+ TRAFFIC_ANNOTATION_FOR_TESTS, false, WebVector<WebString>(),
+ std::move(peer),
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(this),
+ std::vector<std::unique_ptr<URLLoaderThrottle>>(),
+ std::make_unique<ResourceLoadInfoNotifierWrapper>(
+ /*resource_load_info_notifier=*/nullptr),
+ WebBackForwardCacheLoaderHelper());
+ }
+
+ static MojoCreateDataPipeOptions DataPipeOptions() {
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = kDataPipeCapacity;
+ return options;
+ }
+
+ class TestPlatform final : public TestingPlatformSupport {
+ public:
+ explicit TestPlatform(WebResourceRequestSenderDelegate* delegate)
+ : delegate_(delegate) {}
+ WebResourceRequestSenderDelegate* GetResourceRequestSenderDelegate()
+ override {
+ return delegate_;
+ }
+
+ private:
+ WebResourceRequestSenderDelegate* delegate_;
+ };
+
+ protected:
+ std::vector<std::pair<mojo::PendingReceiver<network::mojom::URLLoader>,
+ mojo::PendingRemote<network::mojom::URLLoaderClient>>>
+ loader_and_clients_;
+ TestResourceRequestSenderDelegate delegate_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ ScopedTestingPlatformSupport<TestPlatform, WebResourceRequestSenderDelegate*>
+ platform_;
+ std::unique_ptr<WebResourceRequestSender> resource_request_sender_;
+
+ scoped_refptr<MockRequestPeer> mock_peer_;
+};
+
+// Tests the generation of unique request ids.
+TEST_F(WebResourceRequestSenderTest, MakeRequestID) {
+ int first_id = WebResourceRequestSender::MakeRequestID();
+ int second_id = WebResourceRequestSender::MakeRequestID();
+
+ // Child process ids are unique (per process) and counting from 0 upwards:
+ EXPECT_GT(second_id, first_id);
+ EXPECT_GE(first_id, 0);
+}
+
+TEST_F(WebResourceRequestSenderTest, DelegateTest) {
+ std::unique_ptr<network::ResourceRequest> request(CreateResourceRequest());
+ mock_peer_ =
+ base::MakeRefCounted<MockRequestPeer>(resource_request_sender_.get());
+ StartAsync(std::move(request), mock_peer_);
+
+ ASSERT_EQ(1u, loader_and_clients_.size());
+ mojo::Remote<network::mojom::URLLoaderClient> client(
+ std::move(loader_and_clients_[0].second));
+ loader_and_clients_.clear();
+
+ // The wrapper eats all messages until RequestComplete message is sent.
+ CallOnReceiveResponse(client.get());
+
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ auto options = DataPipeOptions();
+ ASSERT_EQ(mojo::CreateDataPipe(&options, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ client->OnStartLoadingResponseBody(std::move(consumer_handle));
+
+ uint32_t size = strlen(kTestPageContents);
+ auto result = producer_handle->WriteData(kTestPageContents, &size,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ ASSERT_EQ(result, MOJO_RESULT_OK);
+ ASSERT_EQ(size, strlen(kTestPageContents));
+
+ producer_handle.reset();
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(mock_peer_->received_response());
+
+ // This lets the wrapper peer pass all the messages to the original
+ // peer at once.
+ network::URLLoaderCompletionStatus status;
+ status.error_code = net::OK;
+ status.exists_in_cache = false;
+ status.encoded_data_length = strlen(kTestPageContents);
+ client->OnComplete(status);
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(mock_peer_->received_response());
+ EXPECT_EQ(kTestPageContents, mock_peer_->data());
+ EXPECT_TRUE(mock_peer_->complete());
+}
+
+TEST_F(WebResourceRequestSenderTest, CancelDuringCallbackWithWrapperPeer) {
+ std::unique_ptr<network::ResourceRequest> request(CreateResourceRequest());
+ mock_peer_ =
+ base::MakeRefCounted<MockRequestPeer>(resource_request_sender_.get());
+ mock_peer_->SetCancelOnReceiveResponse(true);
+ StartAsync(std::move(request), mock_peer_);
+
+ ASSERT_EQ(1u, loader_and_clients_.size());
+ mojo::Remote<network::mojom::URLLoaderClient> client(
+ std::move(loader_and_clients_[0].second));
+ loader_and_clients_.clear();
+
+ CallOnReceiveResponse(client.get());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ auto options = DataPipeOptions();
+ ASSERT_EQ(mojo::CreateDataPipe(&options, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ client->OnStartLoadingResponseBody(std::move(consumer_handle));
+ uint32_t size = strlen(kTestPageContents);
+ auto result = producer_handle->WriteData(kTestPageContents, &size,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ ASSERT_EQ(result, MOJO_RESULT_OK);
+ ASSERT_EQ(size, strlen(kTestPageContents));
+ producer_handle.reset();
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(mock_peer_->received_response());
+
+ // This lets the wrapper peer pass all the messages to the original
+ // peer at once, but the original peer cancels right after it receives
+ // the response. (This will remove pending request info from
+ // WebResourceRequestSender while the wrapper peer is still running
+ // OnCompletedRequest, but it should not lead to crashes.)
+ network::URLLoaderCompletionStatus status;
+ status.error_code = net::OK;
+ status.exists_in_cache = false;
+ status.encoded_data_length = strlen(kTestPageContents);
+ client->OnComplete(status);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(mock_peer_->received_response());
+ // Request should have been cancelled with no additional messages.
+ // EXPECT_TRUE(peer_context.cancelled);
+ EXPECT_EQ("", mock_peer_->data());
+ EXPECT_FALSE(mock_peer_->complete());
+}
+
+class TimeConversionTest : public WebResourceRequestSenderTest {
+ public:
+ void PerformTest(network::mojom::URLResponseHeadPtr response_head) {
+ std::unique_ptr<network::ResourceRequest> request(CreateResourceRequest());
+ StartAsync(std::move(request), mock_peer_);
+
+ ASSERT_EQ(1u, loader_and_clients_.size());
+ mojo::Remote<network::mojom::URLLoaderClient> client(
+ std::move(loader_and_clients_[0].second));
+ loader_and_clients_.clear();
+ client->OnReceiveResponse(std::move(response_head));
+ }
+
+ const network::mojom::URLResponseHead& response_info() const {
+ return *response_info_;
+ }
+
+ private:
+ network::mojom::URLResponseHeadPtr response_info_ =
+ network::mojom::URLResponseHead::New();
+};
+
+// TODO(simonjam): Enable this when 10829031 lands.
+TEST_F(TimeConversionTest, DISABLED_ProperlyInitialized) {
+ auto response_head = network::mojom::URLResponseHead::New();
+ response_head->request_start = TicksFromMicroseconds(5);
+ response_head->response_start = TicksFromMicroseconds(15);
+ response_head->load_timing.request_start_time = base::Time::Now();
+ response_head->load_timing.request_start = TicksFromMicroseconds(10);
+ response_head->load_timing.connect_timing.connect_start =
+ TicksFromMicroseconds(13);
+
+ auto request_start = response_head->load_timing.request_start;
+ PerformTest(std::move(response_head));
+
+ EXPECT_LT(base::TimeTicks(), response_info().load_timing.request_start);
+ EXPECT_EQ(base::TimeTicks(),
+ response_info().load_timing.connect_timing.dns_start);
+ EXPECT_LE(request_start,
+ response_info().load_timing.connect_timing.connect_start);
+}
+
+TEST_F(TimeConversionTest, PartiallyInitialized) {
+ auto response_head = network::mojom::URLResponseHead::New();
+ response_head->request_start = TicksFromMicroseconds(5);
+ response_head->response_start = TicksFromMicroseconds(15);
+
+ PerformTest(std::move(response_head));
+
+ EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
+ EXPECT_EQ(base::TimeTicks(),
+ response_info().load_timing.connect_timing.dns_start);
+}
+
+TEST_F(TimeConversionTest, NotInitialized) {
+ auto response_head = network::mojom::URLResponseHead::New();
+
+ PerformTest(std::move(response_head));
+
+ EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
+ EXPECT_EQ(base::TimeTicks(),
+ response_info().load_timing.connect_timing.dns_start);
+}
+
+class CompletionTimeConversionTest : public WebResourceRequestSenderTest {
+ public:
+ void PerformTest(base::TimeTicks remote_request_start,
+ base::TimeTicks completion_time,
+ base::TimeDelta delay) {
+ std::unique_ptr<network::ResourceRequest> request(CreateResourceRequest());
+ mock_peer_ =
+ base::MakeRefCounted<MockRequestPeer>(resource_request_sender_.get());
+ StartAsync(std::move(request), mock_peer_);
+
+ ASSERT_EQ(1u, loader_and_clients_.size());
+ mojo::Remote<network::mojom::URLLoaderClient> client(
+ std::move(loader_and_clients_[0].second));
+ auto response_head = network::mojom::URLResponseHead::New();
+ response_head->request_start = remote_request_start;
+ response_head->load_timing.request_start = remote_request_start;
+ response_head->load_timing.receive_headers_end = remote_request_start;
+ // We need to put something non-null time, otherwise no values will be
+ // copied.
+ response_head->load_timing.request_start_time =
+ base::Time() + base::TimeDelta::FromSeconds(99);
+ client->OnReceiveResponse(std::move(response_head));
+
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ client->OnStartLoadingResponseBody(std::move(consumer_handle));
+ producer_handle.reset(); // The response is empty.
+
+ network::URLLoaderCompletionStatus status;
+ status.completion_time = completion_time;
+
+ client->OnComplete(status);
+
+ const base::TimeTicks until = base::TimeTicks::Now() + delay;
+ while (base::TimeTicks::Now() < until)
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
+ base::RunLoop().RunUntilIdle();
+ loader_and_clients_.clear();
+ }
+
+ base::TimeTicks request_start() const {
+ EXPECT_TRUE(mock_peer_->received_response());
+ return mock_peer_->last_load_timing().request_start;
+ }
+ base::TimeTicks completion_time() const {
+ EXPECT_TRUE(mock_peer_->complete());
+ return mock_peer_->completion_status().completion_time;
+ }
+};
+
+TEST_F(CompletionTimeConversionTest, NullCompletionTimestamp) {
+ const auto remote_request_start =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(4);
+
+ PerformTest(remote_request_start, base::TimeTicks(), base::TimeDelta());
+
+ EXPECT_EQ(base::TimeTicks(), completion_time());
+}
+
+TEST_F(CompletionTimeConversionTest, RemoteRequestStartIsUnavailable) {
+ base::TimeTicks begin = base::TimeTicks::Now();
+
+ const auto remote_completion_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(8);
+
+ PerformTest(base::TimeTicks(), remote_completion_time, base::TimeDelta());
+
+ base::TimeTicks end = base::TimeTicks::Now();
+ EXPECT_LE(begin, completion_time());
+ EXPECT_LE(completion_time(), end);
+}
+
+TEST_F(CompletionTimeConversionTest, Convert) {
+ const auto remote_request_start =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(4);
+
+ const auto remote_completion_time =
+ remote_request_start + base::TimeDelta::FromMilliseconds(3);
+
+ PerformTest(remote_request_start, remote_completion_time,
+ base::TimeDelta::FromMilliseconds(15));
+
+ EXPECT_EQ(completion_time(),
+ request_start() + base::TimeDelta::FromMilliseconds(3));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
new file mode 100644
index 00000000000..bfd4e078fef
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
@@ -0,0 +1,1172 @@
+// Copyright 2014 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 "third_party/blink/public/platform/web_url_loader.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/auto_reset.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/check_op.h"
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/files/file_path.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/notreached.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "net/base/filename_util.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/cert/cert_status_flags.h"
+#include "net/cert/ct_sct_to_string.h"
+#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/ssl/ssl_cipher_suite_names.h"
+#include "net/ssl/ssl_connection_status_flags.h"
+#include "net/ssl/ssl_info.h"
+#include "services/network/public/cpp/http_raw_request_response_info.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
+#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
+#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/loader/mime_sniffing_throttle.h"
+#include "third_party/blink/public/common/loader/previews_state.h"
+#include "third_party/blink/public/common/loader/referrer_utils.h"
+#include "third_party/blink/public/common/loader/resource_type_util.h"
+#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/blink/public/common/net/ip_address_space_util.h"
+#include "third_party/blink/public/common/security/security_style.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
+#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
+#include "third_party/blink/public/platform/url_conversion.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_http_load_info.h"
+#include "third_party/blink/public/platform/web_request_peer.h"
+#include "third_party/blink/public/platform/web_resource_request_sender.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_url_error.h"
+#include "third_party/blink/public/platform/web_url_loader_client.h"
+#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/platform/web_url_request_extra_data.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_security_policy.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
+#include "url/origin.h"
+
+using base::Time;
+using base::TimeTicks;
+using blink::scheduler::WebResourceLoadingTaskRunnerHandle;
+
+namespace blink {
+
+// Utilities -------------------------------------------------------------------
+
+namespace {
+
+// Converts timing data from |load_timing| to the mojo type.
+network::mojom::LoadTimingInfo ToMojoLoadTiming(
+ const net::LoadTimingInfo& load_timing) {
+ DCHECK(!load_timing.request_start.is_null());
+
+ return network::mojom::LoadTimingInfo(
+ load_timing.socket_reused, load_timing.socket_log_id,
+ load_timing.request_start_time, load_timing.request_start,
+ load_timing.proxy_resolve_start, load_timing.proxy_resolve_end,
+ load_timing.connect_timing, load_timing.send_start, load_timing.send_end,
+ load_timing.receive_headers_start, load_timing.receive_headers_end,
+ load_timing.receive_non_informational_headers_start,
+ load_timing.first_early_hints_time, load_timing.push_start,
+ load_timing.push_end, load_timing.service_worker_start_time,
+ load_timing.service_worker_ready_time,
+ load_timing.service_worker_fetch_start,
+ load_timing.service_worker_respond_with_settled);
+}
+
+// This is complementary to ConvertNetPriorityToWebKitPriority, defined in
+// service_worker_context_client.cc.
+// TODO(yhirano): Move this to blink/platform/loader.
+net::RequestPriority ConvertWebKitPriorityToNetPriority(
+ const WebURLRequest::Priority& priority) {
+ switch (priority) {
+ case WebURLRequest::Priority::kVeryHigh:
+ return net::HIGHEST;
+
+ case WebURLRequest::Priority::kHigh:
+ return net::MEDIUM;
+
+ case WebURLRequest::Priority::kMedium:
+ return net::LOW;
+
+ case WebURLRequest::Priority::kLow:
+ return net::LOWEST;
+
+ case WebURLRequest::Priority::kVeryLow:
+ return net::IDLE;
+
+ case WebURLRequest::Priority::kUnresolved:
+ default:
+ NOTREACHED();
+ return net::LOW;
+ }
+}
+
+// Convert a net::SignedCertificateTimestampAndStatus object to a
+// WebURLResponse::SignedCertificateTimestamp object.
+WebURLResponse::SignedCertificateTimestamp NetSCTToBlinkSCT(
+ const net::SignedCertificateTimestampAndStatus& sct_and_status) {
+ return WebURLResponse::SignedCertificateTimestamp(
+ WebString::FromASCII(net::ct::StatusToString(sct_and_status.status)),
+ WebString::FromASCII(net::ct::OriginToString(sct_and_status.sct->origin)),
+ WebString::FromUTF8(sct_and_status.sct->log_description),
+ WebString::FromASCII(
+ base::HexEncode(sct_and_status.sct->log_id.c_str(),
+ sct_and_status.sct->log_id.length())),
+ sct_and_status.sct->timestamp.ToJavaTime(),
+ WebString::FromASCII(net::ct::HashAlgorithmToString(
+ sct_and_status.sct->signature.hash_algorithm)),
+ WebString::FromASCII(net::ct::SignatureAlgorithmToString(
+ sct_and_status.sct->signature.signature_algorithm)),
+ WebString::FromASCII(base::HexEncode(
+ sct_and_status.sct->signature.signature_data.c_str(),
+ sct_and_status.sct->signature.signature_data.length())));
+}
+
+WebString CryptoBufferAsWebString(const CRYPTO_BUFFER* buffer) {
+ base::StringPiece sp = net::x509_util::CryptoBufferAsStringPiece(buffer);
+ return WebString::FromLatin1(reinterpret_cast<const WebLChar*>(sp.begin()),
+ sp.size());
+}
+
+void SetSecurityStyleAndDetails(const GURL& url,
+ const network::mojom::URLResponseHead& head,
+ WebURLResponse* response,
+ bool report_security_info) {
+ if (!report_security_info) {
+ response->SetSecurityStyle(SecurityStyle::kUnknown);
+ return;
+ }
+ if (!url.SchemeIsCryptographic()) {
+ // Some origins are considered secure even though they're not cryptographic,
+ // so treat them as secure in the UI.
+ if (network::IsUrlPotentiallyTrustworthy(url))
+ response->SetSecurityStyle(SecurityStyle::kSecure);
+ else
+ response->SetSecurityStyle(SecurityStyle::kInsecure);
+ return;
+ }
+
+ // The resource loader does not provide a guarantee that requests always have
+ // security info (such as a certificate) attached. Use SecurityStyleUnknown
+ // in this case where there isn't enough information to be useful.
+ if (!head.ssl_info.has_value()) {
+ response->SetSecurityStyle(SecurityStyle::kUnknown);
+ return;
+ }
+
+ const net::SSLInfo& ssl_info = *head.ssl_info;
+
+ const char* protocol = "";
+ const char* key_exchange = "";
+ const char* cipher = "";
+ const char* mac = "";
+ const char* key_exchange_group = "";
+
+ if (ssl_info.connection_status) {
+ int ssl_version =
+ net::SSLConnectionStatusToVersion(ssl_info.connection_status);
+ net::SSLVersionToString(&protocol, ssl_version);
+
+ bool is_aead;
+ bool is_tls13;
+ uint16_t cipher_suite =
+ net::SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
+ net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead,
+ &is_tls13, cipher_suite);
+ if (!key_exchange) {
+ DCHECK(is_tls13);
+ key_exchange = "";
+ }
+
+ if (!mac) {
+ DCHECK(is_aead);
+ mac = "";
+ }
+
+ if (ssl_info.key_exchange_group != 0) {
+ // Historically the field was named 'curve' rather than 'group'.
+ key_exchange_group = SSL_get_curve_name(ssl_info.key_exchange_group);
+ if (!key_exchange_group) {
+ NOTREACHED();
+ key_exchange_group = "";
+ }
+ }
+ }
+
+ if (net::IsCertStatusError(head.cert_status)) {
+ response->SetSecurityStyle(SecurityStyle::kInsecure);
+ } else {
+ response->SetSecurityStyle(SecurityStyle::kSecure);
+ }
+
+ WebURLResponse::SignedCertificateTimestampList sct_list(
+ ssl_info.signed_certificate_timestamps.size());
+
+ for (size_t i = 0; i < sct_list.size(); ++i)
+ sct_list[i] = NetSCTToBlinkSCT(ssl_info.signed_certificate_timestamps[i]);
+
+ if (!ssl_info.cert) {
+ NOTREACHED();
+ response->SetSecurityStyle(SecurityStyle::kUnknown);
+ return;
+ }
+
+ std::vector<std::string> san_dns;
+ std::vector<std::string> san_ip;
+ ssl_info.cert->GetSubjectAltName(&san_dns, &san_ip);
+ WebVector<WebString> web_san(san_dns.size() + san_ip.size());
+ std::transform(san_dns.begin(), san_dns.end(), web_san.begin(),
+ [](const std::string& h) { return WebString::FromLatin1(h); });
+ std::transform(san_ip.begin(), san_ip.end(), web_san.begin() + san_dns.size(),
+ [](const std::string& h) {
+ net::IPAddress ip(reinterpret_cast<const uint8_t*>(h.data()),
+ h.size());
+ return WebString::FromLatin1(ip.ToString());
+ });
+
+ WebVector<WebString> web_cert;
+ web_cert.reserve(ssl_info.cert->intermediate_buffers().size() + 1);
+ web_cert.emplace_back(CryptoBufferAsWebString(ssl_info.cert->cert_buffer()));
+ for (const auto& cert : ssl_info.cert->intermediate_buffers())
+ web_cert.emplace_back(CryptoBufferAsWebString(cert.get()));
+
+ WebURLResponse::WebSecurityDetails webSecurityDetails(
+ WebString::FromASCII(protocol), WebString::FromASCII(key_exchange),
+ WebString::FromASCII(key_exchange_group), WebString::FromASCII(cipher),
+ WebString::FromASCII(mac),
+ WebString::FromUTF8(ssl_info.cert->subject().common_name), web_san,
+ WebString::FromUTF8(ssl_info.cert->issuer().common_name),
+ ssl_info.cert->valid_start().ToDoubleT(),
+ ssl_info.cert->valid_expiry().ToDoubleT(), web_cert, sct_list);
+
+ response->SetSecurityDetails(webSecurityDetails);
+}
+
+bool IsBannedCrossSiteAuth(
+ network::ResourceRequest* resource_request,
+ WebURLRequestExtraData* passed_url_request_extra_data) {
+ auto& request_url = resource_request->url;
+ auto& first_party = resource_request->site_for_cookies;
+
+ bool allow_cross_origin_auth_prompt = false;
+ if (passed_url_request_extra_data) {
+ WebURLRequestExtraData* url_request_extra_data =
+ static_cast<WebURLRequestExtraData*>(passed_url_request_extra_data);
+ allow_cross_origin_auth_prompt =
+ url_request_extra_data->allow_cross_origin_auth_prompt();
+ }
+
+ if (first_party.IsFirstPartyWithSchemefulMode(
+ request_url, /*compute_schemefully=*/false)) {
+ // If the first party is secure but the subresource is not, this is
+ // mixed-content. Do not allow the image.
+ if (!allow_cross_origin_auth_prompt &&
+ network::IsUrlPotentiallyTrustworthy(first_party.RepresentativeUrl()) &&
+ !network::IsUrlPotentiallyTrustworthy(request_url)) {
+ return true;
+ }
+ return false;
+ }
+
+ return !allow_cross_origin_auth_prompt;
+}
+
+} // namespace
+
+// This inner class exists since the WebURLLoader may be deleted while inside a
+// call to WebURLLoaderClient. Refcounting is to keep the context from
+// being deleted if it may have work to do after calling into the client.
+class WebURLLoader::Context : public WebRequestPeer {
+ public:
+ Context(WebURLLoader* loader,
+ const WebVector<WebString>& cors_exempt_header_list,
+ base::WaitableEvent* terminate_sync_load_event,
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ freezable_task_runner_handle,
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ unfreezable_task_runner_handle,
+ scoped_refptr<network::SharedURLLoaderFactory> factory,
+ mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper);
+
+ int request_id() const { return request_id_; }
+ WebURLLoaderClient* client() const { return client_; }
+ void set_client(WebURLLoaderClient* client) { client_ = client; }
+ scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner() {
+ return freezable_task_runner_;
+ }
+ scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner() {
+ return unfreezable_task_runner_;
+ }
+
+ void Cancel();
+ void SetDefersLoading(WebURLLoader::DeferType value);
+ void DidChangePriority(WebURLRequest::Priority new_priority,
+ int intra_priority_value);
+ void Start(std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
+ int requestor_id,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ SyncLoadResponse* sync_load_response,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper);
+
+ // WebRequestPeer overrides:
+ void OnUploadProgress(uint64_t position, uint64_t size) override;
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head,
+ std::vector<std::string>* removed_headers) override;
+ void OnReceivedResponse(network::mojom::URLResponseHeadPtr head) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override;
+ void OnTransferSizeUpdated(int transfer_size_diff) override;
+ void OnReceivedCachedMetadata(mojo_base::BigBuffer data) override;
+ void OnCompletedRequest(
+ const network::URLLoaderCompletionStatus& status) override;
+
+ void SetResourceRequestSenderForTesting( // IN-TEST
+ std::unique_ptr<WebResourceRequestSender> resource_request_sender);
+
+ private:
+ // The maximal number of bytes consumed in a task. When there are more bytes
+ // in the data pipe, they will be consumed in following tasks. Setting a too
+ // small number will generate ton of tasks but setting a too large number will
+ // lead to thread janks. Also, some clients cannot handle too large chunks
+ // (512k for example).
+ static constexpr uint32_t kMaxNumConsumedBytesInTask = 64 * 1024;
+
+ ~Context() override;
+
+ // Called when the body data stream is detached from the reader side.
+ void CancelBodyStreaming();
+
+ void OnBodyAvailable(MojoResult, const mojo::HandleSignalsState&);
+ void OnBodyHasBeenRead(uint32_t read_bytes);
+
+ static net::NetworkTrafficAnnotationTag GetTrafficAnnotationTag(
+ network::ResourceRequest* request);
+
+ WebURLLoader* loader_;
+
+ KURL url_;
+ // Controls SetSecurityStyleAndDetails() in PopulateURLResponse(). Initially
+ // set to WebURLRequest::ReportRawHeaders() in Start() and gets updated in
+ // WillFollowRedirect() (by the InspectorNetworkAgent) while the new
+ // ReportRawHeaders() value won't be propagated to the browser process.
+ //
+ // TODO(tyoshino): Investigate whether it's worth propagating the new value.
+ bool report_raw_headers_;
+
+ WebURLLoaderClient* client_;
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ freezable_task_runner_handle_;
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ unfreezable_task_runner_handle_;
+ scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner_;
+ mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle_;
+ WebURLLoader::DeferType defers_loading_;
+ const WebVector<WebString> cors_exempt_header_list_;
+ base::WaitableEvent* terminate_sync_load_event_;
+
+ int request_id_;
+ bool in_two_phase_read_ = false;
+ bool is_in_on_body_available_ = false;
+
+ base::Optional<network::URLLoaderCompletionStatus> completion_status_;
+
+ std::unique_ptr<WebResourceRequestSender> resource_request_sender_;
+
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper_;
+};
+
+// WebURLLoader::Context -------------------------------------------------------
+
+// static
+constexpr uint32_t WebURLLoader::Context::kMaxNumConsumedBytesInTask;
+
+WebURLLoader::Context::Context(
+ WebURLLoader* loader,
+ const WebVector<WebString>& cors_exempt_header_list,
+ base::WaitableEvent* terminate_sync_load_event,
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ freezable_task_runner_handle,
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ unfreezable_task_runner_handle,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
+ : loader_(loader),
+ report_raw_headers_(false),
+ client_(nullptr),
+ freezable_task_runner_handle_(std::move(freezable_task_runner_handle)),
+ unfreezable_task_runner_handle_(
+ std::move(unfreezable_task_runner_handle)),
+ freezable_task_runner_(freezable_task_runner_handle_->GetTaskRunner()),
+ unfreezable_task_runner_(
+ unfreezable_task_runner_handle_->GetTaskRunner()),
+ keep_alive_handle_(std::move(keep_alive_handle)),
+ defers_loading_(WebURLLoader::DeferType::kNotDeferred),
+ cors_exempt_header_list_(cors_exempt_header_list),
+ terminate_sync_load_event_(terminate_sync_load_event),
+ request_id_(-1),
+ resource_request_sender_(std::make_unique<WebResourceRequestSender>()),
+ url_loader_factory_(std::move(url_loader_factory)),
+ back_forward_cache_loader_helper_(back_forward_cache_loader_helper) {
+ DCHECK(url_loader_factory_);
+}
+
+void WebURLLoader::Context::Cancel() {
+ TRACE_EVENT_WITH_FLOW0("loading", "WebURLLoader::Context::Cancel", this,
+ TRACE_EVENT_FLAG_FLOW_IN);
+ if (request_id_ != -1) {
+ resource_request_sender_->Cancel(freezable_task_runner_);
+ request_id_ = -1;
+ }
+
+ // Do not make any further calls to the client.
+ client_ = nullptr;
+ loader_ = nullptr;
+}
+
+void WebURLLoader::Context::SetDefersLoading(WebURLLoader::DeferType value) {
+ if (request_id_ != -1)
+ resource_request_sender_->SetDefersLoading(value);
+ defers_loading_ = value;
+}
+
+void WebURLLoader::Context::DidChangePriority(
+ WebURLRequest::Priority new_priority,
+ int intra_priority_value) {
+ if (request_id_ != -1) {
+ net::RequestPriority net_priority =
+ ConvertWebKitPriorityToNetPriority(new_priority);
+ resource_request_sender_->DidChangePriority(net_priority,
+ intra_priority_value);
+ freezable_task_runner_handle_->DidChangeRequestPriority(net_priority);
+ }
+}
+
+void WebURLLoader::Context::Start(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequestExtraData> passed_url_request_extra_data,
+ int requestor_id,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ SyncLoadResponse* sync_load_response,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper) {
+ DCHECK_EQ(request_id_, -1);
+
+ // Notify Blink's scheduler with the initial resource fetch priority.
+ freezable_task_runner_handle_->DidChangeRequestPriority(request->priority);
+
+ url_ = KURL(request->url);
+ report_raw_headers_ = request->report_raw_headers;
+
+ // TODO(horo): Check credentials flag is unset when credentials mode is omit.
+ // Check credentials flag is set when credentials mode is include.
+
+ const network::mojom::RequestDestination request_destination =
+ request->destination;
+
+ // TODO(yhirano): Move the logic below to blink/platform/loader.
+ if (!request->is_favicon &&
+ request_destination == network::mojom::RequestDestination::kImage &&
+ IsBannedCrossSiteAuth(request.get(),
+ passed_url_request_extra_data.get())) {
+ // Prevent third-party image content from prompting for login, as this
+ // is often a scam to extract credentials for another domain from the
+ // user. Only block image loads, as the attack applies largely to the
+ // "src" property of the <img> tag. It is common for web properties to
+ // allow untrusted values for <img src>; this is considered a fair thing
+ // for an HTML sanitizer to do. Conversely, any HTML sanitizer that didn't
+ // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags
+ // would be considered vulnerable in and of itself.
+ request->do_not_prompt_for_login = true;
+ request->load_flags |= net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
+ }
+
+ scoped_refptr<WebURLRequestExtraData> empty_url_request_extra_data;
+ WebURLRequestExtraData* url_request_extra_data;
+ if (passed_url_request_extra_data) {
+ url_request_extra_data = static_cast<WebURLRequestExtraData*>(
+ passed_url_request_extra_data.get());
+ } else {
+ empty_url_request_extra_data =
+ base::MakeRefCounted<WebURLRequestExtraData>();
+ url_request_extra_data = empty_url_request_extra_data.get();
+ }
+ url_request_extra_data->CopyToResourceRequest(request.get());
+
+ if (request->load_flags & net::LOAD_PREFETCH)
+ request->corb_detachable = true;
+
+ auto throttles =
+ url_request_extra_data->TakeURLLoaderThrottles().ReleaseVector();
+ // The frame request blocker is only for a frame's subresources.
+ if (url_request_extra_data->frame_request_blocker() &&
+ !IsRequestDestinationFrame(request_destination)) {
+ auto throttle = url_request_extra_data->frame_request_blocker()
+ ->GetThrottleIfRequestsBlocked();
+ if (throttle)
+ throttles.push_back(std::move(throttle));
+ }
+
+ // TODO(minggang): Remove the useage of render frame id.
+ Platform::Current()->AppendVariationsThrottles(request->render_frame_id,
+ &throttles);
+
+ uint32_t loader_options = network::mojom::kURLLoadOptionNone;
+ if (!no_mime_sniffing) {
+ loader_options |= network::mojom::kURLLoadOptionSniffMimeType;
+ throttles.push_back(
+ std::make_unique<MimeSniffingThrottle>(unfreezable_task_runner_));
+ }
+
+ if (sync_load_response) {
+ DCHECK(defers_loading_ == WebURLLoader::DeferType::kNotDeferred);
+
+ loader_options |= network::mojom::kURLLoadOptionSynchronous;
+ request->load_flags |= net::LOAD_IGNORE_LIMITS;
+
+ mojo::PendingRemote<mojom::BlobRegistry> download_to_blob_registry;
+ if (pass_response_pipe_to_client) {
+ Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
+ download_to_blob_registry.InitWithNewPipeAndPassReceiver());
+ }
+ net::NetworkTrafficAnnotationTag tag =
+ GetTrafficAnnotationTag(request.get());
+ resource_request_sender_->SendSync(
+ std::move(request), requestor_id, tag, loader_options,
+ sync_load_response, url_loader_factory_, std::move(throttles),
+ timeout_interval, cors_exempt_header_list_, terminate_sync_load_event_,
+ std::move(download_to_blob_registry), base::WrapRefCounted(this),
+ std::move(resource_load_info_notifier_wrapper),
+ back_forward_cache_loader_helper_);
+ return;
+ }
+
+ TRACE_EVENT_WITH_FLOW0("loading", "WebURLLoader::Context::Start", this,
+ TRACE_EVENT_FLAG_FLOW_OUT);
+ net::NetworkTrafficAnnotationTag tag = GetTrafficAnnotationTag(request.get());
+ request_id_ = resource_request_sender_->SendAsync(
+ std::move(request), requestor_id, unfreezable_task_runner_, tag,
+ loader_options, cors_exempt_header_list_, base::WrapRefCounted(this),
+ url_loader_factory_, std::move(throttles),
+ std::move(resource_load_info_notifier_wrapper),
+ back_forward_cache_loader_helper_);
+
+ if (defers_loading_ != WebURLLoader::DeferType::kNotDeferred) {
+ resource_request_sender_->SetDefersLoading(
+ WebURLLoader::DeferType::kDeferred);
+ }
+}
+
+void WebURLLoader::Context::OnUploadProgress(uint64_t position, uint64_t size) {
+ if (client_)
+ client_->DidSendData(position, size);
+}
+
+bool WebURLLoader::Context::OnReceivedRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head,
+ std::vector<std::string>* removed_headers) {
+ if (!client_)
+ return false;
+
+ TRACE_EVENT_WITH_FLOW0("loading", "WebURLLoader::Context::OnReceivedRedirect",
+ this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
+ WebURLResponse response;
+ PopulateURLResponse(url_, *head, &response, report_raw_headers_, request_id_);
+
+ url_ = KURL(redirect_info.new_url);
+ return client_->WillFollowRedirect(
+ url_, redirect_info.new_site_for_cookies,
+ WebString::FromUTF8(redirect_info.new_referrer),
+ ReferrerUtils::NetToMojoReferrerPolicy(redirect_info.new_referrer_policy),
+ WebString::FromUTF8(redirect_info.new_method), response,
+ report_raw_headers_, removed_headers);
+}
+
+void WebURLLoader::Context::OnReceivedResponse(
+ network::mojom::URLResponseHeadPtr head) {
+ if (!client_)
+ return;
+
+ TRACE_EVENT_WITH_FLOW0("loading", "WebURLLoader::Context::OnReceivedResponse",
+ this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
+ // These headers must be stripped off before entering into the renderer
+ // (see also https://crbug.com/1019732).
+ DCHECK(!head->headers || !head->headers->HasHeader("set-cookie"));
+ DCHECK(!head->headers || !head->headers->HasHeader("set-cookie2"));
+ DCHECK(!head->headers || !head->headers->HasHeader("clear-site-data"));
+
+ WebURLResponse response;
+ PopulateURLResponse(url_, *head, &response, report_raw_headers_, request_id_);
+
+ client_->DidReceiveResponse(response);
+
+ // DidReceiveResponse() may have triggered a cancel, causing the |client_| to
+ // go away.
+ if (!client_)
+ return;
+}
+
+void WebURLLoader::Context::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ if (client_)
+ client_->DidStartLoadingResponseBody(std::move(body));
+
+ TRACE_EVENT_WITH_FLOW0(
+ "loading", "WebURLLoader::Context::OnStartLoadingResponseBody", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+}
+
+void WebURLLoader::Context::OnTransferSizeUpdated(int transfer_size_diff) {
+ client_->DidReceiveTransferSizeUpdate(transfer_size_diff);
+}
+
+void WebURLLoader::Context::OnReceivedCachedMetadata(
+ mojo_base::BigBuffer data) {
+ if (!client_)
+ return;
+ TRACE_EVENT_WITH_FLOW1(
+ "loading", "WebURLLoader::Context::OnReceivedCachedMetadata", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "length",
+ data.size());
+ client_->DidReceiveCachedMetadata(std::move(data));
+}
+
+void WebURLLoader::Context::OnCompletedRequest(
+ const network::URLLoaderCompletionStatus& status) {
+ int64_t total_transfer_size = status.encoded_data_length;
+ int64_t encoded_body_size = status.encoded_body_length;
+
+ if (client_) {
+ TRACE_EVENT_WITH_FLOW0("loading",
+ "WebURLLoader::Context::OnCompletedRequest", this,
+ TRACE_EVENT_FLAG_FLOW_IN);
+
+ if (status.error_code != net::OK) {
+ client_->DidFail(PopulateURLError(status, url_), status.completion_time,
+ total_transfer_size, encoded_body_size,
+ status.decoded_body_length);
+ } else {
+ client_->DidFinishLoading(status.completion_time, total_transfer_size,
+ encoded_body_size, status.decoded_body_length,
+ status.should_report_corb_blocking);
+ }
+ }
+}
+
+WebURLLoader::Context::~Context() {
+ // We must be already cancelled at this point.
+ DCHECK_LT(request_id_, 0);
+}
+
+void WebURLLoader::Context::CancelBodyStreaming() {
+ scoped_refptr<Context> protect(this);
+
+ if (client_) {
+ // TODO(yhirano): Set |stale_copy_in_cache| appropriately if possible.
+ client_->DidFail(WebURLError(net::ERR_ABORTED, url_),
+ base::TimeTicks::Now(),
+ WebURLLoaderClient::kUnknownEncodedDataLength, 0, 0);
+ }
+
+ // Notify the browser process that the request is canceled.
+ Cancel();
+}
+
+// WebURLLoader ----------------------------------------------------------------
+
+WebURLLoader::WebURLLoader(
+ const WebVector<WebString>& cors_exempt_header_list,
+ base::WaitableEvent* terminate_sync_load_event,
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ freezable_task_runner_handle,
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ unfreezable_task_runner_handle,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
+ : context_(new Context(this,
+ cors_exempt_header_list,
+ terminate_sync_load_event,
+ std::move(freezable_task_runner_handle),
+ std::move(unfreezable_task_runner_handle),
+ std::move(url_loader_factory),
+ std::move(keep_alive_handle),
+ back_forward_cache_loader_helper)) {}
+
+WebURLLoader::WebURLLoader() = default;
+
+WebURLLoader::~WebURLLoader() {
+ Cancel();
+}
+
+void WebURLLoader::PopulateURLResponse(
+ const WebURL& url,
+ const network::mojom::URLResponseHead& head,
+ WebURLResponse* response,
+ bool report_security_info,
+ int request_id) {
+ response->SetCurrentRequestUrl(url);
+ response->SetResponseTime(head.response_time);
+ response->SetMimeType(WebString::FromUTF8(head.mime_type));
+ response->SetTextEncodingName(WebString::FromUTF8(head.charset));
+ response->SetExpectedContentLength(head.content_length);
+ response->SetHasMajorCertificateErrors(
+ net::IsCertStatusError(head.cert_status));
+ response->SetCTPolicyCompliance(head.ct_policy_compliance);
+ response->SetIsLegacyTLSVersion(head.is_legacy_tls_version);
+ response->SetHasRangeRequested(head.has_range_requested);
+ response->SetTimingAllowPassed(head.timing_allow_passed);
+ response->SetAppCacheID(head.appcache_id);
+ response->SetAppCacheManifestURL(KURL(head.appcache_manifest_url));
+ response->SetWasCached(!head.load_timing.request_start_time.is_null() &&
+ head.response_time <
+ head.load_timing.request_start_time);
+ response->SetConnectionID(head.load_timing.socket_log_id);
+ response->SetConnectionReused(head.load_timing.socket_reused);
+ response->SetWasFetchedViaSPDY(head.was_fetched_via_spdy);
+ response->SetWasFetchedViaServiceWorker(head.was_fetched_via_service_worker);
+ response->SetServiceWorkerResponseSource(head.service_worker_response_source);
+ response->SetWasFallbackRequiredByServiceWorker(
+ head.was_fallback_required_by_service_worker);
+ response->SetType(head.response_type);
+ response->SetPadding(head.padding);
+ WebVector<KURL> url_list_via_service_worker(
+ head.url_list_via_service_worker.size());
+ std::transform(head.url_list_via_service_worker.begin(),
+ head.url_list_via_service_worker.end(),
+ url_list_via_service_worker.begin(),
+ [](const GURL& h) { return KURL(h); });
+ response->SetUrlListViaServiceWorker(url_list_via_service_worker);
+ response->SetCacheStorageCacheName(
+ head.service_worker_response_source ==
+ network::mojom::FetchResponseSource::kCacheStorage
+ ? WebString::FromUTF8(head.cache_storage_cache_name)
+ : WebString());
+
+ WebVector<WebString> dns_aliases(head.dns_aliases.size());
+ std::transform(head.dns_aliases.begin(), head.dns_aliases.end(),
+ dns_aliases.begin(),
+ [](const std::string& h) { return WebString::FromASCII(h); });
+ response->SetDnsAliases(dns_aliases);
+ response->SetRemoteIPEndpoint(head.remote_endpoint);
+ // This computation can only be done once SetUrlListViaServiceWorker() has
+ // been called on |response|, so that ResponseUrl() returns the correct
+ // answer.
+ //
+ // Implements: https://wicg.github.io/cors-rfc1918/#integration-html
+ response->SetAddressSpace(CalculateResourceAddressSpace(
+ KURL(response->ResponseUrl()), head.remote_endpoint.address()));
+
+ WebVector<WebString> cors_exposed_header_names(
+ head.cors_exposed_header_names.size());
+ std::transform(head.cors_exposed_header_names.begin(),
+ head.cors_exposed_header_names.end(),
+ cors_exposed_header_names.begin(),
+ [](const std::string& h) { return WebString::FromLatin1(h); });
+ response->SetCorsExposedHeaderNames(cors_exposed_header_names);
+ response->SetDidServiceWorkerNavigationPreload(
+ head.did_service_worker_navigation_preload);
+ response->SetEncodedDataLength(head.encoded_data_length);
+ response->SetEncodedBodyLength(head.encoded_body_length);
+ response->SetWasAlpnNegotiated(head.was_alpn_negotiated);
+ response->SetAlpnNegotiatedProtocol(
+ WebString::FromUTF8(head.alpn_negotiated_protocol));
+ response->SetWasAlternateProtocolAvailable(
+ head.was_alternate_protocol_available);
+ response->SetConnectionInfo(head.connection_info);
+ response->SetAsyncRevalidationRequested(head.async_revalidation_requested);
+ response->SetNetworkAccessed(head.network_accessed);
+ response->SetRequestId(request_id);
+ response->SetIsSignedExchangeInnerResponse(
+ head.is_signed_exchange_inner_response);
+ response->SetWasInPrefetchCache(head.was_in_prefetch_cache);
+ response->SetWasCookieInRequest(head.was_cookie_in_request);
+ response->SetRecursivePrefetchToken(head.recursive_prefetch_token);
+ response->SetWebBundleURL(KURL(head.web_bundle_url));
+
+ SetSecurityStyleAndDetails(KURL(url), head, response, report_security_info);
+
+ // If there's no received headers end time, don't set load timing. This is
+ // the case for non-HTTP requests, requests that don't go over the wire, and
+ // certain error cases.
+ if (!head.load_timing.receive_headers_end.is_null()) {
+ response->SetLoadTiming(ToMojoLoadTiming(head.load_timing));
+ }
+
+ if (head.raw_request_response_info.get()) {
+ WebHTTPLoadInfo load_info;
+
+ load_info.SetHTTPStatusCode(
+ head.raw_request_response_info->http_status_code);
+ load_info.SetHTTPStatusText(WebString::FromLatin1(
+ head.raw_request_response_info->http_status_text));
+
+ load_info.SetRequestHeadersText(WebString::FromLatin1(
+ head.raw_request_response_info->request_headers_text));
+ load_info.SetResponseHeadersText(WebString::FromLatin1(
+ head.raw_request_response_info->response_headers_text));
+ for (auto& header : head.raw_request_response_info->request_headers) {
+ load_info.AddRequestHeader(WebString::FromLatin1(header->key),
+ WebString::FromLatin1(header->value));
+ }
+ for (auto& header : head.raw_request_response_info->response_headers) {
+ load_info.AddResponseHeader(WebString::FromLatin1(header->key),
+ WebString::FromLatin1(header->value));
+ }
+ response->SetHTTPLoadInfo(load_info);
+ }
+
+ response->SetAuthChallengeInfo(head.auth_challenge_info);
+
+ const net::HttpResponseHeaders* headers = head.headers.get();
+ if (!headers)
+ return;
+
+ WebURLResponse::HTTPVersion version = WebURLResponse::kHTTPVersionUnknown;
+ if (headers->GetHttpVersion() == net::HttpVersion(0, 9))
+ version = WebURLResponse::kHTTPVersion_0_9;
+ else if (headers->GetHttpVersion() == net::HttpVersion(1, 0))
+ version = WebURLResponse::kHTTPVersion_1_0;
+ else if (headers->GetHttpVersion() == net::HttpVersion(1, 1))
+ version = WebURLResponse::kHTTPVersion_1_1;
+ else if (headers->GetHttpVersion() == net::HttpVersion(2, 0))
+ version = WebURLResponse::kHTTPVersion_2_0;
+ response->SetHttpVersion(version);
+ response->SetHttpStatusCode(headers->response_code());
+ response->SetHttpStatusText(WebString::FromLatin1(headers->GetStatusText()));
+
+ // Build up the header map.
+ size_t iter = 0;
+ std::string name;
+ std::string value;
+ while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
+ response->AddHttpHeaderField(WebString::FromLatin1(name),
+ WebString::FromLatin1(value));
+ }
+}
+
+// static
+WebURLError WebURLLoader::PopulateURLError(
+ const network::URLLoaderCompletionStatus& status,
+ const WebURL& url) {
+ DCHECK_NE(net::OK, status.error_code);
+ const WebURLError::HasCopyInCache has_copy_in_cache =
+ status.exists_in_cache ? WebURLError::HasCopyInCache::kTrue
+ : WebURLError::HasCopyInCache::kFalse;
+ if (status.cors_error_status)
+ return WebURLError(*status.cors_error_status, has_copy_in_cache, url);
+ if (status.blocked_by_response_reason) {
+ DCHECK_EQ(net::ERR_BLOCKED_BY_RESPONSE, status.error_code);
+ return WebURLError(*status.blocked_by_response_reason,
+ status.resolve_error_info, has_copy_in_cache, url);
+ }
+
+ if (status.trust_token_operation_status !=
+ network::mojom::TrustTokenOperationStatus::kOk) {
+ DCHECK(status.error_code ==
+ net::ERR_TRUST_TOKEN_OPERATION_SUCCESS_WITHOUT_SENDING_REQUEST ||
+ status.error_code == net::ERR_TRUST_TOKEN_OPERATION_FAILED)
+ << "Unexpected error code on Trust Token operation failure (or cache "
+ "hit): "
+ << status.error_code;
+
+ return WebURLError(status.error_code, status.trust_token_operation_status,
+ url);
+ }
+
+ return WebURLError(status.error_code, status.extended_error_code,
+ status.resolve_error_info, has_copy_in_cache,
+ WebURLError::IsWebSecurityViolation::kFalse, url);
+}
+
+void WebURLLoader::LoadSynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
+ int requestor_id,
+ bool pass_response_pipe_to_client,
+ bool no_mime_sniffing,
+ base::TimeDelta timeout_interval,
+ WebURLLoaderClient* client,
+ WebURLResponse& response,
+ base::Optional<WebURLError>& error,
+ WebData& data,
+ int64_t& encoded_data_length,
+ int64_t& encoded_body_length,
+ WebBlobInfo& downloaded_blob,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper) {
+ if (!context_)
+ return;
+
+ TRACE_EVENT0("loading", "WebURLLoader::loadSynchronously");
+ SyncLoadResponse sync_load_response;
+
+ DCHECK(!context_->client());
+ context_->set_client(client);
+
+ const bool report_raw_headers = request->report_raw_headers;
+ context_->Start(std::move(request), std::move(url_request_extra_data),
+ requestor_id, pass_response_pipe_to_client, no_mime_sniffing,
+ timeout_interval, &sync_load_response,
+ std::move(resource_load_info_notifier_wrapper));
+
+ const KURL final_url(sync_load_response.url);
+
+ // TODO(tc): For file loads, we may want to include a more descriptive
+ // status code or status text.
+ const int error_code = sync_load_response.error_code;
+ if (error_code != net::OK) {
+ if (sync_load_response.cors_error) {
+ error = WebURLError(*sync_load_response.cors_error,
+ WebURLError::HasCopyInCache::kFalse, final_url);
+ } else {
+ // SyncResourceHandler returns ERR_ABORTED for CORS redirect errors,
+ // so we treat the error as a web security violation.
+ const WebURLError::IsWebSecurityViolation is_web_security_violation =
+ error_code == net::ERR_ABORTED
+ ? WebURLError::IsWebSecurityViolation::kTrue
+ : WebURLError::IsWebSecurityViolation::kFalse;
+ error = WebURLError(error_code, sync_load_response.extended_error_code,
+ sync_load_response.resolve_error_info,
+ WebURLError::HasCopyInCache::kFalse,
+ is_web_security_violation, final_url);
+ }
+ return;
+ }
+
+ PopulateURLResponse(final_url, *sync_load_response.head, &response,
+ report_raw_headers, context_->request_id());
+ encoded_data_length = sync_load_response.head->encoded_data_length;
+ encoded_body_length = sync_load_response.head->encoded_body_length;
+ if (sync_load_response.downloaded_blob) {
+ downloaded_blob = WebBlobInfo(
+ WebString::FromLatin1(sync_load_response.downloaded_blob->uuid),
+ WebString::FromLatin1(sync_load_response.downloaded_blob->content_type),
+ sync_load_response.downloaded_blob->size,
+ std::move(sync_load_response.downloaded_blob->blob));
+ }
+
+ data.Assign(sync_load_response.data);
+}
+
+void WebURLLoader::LoadAsynchronously(
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
+ int requestor_id,
+ bool no_mime_sniffing,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ WebURLLoaderClient* client) {
+ if (!context_)
+ return;
+
+ TRACE_EVENT_WITH_FLOW0("loading", "WebURLLoader::loadAsynchronously", this,
+ TRACE_EVENT_FLAG_FLOW_OUT);
+ DCHECK(!context_->client());
+
+ context_->set_client(client);
+ context_->Start(std::move(request), std::move(url_request_extra_data),
+ requestor_id,
+ /*pass_response_pipe_to_client=*/false, no_mime_sniffing,
+ base::TimeDelta(), nullptr,
+ std::move(resource_load_info_notifier_wrapper));
+}
+
+void WebURLLoader::Cancel() {
+ if (context_)
+ context_->Cancel();
+}
+
+void WebURLLoader::SetDefersLoading(DeferType value) {
+ if (context_)
+ context_->SetDefersLoading(value);
+}
+
+void WebURLLoader::DidChangePriority(WebURLRequest::Priority new_priority,
+ int intra_priority_value) {
+ if (context_)
+ context_->DidChangePriority(new_priority, intra_priority_value);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+WebURLLoader::GetTaskRunnerForBodyLoader() {
+ if (!context_)
+ return nullptr;
+ return context_->unfreezable_task_runner();
+}
+
+void WebURLLoader::SetResourceRequestSenderForTesting(
+ std::unique_ptr<WebResourceRequestSender> resource_request_sender) {
+ context_->SetResourceRequestSenderForTesting( // IN-TEST
+ std::move(resource_request_sender));
+}
+
+// static
+// We have this function at the bottom of this file because it confuses
+// syntax highliting.
+// TODO(kinuko): Deprecate this, we basically need to know the destination
+// and if it's for favicon or not.
+net::NetworkTrafficAnnotationTag WebURLLoader::Context::GetTrafficAnnotationTag(
+ network::ResourceRequest* request) {
+ if (request->is_favicon) {
+ return net::DefineNetworkTrafficAnnotation("favicon_loader", R"(
+ semantics {
+ sender: "Blink Resource Loader"
+ description:
+ "Chrome sends a request to download favicon for a URL."
+ trigger:
+ "Navigating to a URL."
+ data: "None."
+ destination: WEBSITE
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting: "These requests cannot be disabled in settings."
+ policy_exception_justification:
+ "Not implemented."
+ })");
+ }
+ switch (request->destination) {
+ case network::mojom::RequestDestination::kDocument:
+ case network::mojom::RequestDestination::kIframe:
+ case network::mojom::RequestDestination::kFrame:
+ NOTREACHED();
+ FALLTHROUGH;
+
+ case network::mojom::RequestDestination::kEmpty:
+ case network::mojom::RequestDestination::kAudio:
+ case network::mojom::RequestDestination::kAudioWorklet:
+ case network::mojom::RequestDestination::kFont:
+ case network::mojom::RequestDestination::kImage:
+ case network::mojom::RequestDestination::kManifest:
+ case network::mojom::RequestDestination::kPaintWorklet:
+ case network::mojom::RequestDestination::kReport:
+ case network::mojom::RequestDestination::kScript:
+ case network::mojom::RequestDestination::kServiceWorker:
+ case network::mojom::RequestDestination::kSharedWorker:
+ case network::mojom::RequestDestination::kStyle:
+ case network::mojom::RequestDestination::kTrack:
+ case network::mojom::RequestDestination::kVideo:
+ case network::mojom::RequestDestination::kWebBundle:
+ case network::mojom::RequestDestination::kWorker:
+ case network::mojom::RequestDestination::kXslt:
+ return net::DefineNetworkTrafficAnnotation("blink_resource_loader", R"(
+ semantics {
+ sender: "Blink Resource Loader"
+ description:
+ "Blink-initiated request, which includes all resources for "
+ "normal page loads, chrome URLs, and downloads."
+ trigger:
+ "The user navigates to a URL or downloads a file. Also when a "
+ "webpage, ServiceWorker, or chrome:// uses any network communication."
+ data: "Anything the initiator wants to send."
+ destination: OTHER
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting: "These requests cannot be disabled in settings."
+ policy_exception_justification:
+ "Not implemented. Without these requests, Chrome will be unable "
+ "to load any webpage."
+ })");
+
+ case network::mojom::RequestDestination::kEmbed:
+ case network::mojom::RequestDestination::kObject:
+ return net::DefineNetworkTrafficAnnotation(
+ "blink_extension_resource_loader", R"(
+ semantics {
+ sender: "Blink Resource Loader"
+ description:
+ "Blink-initiated request for resources required for NaCl instances "
+ "tagged with <embed> or <object>, or installed extensions."
+ trigger:
+ "An extension or NaCl instance may initiate a request at any time, "
+ "even in the background."
+ data: "Anything the initiator wants to send."
+ destination: OTHER
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting:
+ "These requests cannot be disabled in settings, but they are "
+ "sent only if user installs extensions."
+ chrome_policy {
+ ExtensionInstallBlocklist {
+ ExtensionInstallBlocklist: {
+ entries: '*'
+ }
+ }
+ }
+ })");
+ }
+
+ return net::NetworkTrafficAnnotationTag::NotReached();
+}
+
+void WebURLLoader::Context::SetResourceRequestSenderForTesting(
+ std::unique_ptr<blink::WebResourceRequestSender> resource_request_sender) {
+ resource_request_sender_ = std::move(resource_request_sender);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_factory.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_factory.cc
new file mode 100644
index 00000000000..204f81362f7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_factory.cc
@@ -0,0 +1,46 @@
+// 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 "third_party/blink/public/platform/web_url_loader_factory.h"
+
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_url_loader.h"
+
+using blink::scheduler::WebResourceLoadingTaskRunnerHandle;
+
+namespace blink {
+
+WebURLLoaderFactory::WebURLLoaderFactory(
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ const WebVector<WebString>& cors_exempt_header_list,
+ base::WaitableEvent* terminate_sync_load_event)
+ : loader_factory_(std::move(loader_factory)),
+ cors_exempt_header_list_(cors_exempt_header_list),
+ terminate_sync_load_event_(terminate_sync_load_event) {
+ DCHECK(loader_factory_);
+}
+
+WebURLLoaderFactory::WebURLLoaderFactory() = default;
+
+WebURLLoaderFactory::~WebURLLoaderFactory() = default;
+
+std::unique_ptr<WebURLLoader> WebURLLoaderFactory::CreateURLLoader(
+ const WebURLRequest& request,
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ freezable_task_runner_handle,
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ unfreezable_task_runner_handle,
+ CrossVariantMojoRemote<mojom::KeepAliveHandleInterfaceBase>
+ keep_alive_handle,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper) {
+ DCHECK(freezable_task_runner_handle);
+ DCHECK(unfreezable_task_runner_handle);
+ return std::make_unique<WebURLLoader>(
+ cors_exempt_header_list_, terminate_sync_load_event_,
+ std::move(freezable_task_runner_handle),
+ std::move(unfreezable_task_runner_handle), loader_factory_,
+ std::move(keep_alive_handle), back_forward_cache_loader_helper);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc
new file mode 100644
index 00000000000..6f5e2e2e1d6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc
@@ -0,0 +1,715 @@
+// Copyright 2014 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 "third_party/blink/public/platform/web_url_loader.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/test/task_environment.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/cert/x509_util.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "net/ssl/ssl_connection_status_flags.h"
+#include "net/test/cert_test_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
+#include "third_party/blink/public/platform/web_data.h"
+#include "third_party/blink/public/platform/web_request_peer.h"
+#include "third_party/blink/public/platform/web_resource_request_sender.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_url_error.h"
+#include "third_party/blink/public/platform/web_url_loader.h"
+#include "third_party/blink/public/platform/web_url_loader_client.h"
+#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/platform/web_url_request_extra_data.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace blink {
+namespace {
+
+const char kTestURL[] = "http://foo";
+const char kTestHTTPSURL[] = "https://foo";
+const char kTestData[] = "blah!";
+
+class MockResourceRequestSender : public WebResourceRequestSender {
+ public:
+ MockResourceRequestSender() = default;
+ ~MockResourceRequestSender() override = default;
+
+ // WebResourceRequestSender implementation:
+ void SendSync(
+ std::unique_ptr<network::ResourceRequest> request,
+ int routing_id,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ uint32_t loader_options,
+ SyncLoadResponse* response,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
+ base::TimeDelta timeout,
+ const WebVector<WebString>& cors_exempt_header_list,
+ base::WaitableEvent* terminate_sync_load_event,
+ mojo::PendingRemote<mojom::BlobRegistry> download_to_blob_registry,
+ scoped_refptr<WebRequestPeer> peer,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
+ override {
+ *response = std::move(sync_load_response_);
+ }
+
+ int SendAsync(
+ std::unique_ptr<network::ResourceRequest> request,
+ int routing_id,
+ scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ uint32_t loader_options,
+ const WebVector<WebString>& cors_exempt_header_list,
+ scoped_refptr<WebRequestPeer> peer,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
+ std::unique_ptr<ResourceLoadInfoNotifierWrapper>
+ resource_load_info_notifier_wrapper,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
+ override {
+ EXPECT_FALSE(peer_);
+ if (sync_load_response_.head->encoded_body_length != -1)
+ EXPECT_TRUE(loader_options & network::mojom::kURLLoadOptionSynchronous);
+ peer_ = std::move(peer);
+ return 1;
+ }
+
+ void Cancel(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
+ EXPECT_FALSE(canceled_);
+ canceled_ = true;
+
+ task_runner->ReleaseSoon(FROM_HERE, std::move(peer_));
+ }
+
+ WebRequestPeer* peer() { return peer_.get(); }
+
+ bool canceled() { return canceled_; }
+
+ void SetDefersLoading(WebURLLoader::DeferType value) override {
+ defers_loading_ = (value != WebURLLoader::DeferType::kNotDeferred);
+ }
+ bool defers_loading() const { return defers_loading_; }
+
+ void set_sync_load_response(SyncLoadResponse&& sync_load_response) {
+ sync_load_response_ = std::move(sync_load_response);
+ }
+
+ private:
+ scoped_refptr<WebRequestPeer> peer_;
+ bool canceled_ = false;
+ bool defers_loading_ = false;
+ SyncLoadResponse sync_load_response_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockResourceRequestSender);
+};
+
+class FakeURLLoaderFactory final : public network::mojom::URLLoaderFactory {
+ public:
+ FakeURLLoaderFactory() = default;
+ ~FakeURLLoaderFactory() override = default;
+ void CreateLoaderAndStart(
+ mojo::PendingReceiver<network::mojom::URLLoader> receiver,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
+ override {
+ NOTREACHED();
+ }
+
+ void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
+ override {
+ NOTREACHED();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeURLLoaderFactory);
+};
+
+class TestWebURLLoaderClient : public WebURLLoaderClient {
+ public:
+ TestWebURLLoaderClient()
+ : loader_(new WebURLLoader(
+ /*cors_exempt_header_list=*/WebVector<WebString>(),
+ /*terminate_sync_load_event=*/nullptr,
+ scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
+ scheduler::GetSingleThreadTaskRunnerForTesting()),
+ scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
+ scheduler::GetSingleThreadTaskRunnerForTesting()),
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &fake_url_loader_factory_),
+ /*keep_alive_handle=*/mojo::NullRemote(),
+ WebBackForwardCacheLoaderHelper())),
+ delete_on_receive_redirect_(false),
+ delete_on_receive_response_(false),
+ delete_on_receive_data_(false),
+ delete_on_finish_(false),
+ delete_on_fail_(false),
+ did_receive_redirect_(false),
+ did_receive_response_(false),
+ did_finish_(false) {}
+
+ ~TestWebURLLoaderClient() override {
+ // During the deconstruction of the `loader_`, the request context will be
+ // released asynchronously and we must ensure that the request context has
+ // been deleted practically before the test quits, thus, memory leak will
+ // not be reported on the ASAN build. So, we call 'reset()' to trigger the
+ // deconstruction, and then execute `RunUntilIdle()` to empty the task queue
+ // to achieve that.
+ if (loader_)
+ loader_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ // WebURLLoaderClient implementation:
+ bool WillFollowRedirect(const WebURL& new_url,
+ const net::SiteForCookies& new_site_for_cookies,
+ const WebString& new_referrer,
+ network::mojom::ReferrerPolicy new_referrer_policy,
+ const WebString& new_method,
+ const WebURLResponse& passed_redirect_response,
+ bool& report_raw_headers,
+ std::vector<std::string>*) override {
+ EXPECT_TRUE(loader_);
+
+ // No test currently simulates mutiple redirects.
+ EXPECT_FALSE(did_receive_redirect_);
+ did_receive_redirect_ = true;
+
+ if (delete_on_receive_redirect_)
+ loader_.reset();
+
+ return true;
+ }
+
+ void DidSendData(uint64_t bytesSent, uint64_t totalBytesToBeSent) override {
+ EXPECT_TRUE(loader_);
+ }
+
+ void DidReceiveResponse(const WebURLResponse& response) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_FALSE(did_receive_response_);
+
+ did_receive_response_ = true;
+ response_ = response;
+ if (delete_on_receive_response_)
+ loader_.reset();
+ }
+
+ void DidStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle response_body) override {
+ DCHECK(!response_body_);
+ DCHECK(response_body);
+ response_body_ = std::move(response_body);
+ }
+
+ void DidReceiveData(const char* data, int dataLength) override {
+ NOTREACHED();
+ }
+
+ void DidFinishLoading(base::TimeTicks finishTime,
+ int64_t totalEncodedDataLength,
+ int64_t totalEncodedBodyLength,
+ int64_t totalDecodedBodyLength,
+ bool should_report_corb_blocking) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_TRUE(did_receive_response_);
+ EXPECT_FALSE(did_finish_);
+ did_finish_ = true;
+
+ if (delete_on_finish_)
+ loader_.reset();
+ }
+
+ void DidFail(const WebURLError& error,
+ base::TimeTicks finishTime,
+ int64_t totalEncodedDataLength,
+ int64_t totalEncodedBodyLength,
+ int64_t totalDecodedBodyLength) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_FALSE(did_finish_);
+ error_ = error;
+
+ if (delete_on_fail_)
+ loader_.reset();
+ }
+
+ WebURLLoader* loader() { return loader_.get(); }
+ void DeleteLoader() { loader_.reset(); }
+
+ void set_delete_on_receive_redirect() { delete_on_receive_redirect_ = true; }
+ void set_delete_on_receive_response() { delete_on_receive_response_ = true; }
+ void set_delete_on_receive_data() { delete_on_receive_data_ = true; }
+ void set_delete_on_finish() { delete_on_finish_ = true; }
+ void set_delete_on_fail() { delete_on_fail_ = true; }
+
+ bool did_receive_redirect() const { return did_receive_redirect_; }
+ bool did_receive_response() const { return did_receive_response_; }
+ bool did_receive_response_body() const { return !!response_body_; }
+ bool did_finish() const { return did_finish_; }
+ const base::Optional<WebURLError>& error() const { return error_; }
+ const WebURLResponse& response() const { return response_; }
+
+ private:
+ FakeURLLoaderFactory fake_url_loader_factory_;
+ std::unique_ptr<WebURLLoader> loader_;
+
+ bool delete_on_receive_redirect_;
+ bool delete_on_receive_response_;
+ bool delete_on_receive_data_;
+ bool delete_on_finish_;
+ bool delete_on_fail_;
+
+ bool did_receive_redirect_;
+ bool did_receive_response_;
+ mojo::ScopedDataPipeConsumerHandle response_body_;
+ bool did_finish_;
+ base::Optional<WebURLError> error_;
+ WebURLResponse response_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestWebURLLoaderClient);
+};
+
+class WebURLLoaderTest : public testing::Test {
+ public:
+ WebURLLoaderTest() : client_(std::make_unique<TestWebURLLoaderClient>()) {
+ auto sender = std::make_unique<MockResourceRequestSender>();
+ sender_ = sender.get();
+ client_->loader()->SetResourceRequestSenderForTesting(std::move(sender));
+ }
+
+ ~WebURLLoaderTest() override = default;
+
+ void DoStartAsyncRequest() {
+ auto request = std::make_unique<network::ResourceRequest>();
+ request->url = GURL(kTestURL);
+ request->destination = network::mojom::RequestDestination::kEmpty;
+ request->priority = net::IDLE;
+ client()->loader()->LoadAsynchronously(
+ std::move(request), /*url_request_extra_data=*/nullptr,
+ /*requestor_id=*/0,
+ /*no_mime_sniffing=*/false,
+ std::make_unique<ResourceLoadInfoNotifierWrapper>(
+ /*resource_load_info_notifier=*/nullptr),
+ client());
+ ASSERT_TRUE(peer());
+ }
+
+ void DoReceiveRedirect() {
+ EXPECT_FALSE(client()->did_receive_redirect());
+ net::RedirectInfo redirect_info;
+ redirect_info.status_code = 302;
+ redirect_info.new_method = "GET";
+ redirect_info.new_url = GURL(kTestURL);
+ redirect_info.new_site_for_cookies =
+ net::SiteForCookies::FromUrl(GURL(kTestURL));
+ std::vector<std::string> removed_headers;
+ peer()->OnReceivedRedirect(redirect_info,
+ network::mojom::URLResponseHead::New(),
+ &removed_headers);
+ EXPECT_TRUE(client()->did_receive_redirect());
+ }
+
+ void DoReceiveHTTPSRedirect() {
+ EXPECT_FALSE(client()->did_receive_redirect());
+ net::RedirectInfo redirect_info;
+ redirect_info.status_code = 302;
+ redirect_info.new_method = "GET";
+ redirect_info.new_url = GURL(kTestHTTPSURL);
+ redirect_info.new_site_for_cookies =
+ net::SiteForCookies::FromUrl(GURL(kTestHTTPSURL));
+ peer()->OnReceivedRedirect(redirect_info,
+ network::mojom::URLResponseHead::New(), nullptr);
+ EXPECT_TRUE(client()->did_receive_redirect());
+ }
+
+ void DoReceiveResponse() {
+ EXPECT_FALSE(client()->did_receive_response());
+ peer()->OnReceivedResponse(network::mojom::URLResponseHead::New());
+ EXPECT_TRUE(client()->did_receive_response());
+ }
+
+ void DoStartLoadingResponseBody() {
+ mojo::ScopedDataPipeConsumerHandle handle_to_pass;
+ MojoResult rv = mojo::CreateDataPipe(nullptr, body_handle_, handle_to_pass);
+ ASSERT_EQ(MOJO_RESULT_OK, rv);
+ peer()->OnStartLoadingResponseBody(std::move(handle_to_pass));
+ }
+
+ void DoCompleteRequest() {
+ EXPECT_FALSE(client()->did_finish());
+ DCHECK(body_handle_);
+ body_handle_.reset();
+ base::RunLoop().RunUntilIdle();
+ network::URLLoaderCompletionStatus status(net::OK);
+ status.encoded_data_length = base::size(kTestData);
+ status.encoded_body_length = base::size(kTestData);
+ status.decoded_body_length = base::size(kTestData);
+ peer()->OnCompletedRequest(status);
+ EXPECT_TRUE(client()->did_finish());
+ // There should be no error.
+ EXPECT_FALSE(client()->error());
+ }
+
+ void DoFailRequest() {
+ EXPECT_FALSE(client()->did_finish());
+ DCHECK(body_handle_);
+ body_handle_.reset();
+ base::RunLoop().RunUntilIdle();
+ network::URLLoaderCompletionStatus status(net::ERR_FAILED);
+ status.encoded_data_length = base::size(kTestData);
+ status.encoded_body_length = base::size(kTestData);
+ status.decoded_body_length = base::size(kTestData);
+ peer()->OnCompletedRequest(status);
+ EXPECT_FALSE(client()->did_finish());
+ ASSERT_TRUE(client()->error());
+ EXPECT_EQ(net::ERR_FAILED, client()->error()->reason());
+ }
+
+ TestWebURLLoaderClient* client() { return client_.get(); }
+ MockResourceRequestSender* sender() { return sender_; }
+ WebRequestPeer* peer() { return sender_->peer(); }
+
+ private:
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ mojo::ScopedDataPipeProducerHandle body_handle_;
+ std::unique_ptr<TestWebURLLoaderClient> client_;
+ MockResourceRequestSender* sender_ = nullptr;
+};
+
+TEST_F(WebURLLoaderTest, Success) {
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoStartLoadingResponseBody();
+ DoCompleteRequest();
+ EXPECT_FALSE(sender()->canceled());
+ EXPECT_TRUE(client()->did_receive_response_body());
+}
+
+TEST_F(WebURLLoaderTest, Redirect) {
+ DoStartAsyncRequest();
+ DoReceiveRedirect();
+ DoReceiveResponse();
+ DoStartLoadingResponseBody();
+ DoCompleteRequest();
+ EXPECT_FALSE(sender()->canceled());
+ EXPECT_TRUE(client()->did_receive_response_body());
+}
+
+TEST_F(WebURLLoaderTest, Failure) {
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoStartLoadingResponseBody();
+ DoFailRequest();
+ EXPECT_FALSE(sender()->canceled());
+}
+
+// The client may delete the WebURLLoader during any callback from the loader.
+// These tests make sure that doesn't result in a crash.
+TEST_F(WebURLLoaderTest, DeleteOnReceiveRedirect) {
+ client()->set_delete_on_receive_redirect();
+ DoStartAsyncRequest();
+ DoReceiveRedirect();
+}
+
+TEST_F(WebURLLoaderTest, DeleteOnReceiveResponse) {
+ client()->set_delete_on_receive_response();
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+}
+
+TEST_F(WebURLLoaderTest, DeleteOnFinish) {
+ client()->set_delete_on_finish();
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoStartLoadingResponseBody();
+ DoCompleteRequest();
+}
+
+TEST_F(WebURLLoaderTest, DeleteOnFail) {
+ client()->set_delete_on_fail();
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoStartLoadingResponseBody();
+ DoFailRequest();
+}
+
+TEST_F(WebURLLoaderTest, DefersLoadingBeforeStart) {
+ client()->loader()->SetDefersLoading(WebURLLoader::DeferType::kDeferred);
+ EXPECT_FALSE(sender()->defers_loading());
+ DoStartAsyncRequest();
+ EXPECT_TRUE(sender()->defers_loading());
+}
+
+TEST_F(WebURLLoaderTest, ResponseIPEndpoint) {
+ KURL url("http://example.test/");
+
+ struct TestCase {
+ const char* ip;
+ uint16_t port;
+ } cases[] = {
+ {"127.0.0.1", 443},
+ {"123.123.123.123", 80},
+ {"::1", 22},
+ {"2001:0db8:85a3:0000:0000:8a2e:0370:7334", 1337},
+ {"2001:db8:85a3:0:0:8a2e:370:7334", 12345},
+ {"2001:db8:85a3::8a2e:370:7334", 8080},
+ {"::ffff:192.0.2.128", 8443},
+ };
+
+ for (const auto& test : cases) {
+ SCOPED_TRACE(test.ip);
+
+ net::IPAddress address;
+ ASSERT_TRUE(address.AssignFromIPLiteral(test.ip));
+
+ network::mojom::URLResponseHead head;
+ head.remote_endpoint = net::IPEndPoint(address, test.port);
+
+ WebURLResponse response;
+ WebURLLoader::PopulateURLResponse(url, head, &response, true, -1);
+ EXPECT_EQ(head.remote_endpoint, response.RemoteIPEndpoint());
+ };
+}
+
+TEST_F(WebURLLoaderTest, ResponseAddressSpace) {
+ using AddressSpace = network::mojom::IPAddressSpace;
+
+ struct TestCase {
+ std::string url;
+ std::string ip;
+ AddressSpace expected;
+ } cases[] = {
+ {"http://localhost", "127.0.0.1", AddressSpace::kLocal},
+ {"http://localhost", "::1", AddressSpace::kLocal},
+ {"file:///a/path", "", AddressSpace::kLocal},
+ {"file:///a/path", "8.8.8.8", AddressSpace::kLocal},
+ {"http://router.local", "10.1.0.1", AddressSpace::kPrivate},
+ {"http://router.local", "::ffff:192.0.2.128", AddressSpace::kPrivate},
+ {"https://bleep.test", "8.8.8.8", AddressSpace::kPublic},
+ {"http://a.test", "2001:db8:85a3::8a2e:370:7334", AddressSpace::kPublic},
+ {"http://invalid", "", AddressSpace::kUnknown},
+ };
+
+ for (const auto& test : cases) {
+ SCOPED_TRACE(test.url + ", " + test.ip);
+
+ KURL url(test.url.c_str());
+
+ // We are forced to use the result of AssignFromIPLiteral(), and we cannot
+ // just assign it to an unused variable. Check that all non-empty literals
+ // are correctly parsed.
+ net::IPAddress address;
+ EXPECT_EQ(!test.ip.empty(), address.AssignFromIPLiteral(test.ip));
+
+ network::mojom::URLResponseHead head;
+ head.remote_endpoint = net::IPEndPoint(address, 443);
+
+ WebURLResponse response;
+ WebURLLoader::PopulateURLResponse(url, head, &response, true, -1);
+
+ EXPECT_EQ(test.expected, response.AddressSpace());
+ }
+}
+
+// This test verifies that the IPAddressSpace set on WebURLResponse takes into
+// account WebURLResponse::ResponseUrl() instead of
+// WebURLResponse::CurrentRequestUrl().
+TEST_F(WebURLLoaderTest, ResponseAddressSpaceConsidersResponseUrl) {
+ KURL request_url("http://request.test");
+
+ // The remote endpoint contains a public IP address, but the response was
+ // ultimately fetched by a service worker from a file URL.
+ network::mojom::URLResponseHead head;
+ head.remote_endpoint = net::IPEndPoint(net::IPAddress(8, 8, 8, 8), 80);
+ head.was_fetched_via_service_worker = true;
+ head.url_list_via_service_worker = {
+ GURL("http://redirect.test"),
+ GURL("file:///a/path"),
+ };
+
+ WebURLResponse response;
+ WebURLLoader::PopulateURLResponse(request_url, head, &response, true, -1);
+
+ // The address space of the response reflects the fact the it was fetched
+ // from a file, even though the request was initially to a public website.
+ EXPECT_EQ(KURL("http://request.test"), KURL(response.CurrentRequestUrl()));
+ EXPECT_EQ(KURL("file:///a/path"), KURL(response.ResponseUrl()));
+ EXPECT_EQ(network::mojom::IPAddressSpace::kLocal, response.AddressSpace());
+}
+
+TEST_F(WebURLLoaderTest, ResponseCert) {
+ KURL url("https://test.example/");
+
+ net::CertificateList certs;
+ ASSERT_TRUE(net::LoadCertificateFiles(
+ {"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
+ ASSERT_EQ(2U, certs.size());
+
+ base::StringPiece cert0_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
+ base::StringPiece cert1_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer());
+
+ net::SSLInfo ssl_info;
+ ssl_info.cert =
+ net::X509Certificate::CreateFromDERCertChain({cert0_der, cert1_der});
+ net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_2,
+ &ssl_info.connection_status);
+
+ network::mojom::URLResponseHead head;
+ head.ssl_info = ssl_info;
+ WebURLResponse web_url_response;
+ WebURLLoader::PopulateURLResponse(url, head, &web_url_response, true, -1);
+
+ base::Optional<WebURLResponse::WebSecurityDetails> security_details =
+ web_url_response.SecurityDetailsForTesting();
+ ASSERT_TRUE(security_details.has_value());
+ EXPECT_EQ("TLS 1.2", security_details->protocol);
+ EXPECT_EQ("127.0.0.1", security_details->subject_name);
+ EXPECT_EQ("127.0.0.1", security_details->issuer);
+ ASSERT_EQ(3U, security_details->san_list.size());
+ EXPECT_EQ("test.example", security_details->san_list[0]);
+ EXPECT_EQ("127.0.0.2", security_details->san_list[1]);
+ EXPECT_EQ("fe80::1", security_details->san_list[2]);
+ EXPECT_EQ(certs[0]->valid_start().ToTimeT(), security_details->valid_from);
+ EXPECT_EQ(certs[0]->valid_expiry().ToTimeT(), security_details->valid_to);
+ ASSERT_EQ(2U, security_details->certificate.size());
+ EXPECT_EQ(WebString::FromLatin1(std::string(cert0_der)),
+ security_details->certificate[0]);
+ EXPECT_EQ(WebString::FromLatin1(std::string(cert1_der)),
+ security_details->certificate[1]);
+}
+
+TEST_F(WebURLLoaderTest, ResponseCertWithNoSANs) {
+ KURL url("https://test.example/");
+
+ net::CertificateList certs;
+ ASSERT_TRUE(net::LoadCertificateFiles({"multi-root-B-by-C.pem"}, &certs));
+ ASSERT_EQ(1U, certs.size());
+
+ base::StringPiece cert0_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
+
+ net::SSLInfo ssl_info;
+ net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_2,
+ &ssl_info.connection_status);
+ ssl_info.cert = certs[0];
+ network::mojom::URLResponseHead head;
+ head.ssl_info = ssl_info;
+ WebURLResponse web_url_response;
+ WebURLLoader::PopulateURLResponse(url, head, &web_url_response, true, -1);
+
+ base::Optional<WebURLResponse::WebSecurityDetails> security_details =
+ web_url_response.SecurityDetailsForTesting();
+ ASSERT_TRUE(security_details.has_value());
+ EXPECT_EQ("TLS 1.2", security_details->protocol);
+ EXPECT_EQ("B CA - Multi-root", security_details->subject_name);
+ EXPECT_EQ("C CA - Multi-root", security_details->issuer);
+ EXPECT_EQ(0U, security_details->san_list.size());
+ EXPECT_EQ(certs[0]->valid_start().ToTimeT(), security_details->valid_from);
+ EXPECT_EQ(certs[0]->valid_expiry().ToTimeT(), security_details->valid_to);
+ ASSERT_EQ(1U, security_details->certificate.size());
+ EXPECT_EQ(WebString::FromLatin1(std::string(cert0_der)),
+ security_details->certificate[0]);
+}
+
+// Verifies that the lengths used by the PerformanceResourceTiming API are
+// correctly assigned for sync XHR.
+TEST_F(WebURLLoaderTest, SyncLengths) {
+ static const char kBodyData[] = "Today is Thursday";
+ const int kEncodedBodyLength = 30;
+ const int kEncodedDataLength = 130;
+ const KURL url(kTestURL);
+
+ auto request = std::make_unique<network::ResourceRequest>();
+ request->url = url;
+ request->destination = network::mojom::RequestDestination::kEmpty;
+ request->priority = net::HIGHEST;
+
+ // Prepare a mock response
+ SyncLoadResponse sync_load_response;
+ sync_load_response.error_code = net::OK;
+ sync_load_response.url = url;
+ sync_load_response.data.Assign(WebData(kBodyData));
+ ASSERT_EQ(17u, sync_load_response.data.size());
+ sync_load_response.head->encoded_body_length = kEncodedBodyLength;
+ sync_load_response.head->encoded_data_length = kEncodedDataLength;
+ sender()->set_sync_load_response(std::move(sync_load_response));
+
+ WebURLResponse response;
+ base::Optional<WebURLError> error;
+ WebData data;
+ int64_t encoded_data_length = 0;
+ int64_t encoded_body_length = 0;
+ WebBlobInfo downloaded_blob;
+
+ client()->loader()->LoadSynchronously(
+ std::move(request), /*url_request_extra_data=*/nullptr,
+ /*requestor_id=*/0,
+ /*pass_response_pipe_to_client=*/false, /*no_mime_sniffing=*/false,
+ base::TimeDelta(), nullptr, response, error, data, encoded_data_length,
+ encoded_body_length, downloaded_blob,
+ std::make_unique<ResourceLoadInfoNotifierWrapper>(
+ /*resource_load_info_notifier=*/nullptr));
+
+ EXPECT_EQ(kEncodedBodyLength, encoded_body_length);
+ EXPECT_EQ(kEncodedDataLength, encoded_data_length);
+ EXPECT_TRUE(downloaded_blob.Uuid().IsNull());
+}
+
+// Verifies that PopulateURLResponse() copies AuthChallengeInfo to the response.
+TEST_F(WebURLLoaderTest, AuthChallengeInfo) {
+ network::mojom::URLResponseHead head;
+ net::AuthChallengeInfo auth_challenge_info;
+ auth_challenge_info.is_proxy = true;
+ auth_challenge_info.challenge = "foobar";
+ head.auth_challenge_info = auth_challenge_info;
+
+ blink::WebURLResponse response;
+ WebURLLoader::PopulateURLResponse(KURL(), head, &response, true, -1);
+ ASSERT_TRUE(response.AuthChallengeInfo().has_value());
+ EXPECT_TRUE(response.AuthChallengeInfo()->is_proxy);
+ EXPECT_EQ("foobar", response.AuthChallengeInfo()->challenge);
+}
+
+} // namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc
index 3735b99b52a..40ab612c1f8 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc
@@ -7,12 +7,14 @@
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
-#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-shared.h"
#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
+#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
@@ -31,7 +33,7 @@ WorkerMainScriptLoader::WorkerMainScriptLoader() = default;
WorkerMainScriptLoader::~WorkerMainScriptLoader() = default;
void WorkerMainScriptLoader::Start(
- FetchParameters& fetch_params,
+ const FetchParameters& fetch_params,
std::unique_ptr<WorkerMainScriptLoadParameters>
worker_main_script_load_params,
FetchContext* fetch_context,
@@ -39,7 +41,7 @@ void WorkerMainScriptLoader::Start(
WorkerMainScriptLoaderClient* client) {
DCHECK(resource_load_observer);
DCHECK(client);
- initial_request_.CopyFrom(fetch_params.GetResourceRequest());
+ initial_request_ = fetch_params.GetResourceRequest();
resource_loader_options_ = fetch_params.Options();
initial_request_url_ = fetch_params.GetResourceRequest().Url();
last_request_url_ = initial_request_url_;
@@ -53,10 +55,12 @@ void WorkerMainScriptLoader::Start(
// TODO(crbug.com/929370): Support CSP check to post violation reports for
// worker top-level scripts, if off-the-main-thread fetch is enabled.
+ ResourceRequest resource_request(initial_request_);
resource_load_observer_->WillSendRequest(
- initial_request_.InspectorId(), initial_request_,
+ initial_request_.InspectorId(), resource_request,
/*redirect_response=*/ResourceResponse(), ResourceType::kScript,
- resource_loader_options_.initiator_info);
+ resource_loader_options_.initiator_info,
+ RenderBlockingBehavior::kNonBlocking);
resource_load_info_notifier_wrapper_->NotifyResourceLoadInitiated(
/*request_id=*/-1, initial_request_url_,
@@ -71,7 +75,7 @@ void WorkerMainScriptLoader::Start(
WebURLResponse response;
auto response_head = std::move(worker_main_script_load_params->response_head);
- Platform::Current()->PopulateURLResponse(
+ WebURLLoader::PopulateURLResponse(
WebURL(last_request_url_), *response_head, &response,
response_head->ssl_info.has_value(), /*request_id=*/-1);
resource_response_ = response.ToResourceResponse();
@@ -79,7 +83,7 @@ void WorkerMainScriptLoader::Start(
std::move(response_head), PreviewsTypes::kPreviewsUnspecified);
resource_load_observer_->DidReceiveResponse(
- initial_request_.InspectorId(), initial_request_, resource_response_,
+ initial_request_.InspectorId(), resource_request, resource_response_,
/*resource=*/nullptr,
ResourceLoadObserver::ResponseSource::kNotFromMemoryCache);
@@ -318,12 +322,13 @@ void WorkerMainScriptLoader::HandleRedirections(
redirect_info.new_referrer_policy),
/*skip_service_worker=*/false);
WebURLResponse response;
- Platform::Current()->PopulateURLResponse(
+ WebURLLoader::PopulateURLResponse(
WebURL(last_request_url_), *redirect_response, &response,
redirect_response->ssl_info.has_value(), /*request_id=*/-1);
resource_load_observer_->WillSendRequest(
new_request->InspectorId(), *new_request, response.ToResourceResponse(),
- ResourceType::kScript, resource_loader_options_.initiator_info);
+ ResourceType::kScript, resource_loader_options_.initiator_info,
+ RenderBlockingBehavior::kNonBlocking);
resource_load_info_notifier_wrapper_->NotifyResourceRedirectReceived(
redirect_info, std::move(redirect_response));
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h
index e6f82c490c1..a9426432965 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h
@@ -36,9 +36,10 @@ class SingleCachedMetadataHandler;
class WorkerMainScriptLoaderClient;
struct ResourceLoaderOptions;
-// For dedicated workers (PlzDedicatedWorker) and shared workers, the main
-// script is pre-requested by the browser process. This class is used for
-// receiving the response in the renderer process.
+// For dedicated workers (PlzDedicatedWorker), service workers
+// (PlzServiceWorker), and shared workers, the main script is pre-requested by
+// the browser process. This class is used for receiving the response in the
+// renderer process.
class PLATFORM_EXPORT WorkerMainScriptLoader final
: public GarbageCollected<WorkerMainScriptLoader>,
public network::mojom::URLLoaderClient {
@@ -47,7 +48,7 @@ class PLATFORM_EXPORT WorkerMainScriptLoader final
~WorkerMainScriptLoader() override;
// Starts to load the main script.
- void Start(FetchParameters& fetch_params,
+ void Start(const FetchParameters& fetch_params,
std::unique_ptr<WorkerMainScriptLoadParameters>
worker_main_script_load_params,
FetchContext* fetch_context,
@@ -98,7 +99,7 @@ class PLATFORM_EXPORT WorkerMainScriptLoader final
Member<WorkerMainScriptLoaderClient> client_;
Member<ResourceLoadObserver> resource_load_observer_;
- ResourceRequest initial_request_;
+ ResourceRequestHead initial_request_;
ResourceLoaderOptions resource_loader_options_{nullptr /* world */};
KURL initial_request_url_;
KURL last_request_url_;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
index 7a8e62cd882..e5df67c95aa 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
@@ -49,20 +49,6 @@ class WorkerMainScriptLoaderTest : public testing::Test {
}
protected:
- class TestPlatform final : public TestingPlatformSupport {
- public:
- void PopulateURLResponse(const WebURL& url,
- const network::mojom::URLResponseHead& head,
- WebURLResponse* response,
- bool report_security_info,
- int request_id) override {
- response->SetCurrentRequestUrl(url);
- response->SetHttpStatusCode(head.headers.get()->response_code());
- response->SetMimeType(WebString::FromUTF8(head.mime_type));
- response->SetTextEncodingName(WebString::FromUTF8(head.charset));
- }
- };
-
class TestClient final : public GarbageCollected<TestClient>,
public WorkerMainScriptLoaderClient {
@@ -160,12 +146,13 @@ class WorkerMainScriptLoaderTest : public testing::Test {
class MockResourceLoadObserver : public ResourceLoadObserver {
public:
MOCK_METHOD2(DidStartRequest, void(const FetchParameters&, ResourceType));
- MOCK_METHOD5(WillSendRequest,
+ MOCK_METHOD6(WillSendRequest,
void(uint64_t identifier,
const ResourceRequest&,
const ResourceResponse& redirect_response,
ResourceType,
- const FetchInitiatorInfo&));
+ const FetchInitiatorInfo&,
+ RenderBlockingBehavior));
MOCK_METHOD3(DidChangePriority,
void(uint64_t identifier,
ResourceLoadPriority,
@@ -227,7 +214,7 @@ class WorkerMainScriptLoaderTest : public testing::Test {
mojo::ScopedDataPipeConsumerHandle body_consumer;
MojoCreateDataPipeOptions options = CreateDataPipeOptions();
EXPECT_EQ(MOJO_RESULT_OK,
- mojo::CreateDataPipe(&options, body_producer, &body_consumer));
+ mojo::CreateDataPipe(&options, *body_producer, body_consumer));
worker_main_script_load_params->response_body = std::move(body_consumer);
return worker_main_script_load_params;
@@ -261,7 +248,6 @@ class WorkerMainScriptLoaderTest : public testing::Test {
protected:
base::test::TaskEnvironment task_environment_;
- ScopedTestingPlatformSupport<TestPlatform> platform_;
mojo::PendingRemote<network::mojom::URLLoader> pending_remote_loader_;
mojo::Remote<network::mojom::URLLoaderClient> loader_client_;
@@ -279,7 +265,7 @@ TEST_F(WorkerMainScriptLoaderTest, ResponseWithSucessThenOnComplete) {
MockResourceLoadObserver* mock_observer =
MakeGarbageCollected<MockResourceLoadObserver>();
FakeResourceLoadInfoNotifier fake_resource_load_info_notifier;
- EXPECT_CALL(*mock_observer, WillSendRequest(_, _, _, _, _));
+ EXPECT_CALL(*mock_observer, WillSendRequest(_, _, _, _, _, _));
EXPECT_CALL(*mock_observer, DidReceiveResponse(_, _, _, _, _));
EXPECT_CALL(*mock_observer, DidReceiveData(_, _));
EXPECT_CALL(*mock_observer, DidFinishLoading(_, _, _, _, _));
@@ -310,7 +296,7 @@ TEST_F(WorkerMainScriptLoaderTest, ResponseWithFailureThenOnComplete) {
MockResourceLoadObserver* mock_observer =
MakeGarbageCollected<MockResourceLoadObserver>();
FakeResourceLoadInfoNotifier fake_resource_load_info_notifier;
- EXPECT_CALL(*mock_observer, WillSendRequest(_, _, _, _, _));
+ EXPECT_CALL(*mock_observer, WillSendRequest(_, _, _, _, _, _));
EXPECT_CALL(*mock_observer, DidReceiveResponse(_, _, _, _, _));
EXPECT_CALL(*mock_observer, DidFinishLoading(_, _, _, _, _)).Times(0);
EXPECT_CALL(*mock_observer, DidFailLoading(_, _, _, _, _));
@@ -334,7 +320,7 @@ TEST_F(WorkerMainScriptLoaderTest, DisconnectBeforeOnComplete) {
MockResourceLoadObserver* mock_observer =
MakeGarbageCollected<MockResourceLoadObserver>();
FakeResourceLoadInfoNotifier fake_resource_load_info_notifier;
- EXPECT_CALL(*mock_observer, WillSendRequest(_, _, _, _, _));
+ EXPECT_CALL(*mock_observer, WillSendRequest(_, _, _, _, _, _));
EXPECT_CALL(*mock_observer, DidReceiveResponse(_, _, _, _, _));
EXPECT_CALL(*mock_observer, DidFinishLoading(_, _, _, _, _)).Times(0);
EXPECT_CALL(*mock_observer, DidFailLoading(_, _, _, _, _));
@@ -358,7 +344,7 @@ TEST_F(WorkerMainScriptLoaderTest, OnCompleteWithError) {
MockResourceLoadObserver* mock_observer =
MakeGarbageCollected<MockResourceLoadObserver>();
FakeResourceLoadInfoNotifier fake_resource_load_info_notifier;
- EXPECT_CALL(*mock_observer, WillSendRequest(_, _, _, _, _));
+ EXPECT_CALL(*mock_observer, WillSendRequest(_, _, _, _, _, _));
EXPECT_CALL(*mock_observer, DidReceiveResponse(_, _, _, _, _));
EXPECT_CALL(*mock_observer, DidReceiveData(_, _));
EXPECT_CALL(*mock_observer, DidFinishLoading(_, _, _, _, _)).Times(0);
diff --git a/chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc b/chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc
index 496c0178ab4..635edb5b2c3 100644
--- a/chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/internet_disconnected_web_url_loader.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_loader_client.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -21,7 +22,10 @@ InternetDisconnectedWebURLLoaderFactory::CreateURLLoader(
std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
freezable_task_runner_handle,
std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
- unfreezable_task_runner_handle) {
+ unfreezable_task_runner_handle,
+ CrossVariantMojoRemote<blink::mojom::KeepAliveHandleInterfaceBase>
+ keep_alive_handle,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper) {
DCHECK(freezable_task_runner_handle);
return std::make_unique<InternetDisconnectedWebURLLoader>(
std::move(freezable_task_runner_handle));
diff --git a/chromium/third_party/blink/renderer/platform/loader/mixed_content.cc b/chromium/third_party/blink/renderer/platform/loader/mixed_content.cc
new file mode 100644
index 00000000000..5ab3cfd6032
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/mixed_content.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/loader/mixed_content.h"
+
+#include "base/notreached.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/mixed_content.mojom-blink.h"
+
+namespace blink {
+
+// static
+mojom::blink::MixedContentContextType
+MixedContent::ContextTypeFromRequestContext(
+ mojom::blink::RequestContextType context,
+ MixedContent::CheckModeForPlugin check_mode_for_plugin) {
+ switch (context) {
+ // "Optionally-blockable" mixed content
+ case mojom::RequestContextType::AUDIO:
+ case mojom::RequestContextType::IMAGE:
+ case mojom::RequestContextType::VIDEO:
+ return mojom::blink::MixedContentContextType::kOptionallyBlockable;
+
+ // Plugins! Oh how dearly we love plugin-loaded content!
+ case mojom::RequestContextType::PLUGIN: {
+ return check_mode_for_plugin == MixedContent::CheckModeForPlugin::kStrict
+ ? mojom::blink::MixedContentContextType::kBlockable
+ : mojom::blink::MixedContentContextType::kOptionallyBlockable;
+ }
+
+ // "Blockable" mixed content
+ case mojom::RequestContextType::BEACON:
+ case mojom::RequestContextType::CSP_REPORT:
+ case mojom::RequestContextType::EMBED:
+ case mojom::RequestContextType::EVENT_SOURCE:
+ case mojom::RequestContextType::FAVICON:
+ case mojom::RequestContextType::FETCH:
+ case mojom::RequestContextType::FONT:
+ case mojom::RequestContextType::FORM:
+ case mojom::RequestContextType::FRAME:
+ case mojom::RequestContextType::HYPERLINK:
+ case mojom::RequestContextType::IFRAME:
+ case mojom::RequestContextType::IMAGE_SET:
+ case mojom::RequestContextType::IMPORT:
+ case mojom::RequestContextType::INTERNAL:
+ case mojom::RequestContextType::LOCATION:
+ case mojom::RequestContextType::MANIFEST:
+ case mojom::RequestContextType::OBJECT:
+ case mojom::RequestContextType::PING:
+ case mojom::RequestContextType::PREFETCH:
+ case mojom::RequestContextType::SCRIPT:
+ case mojom::RequestContextType::SERVICE_WORKER:
+ case mojom::RequestContextType::SHARED_WORKER:
+ case mojom::RequestContextType::STYLE:
+ case mojom::RequestContextType::SUBRESOURCE:
+ case mojom::RequestContextType::SUBRESOURCE_WEBBUNDLE:
+ case mojom::RequestContextType::TRACK:
+ case mojom::RequestContextType::WORKER:
+ case mojom::RequestContextType::XML_HTTP_REQUEST:
+ case mojom::RequestContextType::XSLT:
+ return mojom::blink::MixedContentContextType::kBlockable;
+
+ // FIXME: Contexts that we should block, but don't currently.
+ // https://crbug.com/388650
+ case mojom::RequestContextType::DOWNLOAD:
+ return mojom::blink::MixedContentContextType::kShouldBeBlockable;
+
+ case mojom::RequestContextType::UNSPECIFIED:
+ NOTREACHED();
+ }
+ NOTREACHED();
+ return mojom::blink::MixedContentContextType::kBlockable;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/mixed_content.h b/chromium/third_party/blink/renderer/platform/loader/mixed_content.h
new file mode 100644
index 00000000000..c27703e154a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/mixed_content.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_MIXED_CONTENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_MIXED_CONTENT_H_
+
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/loader/mixed_content.mojom-blink-forward.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+// Helper functions related to mixed content checks.
+class MixedContent {
+ public:
+ enum class CheckModeForPlugin { kStrict, kLax };
+
+ PLATFORM_EXPORT static mojom::blink::MixedContentContextType
+ ContextTypeFromRequestContext(mojom::RequestContextType,
+ CheckModeForPlugin);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_MIXED_CONTENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h b/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
index 217da2c4bd9..4d5e3fd4841 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
@@ -38,6 +38,13 @@ class MockFetchContext : public FetchContext {
uint64_t GetTransferSize() const { return transfer_size_; }
+ void set_blocked_urls(Vector<String> blocked_urls) {
+ blocked_urls_ = std::move(blocked_urls);
+ }
+ void set_tagged_urls(Vector<String> tagged_urls) {
+ tagged_urls_ = std::move(tagged_urls);
+ }
+
bool AllowImage(bool images_enabled, const KURL&) const override {
return true;
}
@@ -51,6 +58,21 @@ class MockFetchContext : public FetchContext {
const override {
return base::nullopt;
}
+ base::Optional<ResourceRequestBlockedReason>
+ CanRequestBasedOnSubresourceFilterOnly(
+ ResourceType type,
+ const ResourceRequest& resource_request,
+ const KURL& url,
+ const ResourceLoaderOptions& options,
+ ReportingDisposition reporting_disposition,
+ const base::Optional<ResourceRequest::RedirectInfo>& redirect_info)
+ const override {
+ if (blocked_urls_.Contains(url.GetString())) {
+ return ResourceRequestBlockedReason::kSubresourceFilter;
+ }
+
+ return base::nullopt;
+ }
base::Optional<ResourceRequestBlockedReason> CheckCSPForRequest(
mojom::blink::RequestContextType,
network::mojom::RequestDestination request_destination,
@@ -79,6 +101,15 @@ class MockFetchContext : public FetchContext {
weak_wrapper_resource_load_info_notifier_->AsWeakPtr());
}
+ bool CalculateIfAdSubresource(
+ const ResourceRequestHead& resource_request,
+ const base::Optional<KURL>& alias_url,
+ ResourceType type,
+ const FetchInitiatorInfo& initiator_info) override {
+ const KURL url = alias_url ? alias_url.value() : resource_request.Url();
+ return tagged_urls_.Contains(url.GetString());
+ }
+
void SetResourceLoadInfoNotifier(
mojom::ResourceLoadInfoNotifier* resource_load_info_notifier) {
resource_load_info_notifier_ = resource_load_info_notifier;
@@ -89,6 +120,8 @@ class MockFetchContext : public FetchContext {
mojom::ResourceLoadInfoNotifier* resource_load_info_notifier_ = nullptr;
std::unique_ptr<WeakWrapperResourceLoadInfoNotifier>
weak_wrapper_resource_load_info_notifier_;
+ Vector<String> blocked_urls_;
+ Vector<String> tagged_urls_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc
index 0931e9c4fe7..3a20dfa3286 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.cc
@@ -43,57 +43,4 @@ MockResource::MockResource(const ResourceRequest& request,
const ResourceLoaderOptions& options)
: Resource(request, ResourceType::kMock, options) {}
-CachedMetadataHandler* MockResource::CreateCachedMetadataHandler(
- std::unique_ptr<CachedMetadataSender> send_callback) {
- return MakeGarbageCollected<MockCacheHandler>(std::move(send_callback));
-}
-
-void MockResource::SetSerializedCachedMetadata(mojo_base::BigBuffer data) {
- // Resource ignores the cached metadata.
- Resource::SetSerializedCachedMetadata(mojo_base::BigBuffer());
- MockCacheHandler* cache_handler =
- static_cast<MockCacheHandler*>(Resource::CacheHandler());
- if (cache_handler) {
- cache_handler->Set(data.data(), data.size());
- }
-}
-
-void MockResource::SendCachedMetadata(const uint8_t* data, size_t size) {
- MockCacheHandler* cache_handler =
- static_cast<MockCacheHandler*>(Resource::CacheHandler());
- if (cache_handler) {
- cache_handler->Set(data, size);
- cache_handler->Send();
- }
-}
-
-MockCacheHandler* MockResource::CacheHandler() {
- return static_cast<MockCacheHandler*>(Resource::CacheHandler());
-}
-
-MockCacheHandler::MockCacheHandler(
- std::unique_ptr<CachedMetadataSender> send_callback)
- : send_callback_(std::move(send_callback)) {}
-
-void MockCacheHandler::Set(const uint8_t* data, size_t size) {
- data_.emplace();
- data_->Append(data, SafeCast<wtf_size_t>(size));
-}
-
-void MockCacheHandler::ClearCachedMetadata(
- CachedMetadataHandler::ClearCacheType cache_type) {
- if (cache_type == CachedMetadataHandler::kClearPersistentStorage) {
- Send();
- }
- data_.reset();
-}
-
-void MockCacheHandler::Send() {
- if (data_) {
- send_callback_->Send(data_->data(), data_->size());
- } else {
- send_callback_->Send(nullptr, 0);
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
index 991860b1079..2e522f8c0dc 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
@@ -6,9 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_TESTING_MOCK_RESOURCE_H_
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
@@ -16,27 +14,6 @@ class FetchParameters;
class ResourceFetcher;
struct ResourceLoaderOptions;
-// Mocked cache handler class used by MockResource to test the caching behaviour
-// of Resource.
-class MockCacheHandler : public CachedMetadataHandler {
- public:
- MockCacheHandler(std::unique_ptr<CachedMetadataSender> send_callback);
-
- void Set(const uint8_t* data, size_t);
- void ClearCachedMetadata(CachedMetadataHandler::ClearCacheType) override;
- void Send();
-
- String Encoding() const override { return "mock encoding"; }
- bool IsServedFromCacheStorage() const override { return false; }
- void OnMemoryDump(WebProcessMemoryDump* pmd,
- const String& dump_prefix) const override {}
- size_t GetCodeCacheSize() const override { return 0; }
-
- private:
- std::unique_ptr<CachedMetadataSender> send_callback_;
- base::Optional<Vector<uint8_t>> data_;
-};
-
// Mocked Resource sub-class for testing. MockResource class can pretend a type
// of Resource sub-class in a simple way. You should not expect anything
// complicated to emulate actual sub-resources, but you may be able to use this
@@ -49,14 +26,6 @@ class MockResource final : public Resource {
explicit MockResource(const KURL&);
explicit MockResource(const ResourceRequest&);
MockResource(const ResourceRequest&, const ResourceLoaderOptions&);
-
- CachedMetadataHandler* CreateCachedMetadataHandler(
- std::unique_ptr<CachedMetadataSender> send_callback) override;
- void SetSerializedCachedMetadata(mojo_base::BigBuffer data) override;
-
- MockCacheHandler* CacheHandler();
-
- void SendCachedMetadata(const uint8_t*, size_t);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h b/chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h
index e361dceaf2c..806f9847b9e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/test_loader_factory.h
@@ -9,6 +9,7 @@
#include <utility>
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
@@ -32,7 +33,8 @@ class TestLoaderFactory : public ResourceFetcher::LoaderFactory {
const ResourceRequest& request,
const ResourceLoaderOptions& options,
scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
+ WebBackForwardCacheLoaderHelper back_forward_cache_loader_helper)
override {
WrappedResourceRequest wrapped(request);
return url_loader_factory_->CreateURLLoader(
@@ -40,7 +42,9 @@ class TestLoaderFactory : public ResourceFetcher::LoaderFactory {
scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
std::move(freezable_task_runner)),
scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
- std::move(unfreezable_task_runner)));
+ std::move(unfreezable_task_runner)),
+ /*keep_alive_handle=*/mojo::NullRemote(),
+ back_forward_cache_loader_helper);
}
std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override {
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc b/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc
index f4b9ec2c790..2b3c3aa0411 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h"
+#include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -18,7 +19,9 @@ WebURLLoaderFactoryWithMock::~WebURLLoaderFactoryWithMock() = default;
std::unique_ptr<WebURLLoader> WebURLLoaderFactoryWithMock::CreateURLLoader(
const WebURLRequest& request,
std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>,
- std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>) {
+ std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>,
+ CrossVariantMojoRemote<blink::mojom::KeepAliveHandleInterfaceBase>,
+ WebBackForwardCacheLoaderHelper) {
return mock_factory_->CreateURLLoader();
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h b/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h
index 2a7ad5f5c3e..769ae0dd84a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h
@@ -22,8 +22,9 @@ class WebURLLoaderFactoryWithMock : public WebURLLoaderFactory {
std::unique_ptr<WebURLLoader> CreateURLLoader(
const WebURLRequest&,
std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>,
- std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>)
- override;
+ std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>,
+ CrossVariantMojoRemote<blink::mojom::KeepAliveHandleInterfaceBase>,
+ WebBackForwardCacheLoaderHelper) override;
private:
// Not owned. The mock factory should outlive |this|.
diff --git a/chromium/third_party/blink/renderer/platform/loader/web_url_request_extra_data.cc b/chromium/third_party/blink/renderer/platform/loader/web_url_request_extra_data.cc
index dffa242e974..9a341b2a439 100644
--- a/chromium/third_party/blink/renderer/platform/loader/web_url_request_extra_data.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/web_url_request_extra_data.cc
@@ -19,7 +19,6 @@ void WebURLRequestExtraData::CopyToResourceRequest(
request->is_main_frame = is_main_frame_;
request->transition_type = transition_type_;
request->originated_from_service_worker = originated_from_service_worker_;
- request->force_ignore_site_for_cookies = force_ignore_site_for_cookies_;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/web_url_request_util.cc b/chromium/third_party/blink/renderer/platform/loader/web_url_request_util.cc
index d89f39a78f8..f6f6459b6a8 100644
--- a/chromium/third_party/blink/renderer/platform/loader/web_url_request_util.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/web_url_request_util.cc
@@ -15,15 +15,17 @@
#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/mixed_content.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-blink.h"
+#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_http_header_visitor.h"
-#include "third_party/blink/public/platform/web_mixed_content.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/renderer/platform/loader/mixed_content.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -75,29 +77,31 @@ WebHTTPBody GetWebHTTPBodyForRequestBody(
http_body.SetContainsPasswordData(input.contains_sensitive_info());
for (auto& element : *input.elements()) {
switch (element.type()) {
- case network::mojom::blink::DataElementType::kBytes:
+ case network::DataElement::Tag::kBytes: {
+ const auto& bytes = element.As<network::DataElementBytes>().bytes();
http_body.AppendData(
- WebData(element.bytes(), SafeCast<size_t>(element.length())));
+ WebData(reinterpret_cast<const char*>(bytes.data()), bytes.size()));
break;
- case network::mojom::blink::DataElementType::kFile: {
+ }
+ case network::DataElement::Tag::kFile: {
+ const auto& file = element.As<network::DataElementFile>();
base::Optional<base::Time> modification_time;
- if (!element.expected_modification_time().is_null())
- modification_time = element.expected_modification_time();
+ if (!file.expected_modification_time().is_null())
+ modification_time = file.expected_modification_time();
http_body.AppendFileRange(
- FilePathToWebString(element.path()), element.offset(),
- (element.length() != std::numeric_limits<uint64_t>::max())
- ? element.length()
+ FilePathToWebString(file.path()), file.offset(),
+ (file.length() != std::numeric_limits<uint64_t>::max())
+ ? file.length()
: -1,
modification_time);
break;
}
- case network::mojom::blink::DataElementType::kDataPipe: {
- http_body.AppendDataPipe(element.CloneDataPipeGetter());
+ case network::DataElement::Tag::kDataPipe: {
+ http_body.AppendDataPipe(
+ element.As<network::DataElementDataPipe>().CloneDataPipeGetter());
break;
}
- case network::mojom::blink::DataElementType::kUnknown:
- case network::mojom::blink::DataElementType::kChunkedDataPipe:
- case network::mojom::blink::DataElementType::kReadOnceStream:
+ case network::DataElement::Tag::kChunkedDataPipe:
NOTREACHED();
break;
}
@@ -148,24 +152,19 @@ scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody(
case HTTPBodyElementType::kTypeBlob: {
DCHECK(element.optional_blob);
mojo::Remote<mojom::blink::Blob> blob_remote(
- mojo::PendingRemote<mojom::blink::Blob>(
- std::move(element.optional_blob)));
+ std::move(element.optional_blob));
mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
data_pipe_getter_remote;
blob_remote->AsDataPipeGetter(
data_pipe_getter_remote.InitWithNewPipeAndPassReceiver());
request_body->AppendDataPipe(
- mojo::PendingRemote<network::mojom::DataPipeGetter>(
- data_pipe_getter_remote.PassPipe(), 0u));
+ ToCrossVariantMojoType(std::move(data_pipe_getter_remote)));
break;
}
case HTTPBodyElementType::kTypeDataPipe: {
- // Convert the raw message pipe to
- // mojo::Remote<network::mojom::DataPipeGetter> data_pipe_getter.
mojo::Remote<network::mojom::blink::DataPipeGetter> data_pipe_getter(
- mojo::PendingRemote<network::mojom::blink::DataPipeGetter>(
- std::move(element.data_pipe_getter)));
+ std::move(element.data_pipe_getter));
// Set the cloned DataPipeGetter to the output |request_body|, while
// keeping the original message pipe back in the input |httpBody|. This
@@ -175,8 +174,7 @@ scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody(
cloned_getter;
data_pipe_getter->Clone(cloned_getter.InitWithNewPipeAndPassReceiver());
request_body->AppendDataPipe(
- mojo::PendingRemote<network::mojom::DataPipeGetter>(
- cloned_getter.PassPipe(), 0u));
+ ToCrossVariantMojoType(std::move(cloned_getter)));
element.data_pipe_getter = data_pipe_getter.Unbind();
break;
}
@@ -199,10 +197,10 @@ network::mojom::blink::RequestDestination GetRequestDestinationForWebURLRequest(
request.GetRequestDestination());
}
-WebMixedContentContextType GetMixedContentContextTypeForWebURLRequest(
- const WebURLRequest& request) {
- return WebMixedContent::ContextTypeFromRequestContext(
- request.GetRequestContext(), WebMixedContent::CheckModeForPlugin::kLax);
+mojom::blink::MixedContentContextType
+GetMixedContentContextTypeForWebURLRequest(const WebURLRequest& request) {
+ return MixedContent::ContextTypeFromRequestContext(
+ request.GetRequestContext(), MixedContent::CheckModeForPlugin::kLax);
}
} // namespace blink