From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 17 Aug 2021 22:42:42 -0700 Subject: feat: expose raw response headers from URLLoader With https://chromium-review.googlesource.com/c/chromium/src/+/2856099 unfiltered response headers are only available via trusted channel through //services/network/public/mojom/devtools_observer.mojom. https://github.com/electron/electron/pull/30503/commits/28f4da1582d046e96cb58f3cbb590503e89dfd0d was an attempt to use this interface but given the original response is signalled on a different interface via URLLoaderClient::OnReceiveResponse it is harder to sync these data from two different channels for a synchronous event emitted on the SimpleURLLoaderWrapper::OnResponseStarted. This patch does the minimal approach to add back the raw response headers, moving forward we should find a way in upstream to provide access to these headers for loader clients created on the browser process. diff --git a/services/network/public/cpp/resource_request.cc b/services/network/public/cpp/resource_request.cc index dd0ebad1fdcadab06b25df192a85153d1e65e141..7716dca3cdd57d484b8499b80e50e0c8accc510f 100644 --- a/services/network/public/cpp/resource_request.cc +++ b/services/network/public/cpp/resource_request.cc @@ -197,6 +197,7 @@ ResourceRequest::TrustedParams& ResourceRequest::TrustedParams::operator=( allow_cookies_from_browser = other.allow_cookies_from_browser; include_request_cookies_with_response = other.include_request_cookies_with_response; + report_raw_headers = other.report_raw_headers; enabled_client_hints = other.enabled_client_hints; cookie_observer = Clone(&const_cast&>( @@ -232,6 +233,7 @@ bool ResourceRequest::TrustedParams::EqualsForTesting( const TrustedParams& other) const { return isolation_info.IsEqualForTesting(other.isolation_info) && disable_secure_dns == other.disable_secure_dns && + report_raw_headers == other.report_raw_headers && has_user_activation == other.has_user_activation && allow_cookies_from_browser == other.allow_cookies_from_browser && include_request_cookies_with_response == diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h index 3fa1c79443ca23ad6b25e38daf6e95e8a899740c..67c5a7b55569704167fe089d1d3d5c24f666a429 100644 --- a/services/network/public/cpp/resource_request.h +++ b/services/network/public/cpp/resource_request.h @@ -98,6 +98,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest { bool has_user_activation = false; bool allow_cookies_from_browser = false; bool include_request_cookies_with_response = false; + bool report_raw_headers = false; std::optional enabled_client_hints; mojo::PendingRemote cookie_observer; mojo::PendingRemote trust_token_observer; diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc index 646be484e4d5b3b917bed0ee2d0a52fdf57a8291..b49035fab82ddb29e211e1e215c70aab0a625222 100644 --- a/services/network/public/cpp/url_request_mojom_traits.cc +++ b/services/network/public/cpp/url_request_mojom_traits.cc @@ -67,6 +67,7 @@ bool StructTraitsallow_cookies_from_browser = data.allow_cookies_from_browser(); out->include_request_cookies_with_response = data.include_request_cookies_with_response(); + out->report_raw_headers = data.report_raw_headers(); if (!data.ReadEnabledClientHints(&out->enabled_client_hints)) { return false; } diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h index 9867e5115459f6d0a074d79183e53c3dba0187db..06ec0cea64750057b67108fbfeb1f9d850b0793f 100644 --- a/services/network/public/cpp/url_request_mojom_traits.h +++ b/services/network/public/cpp/url_request_mojom_traits.h @@ -108,6 +108,10 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) const network::ResourceRequest::TrustedParams& trusted_params) { return trusted_params.include_request_cookies_with_response; } + static bool report_raw_headers( + const network::ResourceRequest::TrustedParams& trusted_params) { + return trusted_params.report_raw_headers; + } static const std::optional< network::ResourceRequest::TrustedParams::EnabledClientHints>& enabled_client_hints( diff --git a/services/network/public/mojom/url_request.mojom b/services/network/public/mojom/url_request.mojom index affb80d9ffcc8da3f572b1a1461d2cd648ef3376..3f6301b1732171073c5fb072feaf12e3fb55c74c 100644 --- a/services/network/public/mojom/url_request.mojom +++ b/services/network/public/mojom/url_request.mojom @@ -111,6 +111,9 @@ struct TrustedUrlRequestParams { // client which should not be able to see them. bool include_request_cookies_with_response = false; + // [Electron] Whether to provide unfiltered response headers. + bool report_raw_headers; + // Enabled Client Hints to be evaluated quickly within the network layer // when it receives the AcceptCHFrame. EnabledClientHints? enabled_client_hints; diff --git a/services/network/public/mojom/url_response_head.mojom b/services/network/public/mojom/url_response_head.mojom index 13a211107294e856616d1626fa1dc9c79eb5646c..549a36886d665c1a8100f09b7a86c8dc13c80e84 100644 --- a/services/network/public/mojom/url_response_head.mojom +++ b/services/network/public/mojom/url_response_head.mojom @@ -14,6 +14,7 @@ import "services/network/public/mojom/encoded_body_length.mojom"; import "services/network/public/mojom/fetch_api.mojom"; import "services/network/public/mojom/http_request_headers.mojom"; import "services/network/public/mojom/ip_address_space.mojom"; +import "services/network/public/mojom/http_raw_headers.mojom"; import "services/network/public/mojom/ip_endpoint.mojom"; import "services/network/public/mojom/load_timing_info.mojom"; import "services/network/public/mojom/load_timing_internal_info.mojom"; @@ -53,6 +54,9 @@ struct URLResponseHead { // The response headers or NULL if the URL type does not support headers. HttpResponseHeaders headers; + // Actual response headers, as obtained from the network stack. + array raw_response_headers; + // The mime type of the response. This may be a derived value. string mime_type; diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index c71abe34bb2c2d7cc30e7f8df81b8d71ebfd076e..8b03d8379ee81fa45d7e127d153717b1abb1475e 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc @@ -386,6 +386,9 @@ URLLoader::URLLoader( mojo::SimpleWatcher::ArmingPolicy::MANUAL, TaskRunner(request.priority)), per_factory_orb_state_(context.GetMutableOrbState()), + report_raw_headers_( + request.trusted_params && + request.trusted_params->report_raw_headers), devtools_request_id_(request.devtools_request_id), options_(PopulateOptions(options, factory_params_->is_orb_enabled, @@ -554,7 +557,7 @@ void URLLoader::SetUpUrlRequestCallbacks( &URLLoader::IsSharedDictionaryReadAllowed, base::Unretained(this))); } - if (devtools_request_id()) { + if (devtools_request_id() || report_raw_headers_) { url_request_->SetResponseHeadersCallback(base::BindRepeating( &URLLoader::SetRawResponseHeaders, base::Unretained(this))); } @@ -1151,6 +1154,19 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) { } response_ = BuildResponseHead(); + if (raw_response_headers_ && report_raw_headers_) { + std::vector header_array; + size_t iterator = 0; + std::string name, value; + while (raw_response_headers_->EnumerateHeaderLines(&iterator, &name, &value)) { + network::mojom::HttpRawHeaderPairPtr pair = + network::mojom::HttpRawHeaderPair::New(); + pair->key = name; + pair->value = value; + header_array.push_back(std::move(pair)); + } + response_->raw_response_headers = std::move(header_array); + } DispatchOnRawResponse(); ad_auction_event_record_request_helper_.HandleResponse( diff --git a/services/network/url_loader.h b/services/network/url_loader.h index f437df6e20b7d4e28f5e57e2134c5c7fa9da2bdc..661fef04f6b76abef852ba8eef63b1f78b01652c 100644 --- a/services/network/url_loader.h +++ b/services/network/url_loader.h @@ -624,6 +624,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader std::unique_ptr resource_scheduler_request_handle_; + // Whether client requested raw headers. + bool report_raw_headers_ = false; scoped_refptr raw_response_headers_; std::unique_ptr upload_progress_tracker_;