diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/components/variations/net | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/variations/net')
5 files changed, 279 insertions, 36 deletions
diff --git a/chromium/components/variations/net/variations_command_line_unittest.cc b/chromium/components/variations/net/variations_command_line_unittest.cc index 1a7ef70e90e..2ca4a019a86 100644 --- a/chromium/components/variations/net/variations_command_line_unittest.cc +++ b/chromium/components/variations/net/variations_command_line_unittest.cc @@ -22,8 +22,7 @@ TEST(VariationsCommandLineTest, TestGetVariationsCommandLine) { std::string disable_feature_list = "feature2<trial2"; AssociateParamsFromString(param_list); - base::FieldTrialList::CreateTrialsFromString(trial_list, - std::set<std::string>()); + base::FieldTrialList::CreateTrialsFromString(trial_list); base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine(enable_feature_list, disable_feature_list); diff --git a/chromium/components/variations/net/variations_http_headers.cc b/chromium/components/variations/net/variations_http_headers.cc index c4f4f56d837..6f733ee3fc1 100644 --- a/chromium/components/variations/net/variations_http_headers.cc +++ b/chromium/components/variations/net/variations_http_headers.cc @@ -4,20 +4,20 @@ #include "components/variations/net/variations_http_headers.h" -#include <stddef.h> - #include <utility> #include <vector> #include "base/bind.h" #include "base/feature_list.h" #include "base/macros.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/string_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 "net/base/isolation_info.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/redirect_info.h" #include "services/network/public/cpp/resource_request.h" @@ -33,44 +33,147 @@ const char kClientDataHeader[] = "X-Client-Data"; namespace { -// The result of checking if a URL should have variations headers appended. +// The result of checking whether a request to a URL should have variations +// headers appended to it. +// // This enum is used to record UMA histogram values, and should not be // reordered. -enum URLValidationResult { - INVALID_URL, - NOT_HTTPS, - NOT_GOOGLE_DOMAIN, - SHOULD_APPEND, - NEITHER_HTTP_HTTPS, - IS_GOOGLE_NOT_HTTPS, - URL_VALIDATION_RESULT_SIZE, +enum class URLValidationResult { + kNotValidInvalidUrl = 0, + // kNotValidNotHttps = 1, // Deprecated. + kNotValidNotGoogleDomain = 2, + kShouldAppend = 3, + kNotValidNeitherHttpHttps = 4, + kNotValidIsGoogleNotHttps = 5, + kMaxValue = kNotValidIsGoogleNotHttps, +}; + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum RequestContextCategory { + // First-party contexts. + kBrowserInitiated = 0, + kInternalChromePageInitiated = 1, + kGooglePageInitiated = 2, + kGoogleSubFrameOnGooglePageInitiated = 3, + // Third-party contexts. + kNonGooglePageInitiatedFromRequestInitiator = 4, + kNoTrustedParams = 5, + kNoIsolationInfo = 6, + kGoogleSubFrameOnNonGooglePageInitiated = 7, + kNonGooglePageInitiatedFromFrameOrigin = 8, + kMaxValue = kNonGooglePageInitiatedFromFrameOrigin, }; -void LogUrlValidationHistogram(URLValidationResult result) { - UMA_HISTOGRAM_ENUMERATION("Variations.Headers.URLValidationResult", result, - URL_VALIDATION_RESULT_SIZE); +void LogRequestContextHistogram(RequestContextCategory result) { + base::UmaHistogramEnumeration("Variations.Headers.RequestContextCategory", + result); +} + +// Returns a URLValidationResult for |url|. A valid URL for headers has the +// following qualities: (i) it is well-formed, (ii) its scheme is HTTPS, and +// (iii) it has a Google-associated domain. +URLValidationResult GetUrlValidationResult(const GURL& url) { + if (!url.is_valid()) + return URLValidationResult::kNotValidInvalidUrl; + + if (!url.SchemeIsHTTPOrHTTPS()) + return URLValidationResult::kNotValidNeitherHttpHttps; + + if (!google_util::IsGoogleAssociatedDomainUrl(url)) + return URLValidationResult::kNotValidNotGoogleDomain; + + // HTTPS is checked here, rather than before the IsGoogleAssociatedDomainUrl() + // check, to know how many Google domains are rejected by the change to append + // headers to only HTTPS requests. + if (!url.SchemeIs(url::kHttpsScheme)) + return URLValidationResult::kNotValidIsGoogleNotHttps; + + return URLValidationResult::kShouldAppend; +} + +// Returns true if the request to |url| should include a variations header. +// Also, logs the result of validating |url| in histograms, one of which ends in +// |suffix|. +bool ShouldAppendVariationsHeader(const GURL& url, const std::string& suffix) { + URLValidationResult result = GetUrlValidationResult(url); + base::UmaHistogramEnumeration( + "Variations.Headers.URLValidationResult." + suffix, result); + return result == URLValidationResult::kShouldAppend; } -bool ShouldAppendVariationsHeader(const GURL& url) { - if (!url.is_valid()) { - LogUrlValidationHistogram(INVALID_URL); +// Returns true if the request is sent from a Google-associated property, i.e. +// from a first-party context. This determination is made using the request +// context derived from |resource_request|. +bool IsFirstPartyContext(const network::ResourceRequest& resource_request) { + if (!resource_request.request_initiator) { + // The absence of |request_initiator| means that the request was initiated + // by the browser, e.g. a request from the browser to Autofill upon form + // detection. + LogRequestContextHistogram(RequestContextCategory::kBrowserInitiated); + return true; + } + + const GURL request_initiator_url = + resource_request.request_initiator->GetURL(); + if (request_initiator_url.SchemeIs("chrome-search") || + request_initiator_url.SchemeIs("chrome")) { + // A scheme matching the above patterns means that the request was + // initiated by an internal page, e.g. a request from + // chrome-search://local-ntp/ for App Launcher resources. + LogRequestContextHistogram(kInternalChromePageInitiated); + return true; + } + if (GetUrlValidationResult(request_initiator_url) != + URLValidationResult::kShouldAppend) { + // The request was initiated by a non-Google-associated page, e.g. a request + // from https://www.bbc.com/. + LogRequestContextHistogram(kNonGooglePageInitiatedFromRequestInitiator); return false; } - if (!url.SchemeIsHTTPOrHTTPS()) { - LogUrlValidationHistogram(NEITHER_HTTP_HTTPS); + if (resource_request.is_main_frame) { + // The request is from a Google-associated page--not a sub-frame--e.g. a + // request from https://calendar.google.com/. + LogRequestContextHistogram(kGooglePageInitiated); + return true; + } + if (!resource_request.trusted_params) { + LogRequestContextHistogram(kNoTrustedParams); + // Without TrustedParams, we cannot be certain that the request is from a + // first-party context. return false; } - if (!google_util::IsGoogleAssociatedDomainUrl(url)) { - LogUrlValidationHistogram(NOT_GOOGLE_DOMAIN); + + const net::IsolationInfo* isolation_info = + &resource_request.trusted_params->isolation_info; + if (isolation_info->IsEmpty()) { + LogRequestContextHistogram(kNoIsolationInfo); + // Without IsolationInfo, we cannot be certain that the request is from a + // first-party context. return false; } - // We check https here, rather than before the IsGoogleDomain() check, to know - // how many Google domains are being rejected by the change to https only. - if (!url.SchemeIs(url::kHttpsScheme)) { - LogUrlValidationHistogram(IS_GOOGLE_NOT_HTTPS); + if (GetUrlValidationResult(isolation_info->top_frame_origin()->GetURL()) != + URLValidationResult::kShouldAppend) { + // The request is from a Google-associated sub-frame on a + // non-Google-associated page, e.g. a request to DoubleClick from an ad's + // sub-frame on https://www.lexico.com/. + LogRequestContextHistogram(kGoogleSubFrameOnNonGooglePageInitiated); return false; } - LogUrlValidationHistogram(SHOULD_APPEND); + if (GetUrlValidationResult(isolation_info->frame_origin()->GetURL()) != + URLValidationResult::kShouldAppend) { + // The request was initiated by a non-Google-associated page, e.g. a request + // from https://www.bbc.com/. + // + // TODO(crbug/1094303): This case should be covered by checking the request + // initiator's URL. Maybe deprecate kNonGooglePageInitiatedFromFrameOrigin + // if this bucket is never used. + LogRequestContextHistogram(kNonGooglePageInitiatedFromFrameOrigin); + return false; + } + // The request is from a Google-associated sub-frame on a Google-associated + // page, e.g. a request from a Docs sub-frame on https://drive.google.com/. + LogRequestContextHistogram(kGoogleSubFrameOnGooglePageInitiated); return true; } @@ -100,9 +203,13 @@ class VariationsHeaderHelper { // international TLD domains *.google.<TLD> or *.youtube.<TLD>. // 2. Only transmit for non-Incognito profiles. // 3. For the X-Client-Data header, only include non-empty variation IDs. - if ((incognito == InIncognito::kYes) || !ShouldAppendVariationsHeader(url)) + if ((incognito == InIncognito::kYes) || + !ShouldAppendVariationsHeader(url, "Append")) return false; + // TODO(crbug/1094303): Use the result to determine which IDs to include. + IsFirstPartyContext(*resource_request_); + if (variations_header_.empty()) return false; @@ -153,7 +260,7 @@ void RemoveVariationsHeaderIfNeeded( const net::RedirectInfo& redirect_info, const network::mojom::URLResponseHead& response_head, std::vector<std::string>* to_be_removed_headers) { - if (!ShouldAppendVariationsHeader(redirect_info.new_url)) + if (!ShouldAppendVariationsHeader(redirect_info.new_url, "Remove")) to_be_removed_headers->push_back(kClientDataHeader); } @@ -194,8 +301,10 @@ bool HasVariationsHeader(const network::ResourceRequest& request) { return request.cors_exempt_headers.HasHeader(kClientDataHeader); } -bool ShouldAppendVariationsHeaderForTesting(const GURL& url) { - return ShouldAppendVariationsHeader(url); +bool ShouldAppendVariationsHeaderForTesting( + const GURL& url, + const std::string& histogram_suffix) { + return ShouldAppendVariationsHeader(url, histogram_suffix); } void UpdateCorsExemptHeaderForVariations( diff --git a/chromium/components/variations/net/variations_http_headers.h b/chromium/components/variations/net/variations_http_headers.h index 29506e0f81f..6e30fdd9d14 100644 --- a/chromium/components/variations/net/variations_http_headers.h +++ b/chromium/components/variations/net/variations_http_headers.h @@ -100,7 +100,9 @@ bool IsVariationsHeader(const std::string& header_name); bool HasVariationsHeader(const network::ResourceRequest& request); // Calls the internal ShouldAppendVariationsHeader() for testing. -bool ShouldAppendVariationsHeaderForTesting(const GURL& url); +bool ShouldAppendVariationsHeaderForTesting( + const GURL& url, + const std::string& histogram_suffix); // Updates |cors_exempt_header_list| field of the given |param| to register the // variation headers. diff --git a/chromium/components/variations/net/variations_http_headers_unittest.cc b/chromium/components/variations/net/variations_http_headers_unittest.cc index a07883107ad..79ab8b3dd3f 100644 --- a/chromium/components/variations/net/variations_http_headers_unittest.cc +++ b/chromium/components/variations/net/variations_http_headers_unittest.cc @@ -4,12 +4,18 @@ #include "components/variations/net/variations_http_headers.h" -#include <stddef.h> +#include <string> #include "base/macros.h" #include "base/stl_util.h" +#include "base/test/metrics/histogram_tester.h" +#include "net/base/isolation_info.h" +#include "net/cookies/site_for_cookies.h" +#include "services/network/public/cpp/resource_request.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +#include "url/origin.h" namespace variations { @@ -155,9 +161,136 @@ TEST(VariationsHttpHeadersTest, ShouldAppendVariationsHeader) { for (size_t i = 0; i < base::size(cases); ++i) { const GURL url(cases[i].url); EXPECT_EQ(cases[i].should_append_headers, - ShouldAppendVariationsHeaderForTesting(url)) + ShouldAppendVariationsHeaderForTesting(url, "Append")) << url; } } +struct PopulateRequestContextHistogramData { + const char* request_initiator_url; + bool is_main_frame; + bool has_trusted_params; + const char* isolation_info_top_frame_origin_url; + const char* isolation_info_frame_origin_url; + int bucket; + const char* name; +}; + +class PopulateRequestContextHistogramTest + : public testing::TestWithParam<PopulateRequestContextHistogramData> { + public: + static const PopulateRequestContextHistogramData kCases[]; +}; + +const PopulateRequestContextHistogramData + PopulateRequestContextHistogramTest::kCases[] = { + {"", false, false, "", "", 0, "kBrowserInitiated"}, + {"chrome-search://local-ntp/", false, false, "", "", 1, + "kInternalChromePageInitiated"}, + {"https://www.youtube.com/", true, false, "", "", 2, + "kGooglePageInitiated"}, + {"https://docs.google.com/", false, true, "https://drive.google.com/", + "https://docs.google.com/", 3, "kGoogleSubFrameOnGooglePageInitiated"}, + {"https://www.un.org/", false, false, "", "", 4, + "kNonGooglePageInitiatedFromRequestInitiator"}, + {"https://foo.client-channel.google.com/", false, false, "", "", 5, + "kNoTrustedParams"}, + {"https://foo.google.com/", false, true, "", "", 6, "kNoIsolationInfo"}, + {"https://123acb.safeframe.googlesyndication.com/", false, true, + "https://www.lexico.com/", "", 7, + "kGoogleSubFrameOnNonGooglePageInitiated"}, + {"https://foo.google.com/", false, true, "https://foo.google.com/", + "https://www.reddit.com/", 8, + "kNonGooglePageInitiatedFromFrameOrigin"}, +}; + +TEST(VariationsHttpHeadersTest, PopulateUrlValidationResultHistograms) { + const GURL invalid_url("invalid"); + const GURL not_google("https://heavnlydonuts.com/"); + const GURL should_append("https://youtube.com"); + const GURL wrong_scheme("ftp://foo.com/"); + const GURL google_not_https("http://google.com/"); + + const std::string append = "Append"; + const std::string remove = "Remove"; + base::HistogramTester tester; + + ASSERT_FALSE(ShouldAppendVariationsHeaderForTesting(invalid_url, append)); + ASSERT_FALSE(ShouldAppendVariationsHeaderForTesting(not_google, append)); + ASSERT_TRUE(ShouldAppendVariationsHeaderForTesting(should_append, append)); + + ASSERT_FALSE(ShouldAppendVariationsHeaderForTesting(wrong_scheme, remove)); + ASSERT_FALSE( + ShouldAppendVariationsHeaderForTesting(google_not_https, remove)); + + // Verify that the Append suffixed histogram has a sample corresponding to + // the validation result for the three URLs validated for appending. + const std::string append_histogram = + "Variations.Headers.URLValidationResult.Append"; + tester.ExpectTotalCount(append_histogram, 3); + EXPECT_THAT(tester.GetAllSamples(append_histogram), + testing::ElementsAre(base::Bucket(0, 1), base::Bucket(2, 1), + base::Bucket(3, 1))); + + // Verify that the Remove suffixed histogram has a sample corresponding to + // the validation result for the two URLs validated for removal. + const std::string remove_histogram = + "Variations.Headers.URLValidationResult.Remove"; + tester.ExpectTotalCount(remove_histogram, 2); + EXPECT_THAT(tester.GetAllSamples(remove_histogram), + testing::ElementsAre(base::Bucket(4, 1), base::Bucket(5, 1))); +} + +INSTANTIATE_TEST_SUITE_P( + VariationsHttpHeadersTest, + PopulateRequestContextHistogramTest, + testing::ValuesIn(PopulateRequestContextHistogramTest::kCases)); + +// Returns a ResourceRequest created from the given values. +network::ResourceRequest CreateResourceRequest( + const std::string& request_initiator_url, + bool is_main_frame, + bool has_trusted_params, + const std::string& isolation_info_top_frame_origin_url, + const std::string& isolation_info_frame_origin_url) { + network::ResourceRequest request; + if (request_initiator_url.empty()) + return request; + + request.request_initiator = url::Origin::Create(GURL(request_initiator_url)); + request.is_main_frame = is_main_frame; + if (!has_trusted_params) + return request; + + request.trusted_params = network::ResourceRequest::TrustedParams(); + if (isolation_info_top_frame_origin_url.empty()) + return request; + + request.trusted_params->isolation_info = net::IsolationInfo::Create( + net::IsolationInfo::RedirectMode::kUpdateNothing, + url::Origin::Create(GURL(isolation_info_top_frame_origin_url)), + url::Origin::Create(GURL(isolation_info_frame_origin_url)), + net::SiteForCookies()); + return request; +} + +TEST_P(PopulateRequestContextHistogramTest, PopulateRequestContextHistogram) { + PopulateRequestContextHistogramData data = GetParam(); + SCOPED_TRACE(data.name); + + network::ResourceRequest request = CreateResourceRequest( + data.request_initiator_url, data.is_main_frame, data.has_trusted_params, + data.isolation_info_top_frame_origin_url, + data.isolation_info_frame_origin_url); + + base::HistogramTester tester; + AppendVariationsHeaderUnknownSignedIn(GURL("https://foo.google.com"), + variations::InIncognito::kNo, &request); + + // Verify that the histogram has a single sample corresponding to the request + // context category. + const std::string histogram = "Variations.Headers.RequestContextCategory"; + tester.ExpectUniqueSample(histogram, data.bucket, 1); +} + } // namespace variations diff --git a/chromium/components/variations/net/variations_url_loader_throttle.cc b/chromium/components/variations/net/variations_url_loader_throttle.cc index 2f1aed783c6..d0fd43ff595 100644 --- a/chromium/components/variations/net/variations_url_loader_throttle.cc +++ b/chromium/components/variations/net/variations_url_loader_throttle.cc @@ -21,7 +21,7 @@ VariationsURLLoaderThrottle::~VariationsURLLoaderThrottle() = default; void VariationsURLLoaderThrottle::AppendThrottleIfNeeded( const variations::VariationsClient* variations_client, std::vector<std::unique_ptr<blink::URLLoaderThrottle>>* throttles) { - if (!variations_client || variations_client->IsIncognito()) + if (!variations_client || variations_client->IsOffTheRecord()) return; throttles->push_back(std::make_unique<VariationsURLLoaderThrottle>( |