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 c8e468f41930dc8e31533e086d72743e12d134f1..5b54e21568019b108d92c28086b8d73db98fc704 100644 --- a/services/network/public/cpp/resource_request.cc +++ b/services/network/public/cpp/resource_request.cc @@ -233,6 +233,7 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const { do_not_prompt_for_login == request.do_not_prompt_for_login && is_outermost_main_frame == request.is_outermost_main_frame && transition_type == request.transition_type && + report_raw_headers == request.report_raw_headers && previews_state == request.previews_state && upgrade_if_insecure == request.upgrade_if_insecure && is_revalidating == request.is_revalidating && diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h index 9af8605aaab177daf89524680cb88455fcb48d04..9c851c96588342b245b24fed51d9241f8da7ffcc 100644 --- a/services/network/public/cpp/resource_request.h +++ b/services/network/public/cpp/resource_request.h @@ -158,6 +158,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest { bool do_not_prompt_for_login = false; bool is_outermost_main_frame = false; int transition_type = 0; + bool report_raw_headers = false; int previews_state = 0; bool upgrade_if_insecure = false; bool is_revalidating = false; diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc index 10295a165e2131b7cd5bff996f36f2214db7a125..2d1bb21bf5813125397a93d368de031b11bb4bbb 100644 --- a/services/network/public/cpp/url_request_mojom_traits.cc +++ b/services/network/public/cpp/url_request_mojom_traits.cc @@ -209,6 +209,7 @@ bool StructTraits< out->do_not_prompt_for_login = data.do_not_prompt_for_login(); out->is_outermost_main_frame = data.is_outermost_main_frame(); out->transition_type = data.transition_type(); + out->report_raw_headers = data.report_raw_headers(); out->previews_state = data.previews_state(); out->upgrade_if_insecure = data.upgrade_if_insecure(); out->is_revalidating = data.is_revalidating(); diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h index b4f785570ffab62087ef9be3d18cecb6c747fa38..f6ff5ebc9808e230ed358203c5d0024c676bcd85 100644 --- a/services/network/public/cpp/url_request_mojom_traits.h +++ b/services/network/public/cpp/url_request_mojom_traits.h @@ -269,6 +269,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) static int32_t transition_type(const network::ResourceRequest& request) { return request.transition_type; } + static bool report_raw_headers(const network::ResourceRequest& request) { + return request.report_raw_headers; + } static int32_t previews_state(const network::ResourceRequest& request) { return request.previews_state; } diff --git a/services/network/public/mojom/url_request.mojom b/services/network/public/mojom/url_request.mojom index 05cc03e830d2805d6d572a38e2606de0f346b6bd..75b8da2f1141dffa34d01e84e339b791fdd60664 100644 --- a/services/network/public/mojom/url_request.mojom +++ b/services/network/public/mojom/url_request.mojom @@ -312,6 +312,9 @@ struct URLRequest { // about this. int32 transition_type; + // Whether to provide unfiltered response headers. + bool report_raw_headers; + // Whether or not to request a Preview version of the resource or let the // browser decide. // Note: this is an enum of type PreviewsState. diff --git a/services/network/public/mojom/url_response_head.mojom b/services/network/public/mojom/url_response_head.mojom index 3d2bcc3e81eb42f645fa4e8b1425cb5c54cfd3a1..4cdbe0e38609abfd0b0b5856deb8b2dd5c91ead8 100644 --- a/services/network/public/mojom/url_response_head.mojom +++ b/services/network/public/mojom/url_response_head.mojom @@ -8,6 +8,7 @@ import "mojo/public/mojom/base/time.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; import "services/network/public/mojom/fetch_api.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/network_param.mojom"; @@ -28,6 +29,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 6805b5f3976f60e0cc72634f71bcb21879ffbde1..4d60c127bec00859ed523ca652336239ab71ae00 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc @@ -603,6 +603,7 @@ URLLoader::URLLoader( mojo::SimpleWatcher::ArmingPolicy::MANUAL, base::SequencedTaskRunnerHandle::Get()), per_factory_corb_state_(context.GetMutableCorbState()), + report_raw_headers_(request.report_raw_headers), devtools_request_id_(request.devtools_request_id), request_mode_(request.mode), request_credentials_mode_(request.credentials_mode), @@ -792,7 +793,7 @@ URLLoader::URLLoader( url_request_->SetRequestHeadersCallback(base::BindRepeating( &URLLoader::SetRawRequestHeadersAndNotify, base::Unretained(this))); - if (devtools_request_id()) { + if (devtools_request_id() || report_raw_headers_) { url_request_->SetResponseHeadersCallback(base::BindRepeating( &URLLoader::SetRawResponseHeaders, base::Unretained(this))); } @@ -1541,6 +1542,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(); // Parse and remove the Trust Tokens response headers, if any are expected, diff --git a/services/network/url_loader.h b/services/network/url_loader.h index 158eaacb1bf69afad16107491851dab750df9606..eff061c729bed4b8f3b41699f66d087416b08f47 100644 --- a/services/network/url_loader.h +++ b/services/network/url_loader.h @@ -518,6 +518,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader std::unique_ptr resource_scheduler_request_handle_; + // Whether client requested raw headers. + bool report_raw_headers_ = false; bool enable_reporting_raw_headers_ = false; bool seen_raw_request_headers_ = false; scoped_refptr raw_response_headers_;