Commit f528ce0d authored by Ilya Sherman's avatar Ilya Sherman Committed by Commit Bot

Report the state of the omnibox OnDeviceHead provider in an HTTP header

This header is only sent to Google domains served over HTTPS,
and only when the omnibox provider is in a non-default state.

Bug: 1079341

Change-Id: Ic75978f337dc86f134943fe81f0f47bd7a1a5259
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2181663
Commit-Queue: Ilya Sherman <isherman@chromium.org>
Reviewed-by: default avatarJustin Donnelly <jdonnelly@chromium.org>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#766546}
parent 952c6653
...@@ -11,6 +11,7 @@ static_library("net") { ...@@ -11,6 +11,7 @@ static_library("net") {
] ]
public_deps = [ public_deps = [
":omnibox_http_headers",
"//components/variations", "//components/variations",
"//net", "//net",
"//services/network/public/cpp:cpp", "//services/network/public/cpp:cpp",
...@@ -35,3 +36,32 @@ static_library("net") { ...@@ -35,3 +36,32 @@ static_library("net") {
deps += [ "//third_party/blink/public/common" ] deps += [ "//third_party/blink/public/common" ]
} }
} }
component("omnibox_http_headers") {
output_name = "omnibox_http_headers"
defines = [ "IS_OMNIBOX_HTTP_HEADERS_IMPL" ]
sources = [
"omnibox_http_headers.cc",
"omnibox_http_headers.h",
]
deps = [
"//base",
"//components/google/core/common",
"//net",
"//services/network/public/cpp:cpp",
"//services/network/public/cpp:cpp_base",
"//url",
]
# third_party/blink/public/common does not build on iOS
if (!is_ios) {
sources += [
"omnibox_url_loader_throttle.cc",
"omnibox_url_loader_throttle.h",
]
deps += [ "//third_party/blink/public/common" ]
}
}
// 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 "components/variations/net/omnibox_http_headers.h"
#include "base/metrics/field_trial.h"
#include "components/google/core/common/google_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "url/gurl.h"
namespace variations {
// The header used to report the state of the omnibox on-device search
// suggestions provider. This header is only set when the provider is in a
// non-default state, and only reports one of two possible values: "Enabled" or
// "Control".
const char kOmniboxOnDeviceSuggestionsHeader[] =
"X-Omnibox-On-Device-Suggestions";
// Whether to enable reporting the header. Included as a quick escape hatch in
// case of crashes.
const base::Feature kReportOmniboxOnDeviceSuggestionsHeader{
"ReportOmniboxOnDeviceSuggestionsHeader", base::FEATURE_ENABLED_BY_DEFAULT};
std::string GetHeaderValue() {
const std::string group =
base::FieldTrialList::FindFullName("OmniboxBundledExperimentV1");
// Search for a substring rather than comparing to an exact value so that
// group names can have prefixes (e.g., "Desktop", "Android") and suffixes
// (e.g., config versions).
if (group.find("ReportHttpHeader_Enabled") != std::string::npos) {
return "Enabled";
}
if (group.find("ReportHttpHeader_Control") != std::string::npos) {
return "Control";
}
return std::string();
}
// Returns whether the header should be sent for this URL. The header is only
// sent to Google domains served over HTTPS.
bool ShouldAppendHeader(const GURL& url) {
return url.SchemeIs(url::kHttpsScheme) &&
google_util::IsGoogleDomainUrl(
url, google_util::ALLOW_SUBDOMAIN,
google_util::DISALLOW_NON_STANDARD_PORTS);
}
void AppendOmniboxOnDeviceSuggestionsHeaderIfNeeded(
const GURL& url,
network::ResourceRequest* request) {
if (!base::FeatureList::IsEnabled(kReportOmniboxOnDeviceSuggestionsHeader))
return;
if (!ShouldAppendHeader(url))
return;
std::string header = GetHeaderValue();
if (header.empty())
return;
// Set the omnibox header to cors_exempt_headers rather than headers
// to be exempted from CORS checks.
request->cors_exempt_headers.SetHeaderIfMissing(
kOmniboxOnDeviceSuggestionsHeader, header);
}
} // namespace variations
// 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 COMPONENTS_VARIATIONS_NET_OMNIBOX_HTTP_HEADERS_H_
#define COMPONENTS_VARIATIONS_NET_OMNIBOX_HTTP_HEADERS_H_
#include <memory>
#include <string>
#include <vector>
#include "base/component_export.h"
#include "base/feature_list.h"
#include "build/build_config.h"
class GURL;
namespace network {
struct ResourceRequest;
}
namespace variations {
COMPONENT_EXPORT(OMNIBOX_HTTP_HEADERS)
extern const char kOmniboxOnDeviceSuggestionsHeader[];
COMPONENT_EXPORT(OMNIBOX_HTTP_HEADERS)
extern const base::Feature kReportOmniboxOnDeviceSuggestionsHeader;
// Returns the value to set for the header. Returns an empty string if the
// provider is not explicitly enabled nor disabled via a field trial, i.e. the
// header is only set to a non-empty value during experimentation.
COMPONENT_EXPORT(OMNIBOX_HTTP_HEADERS)
std::string GetHeaderValue();
// Returns whether the header should be sent for this URL. The header is only
// sent to Google domains served over HTTPS.
COMPONENT_EXPORT(OMNIBOX_HTTP_HEADERS)
bool ShouldAppendHeader(const GURL& url);
// Adds an HTTP header reporting whether the Omnibox on-device search
// suggestions provider is enabled. Only reported if the provider is in a
// non-default state and if the |url| is a Google domain. This method is safe to
// call both from browser and from child processes.
COMPONENT_EXPORT(OMNIBOX_HTTP_HEADERS)
void AppendOmniboxOnDeviceSuggestionsHeaderIfNeeded(
const GURL& url,
network::ResourceRequest* request);
} // namespace variations
#endif // COMPONENTS_VARIATIONS_NET_OMNIBOX_HTTP_HEADERS_H_
// 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 "components/variations/net/omnibox_url_loader_throttle.h"
#include "components/variations/net/omnibox_http_headers.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
namespace variations {
OmniboxURLLoaderThrottle::OmniboxURLLoaderThrottle() = default;
OmniboxURLLoaderThrottle::~OmniboxURLLoaderThrottle() = default;
// static
void OmniboxURLLoaderThrottle::AppendThrottleIfNeeded(
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>* throttles) {
if (!base::FeatureList::IsEnabled(kReportOmniboxOnDeviceSuggestionsHeader))
return;
// Don't add the URL loader throttle if there's no header to report. This is a
// minor optimization, and also prevents some noisy DCHECKs from failing in
// tests: https://cs.chromium.org/search/?q=crbug.com/845683
const std::string header = GetHeaderValue();
if (header.empty())
return;
throttles->push_back(std::make_unique<OmniboxURLLoaderThrottle>());
}
void OmniboxURLLoaderThrottle::DetachFromCurrentSequence() {}
void OmniboxURLLoaderThrottle::WillStartRequest(
network::ResourceRequest* request,
bool* defer) {
AppendOmniboxOnDeviceSuggestionsHeaderIfNeeded(request->url, request);
}
void OmniboxURLLoaderThrottle::WillRedirectRequest(
net::RedirectInfo* redirect_info,
const network::mojom::URLResponseHead& response_head,
bool* defer,
std::vector<std::string>* to_be_removed_headers,
net::HttpRequestHeaders* modified_headers,
net::HttpRequestHeaders* modified_cors_exempt_headers) {
// Note: No need to check the kReportOmniboxOnDeviceSuggestionsHeader feature
// state here, as this class is only instantiated when the feature is enabled.
if (!ShouldAppendHeader(redirect_info->new_url))
to_be_removed_headers->push_back(kOmniboxOnDeviceSuggestionsHeader);
}
} // namespace variations
// 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 COMPONENTS_VARIATIONS_NET_OMNIBOX_URL_LOADER_THROTTLE_H_
#define COMPONENTS_VARIATIONS_NET_OMNIBOX_URL_LOADER_THROTTLE_H_
#include <memory>
#include <vector>
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
namespace variations {
// This class is created per request. If the request is for a Google domain
// served over HTTPS, it adds a header describing the state of the omnibox
// on-device search suggestions provider, if that provider is in a non-default
// state. It also removes this header on redirect away from Google domains.
class COMPONENT_EXPORT(OMNIBOX_HTTP_HEADERS) OmniboxURLLoaderThrottle
: public blink::URLLoaderThrottle,
public base::SupportsWeakPtr<OmniboxURLLoaderThrottle> {
public:
OmniboxURLLoaderThrottle();
~OmniboxURLLoaderThrottle() override;
OmniboxURLLoaderThrottle(OmniboxURLLoaderThrottle&&) = delete;
OmniboxURLLoaderThrottle(const OmniboxURLLoaderThrottle&) = delete;
OmniboxURLLoaderThrottle& operator==(OmniboxURLLoaderThrottle&&) = delete;
OmniboxURLLoaderThrottle& operator==(const OmniboxURLLoaderThrottle&) =
delete;
// Adds a utility class that calls into the above function on web content
// navigations.
static void AppendThrottleIfNeeded(
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>* throttles);
private:
// blink::URLLoaderThrottle:
void DetachFromCurrentSequence() override;
void WillStartRequest(network::ResourceRequest* request,
bool* defer) override;
void WillRedirectRequest(
net::RedirectInfo* redirect_info,
const network::mojom::URLResponseHead& response_head,
bool* defer,
std::vector<std::string>* to_be_removed_headers,
net::HttpRequestHeaders* modified_headers,
net::HttpRequestHeaders* modified_cors_exempt_headers) override;
};
} // namespace variations
#endif // COMPONENTS_VARIATIONS_NET_OMNIBOX_URL_LOADER_THROTTLE_H_
...@@ -10,11 +10,13 @@ ...@@ -10,11 +10,13 @@
#include <vector> #include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/feature_list.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "components/google/core/common/google_util.h" #include "components/google/core/common/google_util.h"
#include "components/variations/net/omnibox_http_headers.h"
#include "components/variations/variations_http_header_provider.h" #include "components/variations/variations_http_header_provider.h"
#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_info.h" #include "net/url_request/redirect_info.h"
...@@ -87,6 +89,8 @@ class VariationsHeaderHelper { ...@@ -87,6 +89,8 @@ class VariationsHeaderHelper {
} }
bool AppendHeaderIfNeeded(const GURL& url, InIncognito incognito) { bool AppendHeaderIfNeeded(const GURL& url, InIncognito incognito) {
AppendOmniboxOnDeviceSuggestionsHeaderIfNeeded(url, resource_request_);
// Note the criteria for attaching client experiment headers: // Note the criteria for attaching client experiment headers:
// 1. We only transmit to Google owned domains which can evaluate // 1. We only transmit to Google owned domains which can evaluate
// experiments. // experiments.
...@@ -180,10 +184,13 @@ CreateSimpleURLLoaderWithVariationsHeaderUnknownSignedIn( ...@@ -180,10 +184,13 @@ CreateSimpleURLLoaderWithVariationsHeaderUnknownSignedIn(
} }
bool IsVariationsHeader(const std::string& header_name) { bool IsVariationsHeader(const std::string& header_name) {
return header_name == kClientDataHeader; return header_name == kClientDataHeader ||
header_name == kOmniboxOnDeviceSuggestionsHeader;
} }
bool HasVariationsHeader(const network::ResourceRequest& request) { bool HasVariationsHeader(const network::ResourceRequest& request) {
// Note: kOmniboxOnDeviceSuggestionsHeader is not listed because this function
// is only used for testing.
return request.cors_exempt_headers.HasHeader(kClientDataHeader); return request.cors_exempt_headers.HasHeader(kClientDataHeader);
} }
...@@ -194,6 +201,11 @@ bool ShouldAppendVariationsHeaderForTesting(const GURL& url) { ...@@ -194,6 +201,11 @@ bool ShouldAppendVariationsHeaderForTesting(const GURL& url) {
void UpdateCorsExemptHeaderForVariations( void UpdateCorsExemptHeaderForVariations(
network::mojom::NetworkContextParams* params) { network::mojom::NetworkContextParams* params) {
params->cors_exempt_header_list.push_back(kClientDataHeader); params->cors_exempt_header_list.push_back(kClientDataHeader);
if (base::FeatureList::IsEnabled(kReportOmniboxOnDeviceSuggestionsHeader)) {
params->cors_exempt_header_list.push_back(
kOmniboxOnDeviceSuggestionsHeader);
}
} }
} // namespace variations } // namespace variations
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "content/browser/loader/url_loader_throttles.h" #include "content/browser/loader/url_loader_throttles.h"
#include "components/variations/net/omnibox_url_loader_throttle.h"
#include "components/variations/net/variations_url_loader_throttle.h" #include "components/variations/net/variations_url_loader_throttle.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h" #include "content/public/browser/content_browser_client.h"
...@@ -23,6 +24,7 @@ CreateContentBrowserURLLoaderThrottles( ...@@ -23,6 +24,7 @@ CreateContentBrowserURLLoaderThrottles(
GetContentClient()->browser()->CreateURLLoaderThrottles( GetContentClient()->browser()->CreateURLLoaderThrottles(
request, browser_context, wc_getter, navigation_ui_data, request, browser_context, wc_getter, navigation_ui_data,
frame_tree_node_id); frame_tree_node_id);
variations::OmniboxURLLoaderThrottle::AppendThrottleIfNeeded(&throttles);
variations::VariationsURLLoaderThrottle::AppendThrottleIfNeeded( variations::VariationsURLLoaderThrottle::AppendThrottleIfNeeded(
browser_context->GetVariationsClient(), &throttles); browser_context->GetVariationsClient(), &throttles);
return throttles; return throttles;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "components/variations/net/omnibox_url_loader_throttle.h"
#include "components/variations/net/variations_url_loader_throttle.h" #include "components/variations/net/variations_url_loader_throttle.h"
#include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_thread.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
...@@ -48,6 +49,8 @@ VariationsRenderThreadObserver::~VariationsRenderThreadObserver() = default; ...@@ -48,6 +49,8 @@ VariationsRenderThreadObserver::~VariationsRenderThreadObserver() = default;
// static // static
void VariationsRenderThreadObserver::AppendThrottleIfNeeded( void VariationsRenderThreadObserver::AppendThrottleIfNeeded(
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>* throttles) { std::vector<std::unique_ptr<blink::URLLoaderThrottle>>* throttles) {
variations::OmniboxURLLoaderThrottle::AppendThrottleIfNeeded(throttles);
std::string variations_header = GetVariationsData()->GetVariationsHeader(); std::string variations_header = GetVariationsData()->GetVariationsHeader();
if (!variations_header.empty()) { if (!variations_header.empty()) {
throttles->push_back( throttles->push_back(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment