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/net/url_request | |
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/net/url_request')
-rw-r--r-- | chromium/net/url_request/url_fetcher_response_writer.cc | 3 | ||||
-rw-r--r-- | chromium/net/url_request/url_request.cc | 12 | ||||
-rw-r--r-- | chromium/net/url_request/url_request.h | 28 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_context_builder.cc | 1 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_context_builder_unittest.cc | 36 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_http_job.cc | 154 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_http_job.h | 7 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_http_job_unittest.cc | 83 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_job.cc | 107 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_job.h | 2 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_job_unittest.cc | 115 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_netlog_params.cc | 18 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_quic_unittest.cc | 110 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_test_util.cc | 1 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_test_util.h | 1 | ||||
-rw-r--r-- | chromium/net/url_request/url_request_unittest.cc | 691 |
16 files changed, 1017 insertions, 352 deletions
diff --git a/chromium/net/url_request/url_fetcher_response_writer.cc b/chromium/net/url_request/url_fetcher_response_writer.cc index adfbcb1c370..7a96f12458a 100644 --- a/chromium/net/url_request/url_fetcher_response_writer.cc +++ b/chromium/net/url_request/url_fetcher_response_writer.cc @@ -166,8 +166,7 @@ void URLFetcherFileWriter::CloseAndDeleteFile() { file_stream_.reset(); DisownFile(); file_task_runner_->PostTask( - FROM_HERE, base::BindOnce(base::IgnoreResult(&base::DeleteFile), - file_path_, false /* recursive */)); + FROM_HERE, base::BindOnce(base::GetDeleteFileCallback(), file_path_)); } void URLFetcherFileWriter::DidCreateTempFile(base::FilePath* temp_file_path, diff --git a/chromium/net/url_request/url_request.cc b/chromium/net/url_request/url_request.cc index 40927b586fa..cbed158f16b 100644 --- a/chromium/net/url_request/url_request.cc +++ b/chromium/net/url_request/url_request.cc @@ -395,7 +395,7 @@ int URLRequest::GetResponseCode() const { return job_->GetResponseCode(); } -void URLRequest::set_maybe_sent_cookies(CookieStatusList cookies) { +void URLRequest::set_maybe_sent_cookies(CookieAccessResultList cookies) { maybe_sent_cookies_ = std::move(cookies); } @@ -983,13 +983,12 @@ void URLRequest::NotifySSLCertificateError(int net_error, delegate_->OnSSLCertificateError(this, net_error, ssl_info, fatal); } -bool URLRequest::CanGetCookies(const CookieList& cookie_list) const { +bool URLRequest::CanGetCookies() const { DCHECK(!(load_flags_ & LOAD_DO_NOT_SEND_COOKIES)); bool can_get_cookies = g_default_can_use_cookies; if (network_delegate_) { can_get_cookies = - network_delegate_->CanGetCookies(*this, cookie_list, - /*allowed_from_caller=*/true); + network_delegate_->CanGetCookies(*this, /*allowed_from_caller=*/true); } if (!can_get_cookies) @@ -1015,7 +1014,10 @@ net::PrivacyMode URLRequest::DeterminePrivacyMode() const { // Enable privacy mode if flags tell us not send or save cookies. if ((load_flags_ & LOAD_DO_NOT_SEND_COOKIES) || (load_flags_ & LOAD_DO_NOT_SAVE_COOKIES)) { - return PRIVACY_MODE_ENABLED; + // TODO(https://crbug.com/775438): Client certs should always be + // affirmatively omitted for these requests. + return send_client_certs_ ? PRIVACY_MODE_ENABLED + : PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS; } // Otherwise, check with the delegate if present, or base it off of diff --git a/chromium/net/url_request/url_request.h b/chromium/net/url_request/url_request.h index e967a680d6e..643ab4ae8f0 100644 --- a/chromium/net/url_request/url_request.h +++ b/chromium/net/url_request/url_request.h @@ -11,8 +11,6 @@ #include <string> #include <vector> -#include "base/debug/leak_tracker.h" -#include "base/logging.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" @@ -542,7 +540,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // Returns whether secure DNS should be disabled for the request. bool disable_secure_dns() { return disable_secure_dns_; } - void set_maybe_sent_cookies(CookieStatusList cookies); + void set_maybe_sent_cookies(CookieAccessResultList cookies); void set_maybe_stored_cookies(CookieAndLineStatusList cookies); // These lists contain a list of cookies that are associated with the given @@ -556,7 +554,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // and only contain the cookies relevant to the most recent roundtrip. // Populated while the http request is being built. - const CookieStatusList& maybe_sent_cookies() const { + const CookieAccessResultList& maybe_sent_cookies() const { return maybe_sent_cookies_; } // Populated after the response headers are received. @@ -724,6 +722,20 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { } bool upgrade_if_insecure() const { return upgrade_if_insecure_; } + // By default, client certs will be sent (provided via + // Delegate::OnCertificateRequested) when cookies are disabled + // (LOAD_DO_NOT_SEND_COOKIES / LOAD_DO_NOT_SAVE_COOKIES). As described at + // https://crbug.com/775438, this is not the desired behavior. When + // |send_client_certs| is set to false, this will suppress the + // Delegate::OnCertificateRequested callback when cookies/credentials are also + // suppressed. This method has no effect if credentials are enabled (cookies + // saved and sent). + // TODO(https://crbug.com/775438): Remove this when the underlying + // issue is fixed. + void set_send_client_certs(bool send_client_certs) { + send_client_certs_ = send_client_certs; + } + base::WeakPtr<URLRequest> GetWeakPtr(); protected: @@ -815,7 +827,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // These functions delegate to |network_delegate_| if it is not NULL. // If |network_delegate_| is NULL, cookies can be used unless // SetDefaultCookiePolicyToBlock() has been called. - bool CanGetCookies(const CookieList& cookie_list) const; + bool CanGetCookies() const; bool CanSetCookie(const net::CanonicalCookie& cookie, CookieOptions* options) const; PrivacyMode DeterminePrivacyMode() const; @@ -865,7 +877,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { PrivacyMode privacy_mode_; bool disable_secure_dns_; - CookieStatusList maybe_sent_cookies_; + CookieAccessResultList maybe_sent_cookies_; CookieAndLineStatusList maybe_stored_cookies_; #if BUILDFLAG(ENABLE_REPORTING) @@ -928,8 +940,6 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { std::string blocked_by_; bool use_blocked_by_as_load_param_; - base::debug::LeakTracker<URLRequest> leak_tracker_; - // Safe-guard to ensure that we do not send multiple "I am completed" // messages to network delegate. // TODO(battre): Remove this. http://crbug.com/89049 @@ -959,6 +969,8 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { bool upgrade_if_insecure_; + bool send_client_certs_ = true; + THREAD_CHECKER(thread_checker_); base::WeakPtrFactory<URLRequest> weak_factory_{this}; diff --git a/chromium/net/url_request/url_request_context_builder.cc b/chromium/net/url_request/url_request_context_builder.cc index 943423b3f81..4a71bd3364e 100644 --- a/chromium/net/url_request/url_request_context_builder.cc +++ b/chromium/net/url_request/url_request_context_builder.cc @@ -107,7 +107,6 @@ class BasicNetworkDelegate : public NetworkDelegateImpl { } bool OnCanGetCookies(const URLRequest& request, - const CookieList& cookie_list, bool allowed_from_caller) override { return allowed_from_caller; } diff --git a/chromium/net/url_request/url_request_context_builder_unittest.cc b/chromium/net/url_request/url_request_context_builder_unittest.cc index bb98fa97c86..3b1922c2fab 100644 --- a/chromium/net/url_request/url_request_context_builder_unittest.cc +++ b/chromium/net/url_request/url_request_context_builder_unittest.cc @@ -58,6 +58,7 @@ class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory { int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, const SSLInfo& ssl_info, + const NetworkIsolationKey& network_isolation_key, const GURL& origin, CreateReason reason, int nonce_count, @@ -131,10 +132,11 @@ TEST_F(URLRequestContextBuilderTest, DefaultHttpAuthHandlerFactory) { SSLInfo null_ssl_info; // Verify that the default basic handler is present - EXPECT_EQ(OK, - context->http_auth_handler_factory()->CreateAuthHandlerFromString( - "basic", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, - NetLogWithSource(), host_resolver_.get(), &handler)); + EXPECT_EQ( + OK, + context->http_auth_handler_factory()->CreateAuthHandlerFromString( + "basic", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(), + gurl, NetLogWithSource(), host_resolver_.get(), &handler)); } TEST_F(URLRequestContextBuilderTest, CustomHttpAuthHandlerFactory) { @@ -149,20 +151,23 @@ TEST_F(URLRequestContextBuilderTest, CustomHttpAuthHandlerFactory) { // Verify that a handler is returned for a custom scheme. EXPECT_EQ(kBasicReturnCode, context->http_auth_handler_factory()->CreateAuthHandlerFromString( - "ExtraScheme", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, - NetLogWithSource(), host_resolver_.get(), &handler)); + "ExtraScheme", HttpAuth::AUTH_SERVER, null_ssl_info, + NetworkIsolationKey(), gurl, NetLogWithSource(), + host_resolver_.get(), &handler)); // Verify that the default basic handler isn't present - EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, - context->http_auth_handler_factory()->CreateAuthHandlerFromString( - "basic", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, - NetLogWithSource(), host_resolver_.get(), &handler)); + EXPECT_EQ( + ERR_UNSUPPORTED_AUTH_SCHEME, + context->http_auth_handler_factory()->CreateAuthHandlerFromString( + "basic", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(), + gurl, NetLogWithSource(), host_resolver_.get(), &handler)); // Verify that a handler isn't returned for a bogus scheme. - EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, - context->http_auth_handler_factory()->CreateAuthHandlerFromString( - "Bogus", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, - NetLogWithSource(), host_resolver_.get(), &handler)); + EXPECT_EQ( + ERR_UNSUPPORTED_AUTH_SCHEME, + context->http_auth_handler_factory()->CreateAuthHandlerFromString( + "Bogus", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(), + gurl, NetLogWithSource(), host_resolver_.get(), &handler)); } #if BUILDFLAG(ENABLE_REPORTING) @@ -226,7 +231,8 @@ TEST_F(URLRequestContextBuilderTest, ShutdownHostResolverWithPendingRequest) { std::unique_ptr<HostResolver::ResolveHostRequest> request = context->host_resolver()->CreateRequest( - HostPortPair("example.com", 1234), NetLogWithSource(), base::nullopt); + HostPortPair("example.com", 1234), NetworkIsolationKey(), + NetLogWithSource(), base::nullopt); TestCompletionCallback callback; int rv = request->Start(callback.callback()); ASSERT_TRUE(mock_host_resolver->has_pending_requests()); diff --git a/chromium/net/url_request/url_request_http_job.cc b/chromium/net/url_request/url_request_http_job.cc index 0e88cd83a0c..5590bd226c9 100644 --- a/chromium/net/url_request/url_request_http_job.cc +++ b/chromium/net/url_request/url_request_http_job.cc @@ -88,7 +88,7 @@ base::Value CookieInclusionStatusNetLogParams( const std::string& cookie_name, const std::string& cookie_domain, const std::string& cookie_path, - const net::CanonicalCookie::CookieInclusionStatus& status, + const net::CookieInclusionStatus& status, net::NetLogCaptureMode capture_mode) { base::Value dict(base::Value::Type::DICTIONARY); dict.SetStringKey("operation", operation); @@ -160,6 +160,58 @@ void RecordCTHistograms(const net::SSLInfo& ssl_info) { } } +template <typename CookieWithMetadata> +bool ShouldMarkSameSiteCompatPairs( + const std::vector<CookieWithMetadata>& cookie_list, + const net::CookieOptions& options) { + // If the context is same-site then there cannot be any SameSite-by-default + // warnings, so the compat pair warning is irrelevant. + if (options.same_site_cookie_context().GetContextForCookieInclusion() > + net::CookieOptions::SameSiteCookieContext::ContextType:: + SAME_SITE_LAX_METHOD_UNSAFE) { + return false; + } + return cookie_list.size() >= 2; +} + +void MarkSameSiteCompatPairs( + std::vector<net::CookieWithAccessResult>& cookie_list, + const net::CookieOptions& options) { + for (size_t i = 0; i < cookie_list.size() - 1; ++i) { + const net::CanonicalCookie& c1 = cookie_list[i].cookie; + for (size_t j = i + 1; j < cookie_list.size(); ++j) { + const net::CanonicalCookie& c2 = cookie_list[j].cookie; + if (net::cookie_util::IsSameSiteCompatPair(c1, c2, options)) { + cookie_list[i].access_result.status.AddWarningReason( + net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR); + cookie_list[j].access_result.status.AddWarningReason( + net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR); + } + } + } +} + +void MarkSameSiteCompatPairs( + std::vector<net::CookieAndLineWithStatus>& cookie_list, + const net::CookieOptions& options) { + for (size_t i = 0; i < cookie_list.size() - 1; ++i) { + if (!cookie_list[i].cookie.has_value()) + continue; + const net::CanonicalCookie& c1 = cookie_list[i].cookie.value(); + for (size_t j = i + 1; j < cookie_list.size(); ++j) { + if (!cookie_list[j].cookie.has_value()) + continue; + const net::CanonicalCookie& c2 = cookie_list[j].cookie.value(); + if (net::cookie_util::IsSameSiteCompatPair(c1, c2, options)) { + cookie_list[i].status.AddWarningReason( + net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR); + cookie_list[j].status.AddWarningReason( + net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR); + } + } + } +} + } // namespace namespace net { @@ -279,18 +331,10 @@ void URLRequestHttpJob::Start() { // plugin could set a referrer although sending the referrer is inhibited. request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer); - // Our consumer should have made sure that this is a safe referrer. See for - // instance WebCore::FrameLoader::HideReferrer. + // Our consumer should have made sure that this is a safe referrer (e.g. via + // URLRequestJob::ComputeReferrerForPolicy). if (referrer.is_valid()) { std::string referer_value = referrer.spec(); - // We limit the `referer` header to 4k: see step 6 of - // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer - // and https://github.com/whatwg/fetch/issues/903. - if (referer_value.length() > 4096) { - // Strip the referrer down to its origin, but ensure that it's serialized - // as a URL (e.g. retaining a trailing `/` character). - referer_value = url::Origin::Create(referrer).GetURL().spec(); - } request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer, referer_value); } @@ -552,21 +596,14 @@ void URLRequestHttpJob::AddCookieHeaderAndStart() { void URLRequestHttpJob::SetCookieHeaderAndStart( const CookieOptions& options, - const CookieStatusList& cookies_with_status_list, - const CookieStatusList& excluded_list) { + const CookieAccessResultList& cookies_with_access_result_list, + const CookieAccessResultList& excluded_list) { DCHECK(request_->maybe_sent_cookies().empty()); - // TODO(chlily): This is just for passing to CanGetCookies(), however the - // CookieList parameter of CanGetCookies(), which eventually gets passed to - // the NetworkDelegate, never actually gets used anywhere except in tests. The - // parameter should be removed. - CookieList cookie_list = - net::cookie_util::StripStatuses(cookies_with_status_list); - - bool can_get_cookies = CanGetCookies(cookie_list); - if (!cookies_with_status_list.empty() && can_get_cookies) { + bool can_get_cookies = CanGetCookies(); + if (!cookies_with_access_result_list.empty() && can_get_cookies) { std::string cookie_line = - CanonicalCookie::BuildCookieLine(cookies_with_status_list); + CanonicalCookie::BuildCookieLine(cookies_with_access_result_list); UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length()); request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie, cookie_line); @@ -576,7 +613,7 @@ void URLRequestHttpJob::SetCookieHeaderAndStart( // TODO(crbug.com/1031664): Reduce the number of times the cookie list is // iterated over. Get metrics for every cookie which is included. - for (const auto& c : cookies_with_status_list) { + for (const auto& c : cookies_with_access_result_list) { bool request_is_secure = request_->url().SchemeIsCryptographic(); net::CookieSourceScheme cookie_scheme = c.cookie.SourceScheme(); CookieRequestScheme cookie_request_schemes; @@ -606,43 +643,49 @@ void URLRequestHttpJob::SetCookieHeaderAndStart( } } - // Report status for things in |excluded_list| and |cookies_with_status_list| + // Report status for things in |excluded_list| and + // |cookies_with_access_result_list| // after the delegate got a chance to block them. - CookieStatusList maybe_sent_cookies = excluded_list; - // CanGetCookies only looks at the fields of the URLRequest, not the cookies - // it is passed, so if CanGetCookies(cookie_list) is false, then - // CanGetCookies(excluded_list) would also be false, so tag also the - // excluded cookies as having been blocked by user preferences. + CookieAccessResultList maybe_sent_cookies = excluded_list; + if (!can_get_cookies) { - for (CookieStatusList::iterator it = maybe_sent_cookies.begin(); + for (CookieAccessResultList::iterator it = maybe_sent_cookies.begin(); it != maybe_sent_cookies.end(); ++it) { - it->status.AddExclusionReason( - CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES); + it->access_result.status.AddExclusionReason( + CookieInclusionStatus::EXCLUDE_USER_PREFERENCES); } } - for (const auto& cookie_with_status : cookies_with_status_list) { - CanonicalCookie::CookieInclusionStatus status = cookie_with_status.status; + + for (const auto& cookie_with_access_result : + cookies_with_access_result_list) { + CookieAccessResult access_result = cookie_with_access_result.access_result; if (!can_get_cookies) { - status.AddExclusionReason( - CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES); + access_result.status.AddExclusionReason( + CookieInclusionStatus::EXCLUDE_USER_PREFERENCES); } - maybe_sent_cookies.push_back({cookie_with_status.cookie, status}); + maybe_sent_cookies.push_back( + {cookie_with_access_result.cookie, access_result}); } if (request_->net_log().IsCapturing()) { - for (const auto& cookie_and_status : maybe_sent_cookies) { + for (const auto& cookie_with_access_result : maybe_sent_cookies) { request_->net_log().AddEvent( NetLogEventType::COOKIE_INCLUSION_STATUS, [&](NetLogCaptureMode capture_mode) { return CookieInclusionStatusNetLogParams( - "send", cookie_and_status.cookie.Name(), - cookie_and_status.cookie.Domain(), - cookie_and_status.cookie.Path(), cookie_and_status.status, - capture_mode); + "send", cookie_with_access_result.cookie.Name(), + cookie_with_access_result.cookie.Domain(), + cookie_with_access_result.cookie.Path(), + cookie_with_access_result.access_result.status, capture_mode); }); } } + // Mark the CookieInclusionStatuses of items in |maybe_sent_cookies| if they + // are part of a presumed SameSite compatibility pair. + if (ShouldMarkSameSiteCompatPairs(maybe_sent_cookies, options)) + MarkSameSiteCompatPairs(maybe_sent_cookies, options); + request_->set_maybe_sent_cookies(std::move(maybe_sent_cookies)); StartTransaction(); @@ -707,7 +750,7 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) { // it reaches 0 in the callback itself. num_cookie_lines_left_ = 1; while (headers->EnumerateHeader(&iter, name, &cookie_string)) { - CanonicalCookie::CookieInclusionStatus returned_status; + CookieInclusionStatus returned_status; num_cookie_lines_left_++; @@ -723,7 +766,7 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) { } if (cookie && !CanSetCookie(*cookie, &options)) { returned_status.AddExclusionReason( - CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES); + CookieInclusionStatus::EXCLUDE_USER_PREFERENCES); } if (!returned_status.IsInclude()) { OnSetCookieResult(options, cookie_to_return, std::move(cookie_string), @@ -741,15 +784,21 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) { // loop has been exited. num_cookie_lines_left_--; - if (num_cookie_lines_left_ == 0) + if (num_cookie_lines_left_ == 0) { + // Mark the CookieInclusionStatuses of items in |set_cookie_status_list_| if + // they are part of a presumed SameSite compatibility pair. + if (ShouldMarkSameSiteCompatPairs(set_cookie_status_list_, options)) + MarkSameSiteCompatPairs(set_cookie_status_list_, options); + NotifyHeadersComplete(); + } } void URLRequestHttpJob::OnSetCookieResult( const CookieOptions& options, base::Optional<CanonicalCookie> cookie, std::string cookie_string, - CanonicalCookie::CookieInclusionStatus status) { + CookieInclusionStatus status) { if (request_->net_log().IsCapturing()) { request_->net_log().AddEvent( NetLogEventType::COOKIE_INCLUSION_STATUS, @@ -768,8 +817,14 @@ void URLRequestHttpJob::OnSetCookieResult( // If all the cookie lines have been handled, |set_cookie_status_list_| now // reflects the result of all Set-Cookie lines, and the request can be // continued. - if (num_cookie_lines_left_ == 0) + if (num_cookie_lines_left_ == 0) { + // Mark the CookieInclusionStatuses of items in |set_cookie_status_list_| if + // they are part of a presumed SameSite compatibility pair. + if (ShouldMarkSameSiteCompatPairs(set_cookie_status_list_, options)) + MarkSameSiteCompatPairs(set_cookie_status_list_, options); + NotifyHeadersComplete(); + } } void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() { @@ -817,7 +872,8 @@ void URLRequestHttpJob::ProcessExpectCTHeader() { std::string value; if (headers->GetNormalizedHeader("Expect-CT", &value)) { security_state->ProcessExpectCTHeader( - value, HostPortPair::FromURL(request_info_.url), ssl_info); + value, HostPortPair::FromURL(request_info_.url), ssl_info, + request_->isolation_info().network_isolation_key()); } } diff --git a/chromium/net/url_request/url_request_http_job.h b/chromium/net/url_request/url_request_http_job.h index f214aef293c..cc6eecb5b3e 100644 --- a/chromium/net/url_request/url_request_http_job.h +++ b/chromium/net/url_request/url_request_http_job.h @@ -22,6 +22,7 @@ #include "net/base/ip_endpoint.h" #include "net/base/net_error_details.h" #include "net/base/net_export.h" +#include "net/cookies/cookie_inclusion_status.h" #include "net/http/http_request_info.h" #include "net/socket/connection_attempts.h" #include "net/url_request/url_request_job.h" @@ -167,14 +168,14 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { // Callback functions for Cookie Monster void SetCookieHeaderAndStart(const CookieOptions& options, - const CookieStatusList& cookie_list, - const CookieStatusList& excluded_list); + const CookieAccessResultList& cookie_list, + const CookieAccessResultList& excluded_list); // Another Cookie Monster callback void OnSetCookieResult(const CookieOptions& options, base::Optional<CanonicalCookie> cookie, std::string cookie_string, - CanonicalCookie::CookieInclusionStatus status); + CookieInclusionStatus status); int num_cookie_lines_left_; CookieAndLineStatusList set_cookie_status_list_; diff --git a/chromium/net/url_request/url_request_http_job_unittest.cc b/chromium/net/url_request/url_request_http_job_unittest.cc index f70cf685f69..65fc278295b 100644 --- a/chromium/net/url_request/url_request_http_job_unittest.cc +++ b/chromium/net/url_request/url_request_http_job_unittest.cc @@ -22,6 +22,7 @@ #include "base/test/metrics/histogram_tester.h" #include "net/base/auth.h" #include "net/base/isolation_info.h" +#include "net/base/network_isolation_key.h" #include "net/base/request_priority.h" #include "net/cert/ct_policy_status.h" #include "net/cookies/cookie_monster.h" @@ -1012,6 +1013,84 @@ TEST_F(URLRequestHttpJobWithMockSocketsTest, kGTSRootR3HistogramID, 1); } +namespace { + +// An ExpectCTReporter that records the number of times OnExpectCTFailed() was +// called. +class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter { + public: + MockExpectCTReporter() = default; + ~MockExpectCTReporter() override = default; + + void OnExpectCTFailed( + const HostPortPair& host_port_pair, + const GURL& report_uri, + base::Time expiration, + const X509Certificate* validated_certificate_chain, + const X509Certificate* served_certificate_chain, + const SignedCertificateTimestampAndStatusList& + signed_certificate_timestamps, + const NetworkIsolationKey& network_isolation_key) override { + num_failures_++; + network_isolation_key_ = network_isolation_key; + } + + int num_failures() const { return num_failures_; } + const NetworkIsolationKey& network_isolation_key() const { + return network_isolation_key_; + } + + private: + int num_failures_ = 0; + NetworkIsolationKey network_isolation_key_; +}; + +} // namespace + +TEST_F(URLRequestHttpJobWithMockSocketsTest, + TestHttpJobSendsNetworkIsolationKeyWhenProcessingExpectCTHeader) { + SSLSocketDataProvider ssl_socket_data(net::ASYNC, net::OK); + ssl_socket_data.ssl_info.cert = + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); + ssl_socket_data.ssl_info.is_issued_by_known_root = true; + ssl_socket_data.ssl_info.ct_policy_compliance_required = false; + ssl_socket_data.ssl_info.ct_policy_compliance = + ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS; + + socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data); + + MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; + MockRead reads[] = { + MockRead( + "HTTP/1.1 200 OK\r\n" + "Expect-CT: max-age=100, enforce, report-uri=https://example.test\r\n" + "Content-Length: 12\r\n\r\n"), + MockRead("Test Content")}; + StaticSocketDataProvider socket_data(reads, writes); + socket_factory_.AddSocketDataProvider(&socket_data); + + base::HistogramTester histograms; + + MockExpectCTReporter reporter; + TransportSecurityState transport_security_state; + transport_security_state.SetExpectCTReporter(&reporter); + context_->set_transport_security_state(&transport_security_state); + + TestDelegate delegate; + std::unique_ptr<URLRequest> request = context_->CreateRequest( + GURL("https://www.example.com/"), DEFAULT_PRIORITY, &delegate, + TRAFFIC_ANNOTATION_FOR_TESTS); + IsolationInfo isolation_info = IsolationInfo::CreateTransient(); + request->set_isolation_info(isolation_info); + request->Start(); + delegate.RunUntilComplete(); + EXPECT_THAT(delegate.request_status(), IsOk()); + + ASSERT_EQ(1, reporter.num_failures()); + EXPECT_EQ(isolation_info.network_isolation_key(), + reporter.network_isolation_key()); +} + // Tests that the CT compliance histogram is recorded, even if CT is not // required. TEST_F(URLRequestHttpJobWithMockSocketsTest, @@ -1646,7 +1725,7 @@ TEST_F(URLRequestHttpJobWebSocketTest, CreateHelperPassedThrough) { bool SetAllCookies(CookieMonster* cm, const CookieList& list) { DCHECK(cm); - ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback; + ResultSavingCookieCallback<CookieInclusionStatus> callback; cm->SetAllCookiesAsync(list, callback.MakeCallback()); callback.WaitUntilDone(); return callback.result().IsInclude(); @@ -1660,7 +1739,7 @@ bool CreateAndSetCookie(CookieStore* cs, if (!cookie) return false; DCHECK(cs); - ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback; + ResultSavingCookieCallback<CookieInclusionStatus> callback; cs->SetCanonicalCookieAsync(std::move(cookie), url, CookieOptions::MakeAllInclusive(), callback.MakeCallback()); diff --git a/chromium/net/url_request/url_request_job.cc b/chromium/net/url_request/url_request_job.cc index 3430a8dd62f..e490bd69b85 100644 --- a/chromium/net/url_request/url_request_job.cc +++ b/chromium/net/url_request/url_request_job.cc @@ -16,6 +16,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "net/base/auth.h" +#include "net/base/features.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/load_states.h" @@ -271,49 +272,111 @@ void URLRequestJob::GetConnectionAttempts(ConnectionAttempts* out) const { out->clear(); } +namespace { + +// Assuming |url| has already been stripped for use as a referrer, if +// |should_strip_to_origin| is true, this method returns the output of the +// "Strip `url` for use as a referrer" algorithm from the Referrer Policy spec +// with its "origin-only" flag set to true: +// https://w3c.github.io/webappsec-referrer-policy/#strip-url +GURL MaybeStripToOrigin(GURL url, bool should_strip_to_origin) { + if (!should_strip_to_origin) + return url; + + return url.GetOrigin(); +} + +} // namespace + // static GURL URLRequestJob::ComputeReferrerForPolicy( URLRequest::ReferrerPolicy policy, const GURL& original_referrer, const GURL& destination, bool* same_origin_out_for_metrics) { + // Here and below, numbered lines are from the Referrer Policy spec's + // "Determine request's referrer" algorithm: + // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer + // + // 4. Let referrerURL be the result of stripping referrerSource for use as a + // referrer. + GURL stripped_referrer = original_referrer.GetAsReferrer(); + + // 5. Let referrerOrigin be the result of stripping referrerSource for use as + // a referrer, with the origin-only flag set to true. + // + // (We use a boolean instead of computing the URL right away in order to avoid + // constructing a new GURL when it's not necessary.) + bool should_strip_to_origin = false; + + // 6. If the result of serializing referrerURL is a string whose length is + // greater than 4096, set referrerURL to referrerOrigin. + if (stripped_referrer.spec().size() > 4096) + should_strip_to_origin = true; + + bool same_origin = url::Origin::Create(original_referrer) + .IsSameOriginWith(url::Origin::Create(destination)); + + if (same_origin_out_for_metrics) + *same_origin_out_for_metrics = same_origin; + + // 7. The user agent MAY alter referrerURL or referrerOrigin at this point to + // enforce arbitrary policy considerations in the interests of minimizing data + // leakage. For example, the user agent could strip the URL down to an origin, + // modify its host, replace it with an empty string, etc. + if (base::FeatureList::IsEnabled( + features::kCapReferrerToOriginOnCrossOrigin) && + !same_origin) { + should_strip_to_origin = true; + } + bool secure_referrer_but_insecure_destination = original_referrer.SchemeIsCryptographic() && !destination.SchemeIsCryptographic(); - url::Origin referrer_origin = url::Origin::Create(original_referrer); - bool same_origin = - referrer_origin.IsSameOriginWith(url::Origin::Create(destination)); - if (same_origin_out_for_metrics) - *same_origin_out_for_metrics = same_origin; + switch (policy) { case URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE: - return secure_referrer_but_insecure_destination ? GURL() - : original_referrer; + if (secure_referrer_but_insecure_destination) + return GURL(); + return MaybeStripToOrigin(std::move(stripped_referrer), + should_strip_to_origin); case URLRequest::REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN: - if (same_origin) { - return original_referrer; - } else if (secure_referrer_but_insecure_destination) { + if (secure_referrer_but_insecure_destination) return GURL(); - } else { - return referrer_origin.GetURL(); - } + if (!same_origin) + should_strip_to_origin = true; + return MaybeStripToOrigin(std::move(stripped_referrer), + should_strip_to_origin); case URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN: - return same_origin ? original_referrer : referrer_origin.GetURL(); + if (!same_origin) + should_strip_to_origin = true; + return MaybeStripToOrigin(std::move(stripped_referrer), + should_strip_to_origin); case URLRequest::NEVER_CLEAR_REFERRER: - return original_referrer; + return MaybeStripToOrigin(std::move(stripped_referrer), + should_strip_to_origin); + case URLRequest::ORIGIN: - return referrer_origin.GetURL(); + should_strip_to_origin = true; + return MaybeStripToOrigin(std::move(stripped_referrer), + should_strip_to_origin); + case URLRequest::CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN: - if (same_origin) - return original_referrer; - return GURL(); + if (!same_origin) + return GURL(); + return MaybeStripToOrigin(std::move(stripped_referrer), + should_strip_to_origin); + case URLRequest::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE: if (secure_referrer_but_insecure_destination) return GURL(); - return referrer_origin.GetURL(); + should_strip_to_origin = true; + return MaybeStripToOrigin(std::move(stripped_referrer), + should_strip_to_origin); + case URLRequest::NO_REFERRER: return GURL(); } @@ -333,8 +396,8 @@ void URLRequestJob::NotifySSLCertificateError(int net_error, request_->NotifySSLCertificateError(net_error, ssl_info, fatal); } -bool URLRequestJob::CanGetCookies(const CookieList& cookie_list) const { - return request_->CanGetCookies(cookie_list); +bool URLRequestJob::CanGetCookies() const { + return request_->CanGetCookies(); } bool URLRequestJob::CanSetCookie(const net::CanonicalCookie& cookie, diff --git a/chromium/net/url_request/url_request_job.h b/chromium/net/url_request/url_request_job.h index caabaeab232..e7b13cc3942 100644 --- a/chromium/net/url_request/url_request_job.h +++ b/chromium/net/url_request/url_request_job.h @@ -265,7 +265,7 @@ class NET_EXPORT URLRequestJob { bool fatal); // Delegates to URLRequest. - bool CanGetCookies(const CookieList& cookie_list) const; + bool CanGetCookies() const; // Delegates to URLRequest. bool CanSetCookie(const net::CanonicalCookie& cookie, diff --git a/chromium/net/url_request/url_request_job_unittest.cc b/chromium/net/url_request/url_request_job_unittest.cc index 4056dd8742c..4f6ed2d87b3 100644 --- a/chromium/net/url_request/url_request_job_unittest.cc +++ b/chromium/net/url_request/url_request_job_unittest.cc @@ -7,6 +7,8 @@ #include <memory> #include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" +#include "net/base/features.h" #include "net/base/request_priority.h" #include "net/http/http_transaction_test_util.h" #include "net/test/cert_test_util.h" @@ -18,6 +20,7 @@ #include "net/url_request/url_request_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/url_util.h" using net::test::IsError; using net::test::IsOk; @@ -658,4 +661,116 @@ TEST(URLRequestJobComputeReferrer, AcceptsNullptrInput) { GURL(), nullptr); } +TEST(URLRequestJobComputeReferrer, FilesystemDestination) { + EXPECT_EQ( + URLRequestJob::ComputeReferrerForPolicy( + URLRequest::NEVER_CLEAR_REFERRER, GURL("https://referrer.example"), + GURL("filesystem:https://destination.example"), nullptr), + GURL("https://referrer.example")); +} + +TEST(URLRequestJobComputeReferrer, TruncatesLongReferrer) { + std::string original_spec = "https://referrer.example/"; + original_spec.resize(4097, 'a'); + const GURL kOriginalReferrer(original_spec); + + EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy( + URLRequest::NEVER_CLEAR_REFERRER, kOriginalReferrer, + GURL("https://google.com")), + GURL("https://referrer.example/")); +} + +TEST(URLRequestJobComputeReferrer, DoesntTruncateShortReferrer) { + std::string original_spec = "https://referrer.example/"; + original_spec.resize(4096, 'a'); + const GURL kOriginalReferrer(original_spec); + + EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy( + URLRequest::NEVER_CLEAR_REFERRER, kOriginalReferrer, + GURL("https://google.com")), + kOriginalReferrer); +} + +TEST(URLRequestJobComputeReferrer, DoesntTruncateEvenShorterReferrer) { + std::string original_spec = "https://referrer.example/"; + original_spec.resize(4095, 'a'); + const GURL kOriginalReferrer(original_spec); + + EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy( + URLRequest::NEVER_CLEAR_REFERRER, kOriginalReferrer, + GURL("https://google.com")), + kOriginalReferrer); +} + +TEST(URLRequestJobComputeReferrer, DoesntTruncateReferrerWithLongRef) { + // Because the "is the length greater than 4096?" check comes *after* + // stripping the ref in the Referrer Policy spec, a URL that is short except + // for having a very long ref should not be stripped to an origin by the "if + // the length is too long, strip to the origin" check. + EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy( + URLRequest::NEVER_CLEAR_REFERRER, + GURL(std::string("https://referrer.example/path#") + + std::string(5000, 'a')), + GURL("https://google.com")), + GURL("https://referrer.example/path")); +} + +TEST(URLRequestJobComputeReferrer, InvalidSchemeReferrer) { + const GURL kOriginalReferrer("about:blank"); + ASSERT_FALSE(url::IsReferrerScheme( + kOriginalReferrer.spec().data(), + kOriginalReferrer.parsed_for_possibly_invalid_spec().scheme)); + + EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy( + URLRequest::NEVER_CLEAR_REFERRER, kOriginalReferrer, + GURL("https://google.com")), + GURL()); + + EXPECT_EQ( + URLRequestJob::ComputeReferrerForPolicy( + URLRequest::ORIGIN, kOriginalReferrer, GURL("https://google.com")), + GURL()); +} + +TEST(URLRequestJobComputeReferrer, CapReferrerOnCrossOrigin) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + features::kCapReferrerToOriginOnCrossOrigin); + + const GURL kOriginalReferrer("https://boggle.com/path"); + + EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy( + URLRequest::NEVER_CLEAR_REFERRER, kOriginalReferrer, + GURL("https://google.com")), + GURL("https://boggle.com/")); +} + +TEST(URLRequestJobComputeReferrer, + CapReferrerOnCrossOriginRespectsStricterPolicy) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + features::kCapReferrerToOriginOnCrossOrigin); + + const GURL kOriginalReferrer("https://boggle.com/path"); + + EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(URLRequest::NO_REFERRER, + kOriginalReferrer, + GURL("https://google.com")), + GURL()); +} + +TEST(URLRequestJobComputeReferrer, + CapReferrerOnCrossOriginDoesntCapOnSameOrigin) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + features::kCapReferrerToOriginOnCrossOrigin); + + const GURL kOriginalReferrer("https://boggle.com/path"); + + EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy( + URLRequest::NEVER_CLEAR_REFERRER, kOriginalReferrer, + GURL("https://boggle.com")), + kOriginalReferrer); +} + } // namespace net diff --git a/chromium/net/url_request/url_request_netlog_params.cc b/chromium/net/url_request/url_request_netlog_params.cc index 2a88f066683..d6473f26e52 100644 --- a/chromium/net/url_request/url_request_netlog_params.cc +++ b/chromium/net/url_request/url_request_netlog_params.cc @@ -16,6 +16,22 @@ namespace net { +namespace { + +std::string PrivacyModeDebugString(PrivacyMode privacy_mode) { + switch (privacy_mode) { + case PRIVACY_MODE_DISABLED: + return "disabled"; + case PRIVACY_MODE_ENABLED: + return "enabled"; + case PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS: + return "enabled without client certs"; + } + return ""; +} + +} // namespace + base::Value NetLogURLRequestConstructorParams( const GURL& url, RequestPriority priority, @@ -40,7 +56,7 @@ base::Value NetLogURLRequestStartParams( dict.SetStringKey("url", url.possibly_invalid_spec()); dict.SetStringKey("method", method); dict.SetIntKey("load_flags", load_flags); - dict.SetIntKey("privacy_mode", privacy_mode == PRIVACY_MODE_ENABLED); + dict.SetStringKey("privacy_mode", PrivacyModeDebugString(privacy_mode)); dict.SetStringKey("network_isolation_key", network_isolation_key.ToDebugString()); dict.SetStringKey("site_for_cookies", site_for_cookies.ToDebugString()); diff --git a/chromium/net/url_request/url_request_quic_unittest.cc b/chromium/net/url_request/url_request_quic_unittest.cc index c282944895a..3860e68196d 100644 --- a/chromium/net/url_request/url_request_quic_unittest.cc +++ b/chromium/net/url_request/url_request_quic_unittest.cc @@ -11,11 +11,15 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/test/bind_test_util.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "net/base/features.h" #include "net/base/isolation_info.h" #include "net/base/load_timing_info.h" #include "net/base/network_delegate.h" +#include "net/base/network_isolation_key.h" +#include "net/cert/ct_policy_enforcer.h" +#include "net/cert/ct_policy_status.h" #include "net/cert/mock_cert_verifier.h" #include "net/dns/mapped_host_resolver.h" #include "net/dns/mock_host_resolver.h" @@ -64,6 +68,53 @@ const char kIndexPath[] = "/index2.html"; const char kIndexBodyValue[] = "Hello from QUIC Server"; const int kIndexStatus = 200; +class MockCTPolicyEnforcerNonCompliant : public CTPolicyEnforcer { + public: + MockCTPolicyEnforcerNonCompliant() = default; + ~MockCTPolicyEnforcerNonCompliant() override = default; + + ct::CTPolicyCompliance CheckCompliance( + X509Certificate* cert, + const ct::SCTList& verified_scts, + const NetLogWithSource& net_log) override { + return ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS; + } +}; + +// An ExpectCTReporter that records the number of times OnExpectCTFailed() was +// called. +class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter { + public: + MockExpectCTReporter() = default; + ~MockExpectCTReporter() override = default; + + void OnExpectCTFailed( + const HostPortPair& host_port_pair, + const GURL& report_uri, + base::Time expiration, + const X509Certificate* validated_certificate_chain, + const X509Certificate* served_certificate_chain, + const SignedCertificateTimestampAndStatusList& + signed_certificate_timestamps, + const NetworkIsolationKey& network_isolation_key) override { + num_failures_++; + report_uri_ = report_uri; + network_isolation_key_ = network_isolation_key; + } + + int num_failures() const { return num_failures_; } + const GURL& report_uri() const { return report_uri_; } + const NetworkIsolationKey& network_isolation_key() const { + return network_isolation_key_; + } + + private: + int num_failures_ = 0; + + GURL report_uri_; + NetworkIsolationKey network_isolation_key_; +}; + class URLRequestQuicTest : public TestWithTaskEnvironment, public ::testing::WithParamInterface<quic::ParsedQuicVersion> { @@ -78,8 +129,7 @@ class URLRequestQuicTest verify_result.verified_cert = ImportCertFromFile( GetTestCertsDirectory(), "quic-chain.pem"); cert_verifier_.AddResultForCertAndHost(verify_result.verified_cert.get(), - "test.example.com", verify_result, - OK); + kTestServerHost, verify_result, OK); // To simplify the test, and avoid the race with the HTTP request, we force // QUIC for these requests. context_->set_quic_context(&quic_context_); @@ -92,6 +142,8 @@ class URLRequestQuicTest context_->set_http_network_session_params(std::move(params)); context_->set_cert_verifier(&cert_verifier_); context_->set_net_log(&net_log_); + transport_security_state_.SetExpectCTReporter(&expect_ct_reporter_); + context_->set_transport_security_state(&transport_security_state_); } void TearDown() override { @@ -108,6 +160,10 @@ class URLRequestQuicTest context_->set_network_delegate(network_delegate); } + // Can be used to modify |context_|. Only safe to modify before Init() is + // called. + TestURLRequestContext* context() { return context_.get(); } + // Initializes the TestURLRequestContext |context_|. void Init() { context_->Init(); } @@ -155,6 +211,12 @@ class URLRequestQuicTest quic::ParsedQuicVersion version() { return GetParam(); } + MockExpectCTReporter* expect_ct_reporter() { return &expect_ct_reporter_; } + + TransportSecurityState* transport_security_state() { + return &transport_security_state_; + } + protected: // Returns a fully-qualified URL for |path| on the test server. std::string UrlFromPath(base::StringPiece path) { @@ -219,6 +281,9 @@ class URLRequestQuicTest return path.MaybeAsASCII(); } + MockExpectCTReporter expect_ct_reporter_; + TransportSecurityState transport_security_state_; + std::unique_ptr<MappedHostResolver> host_resolver_; std::unique_ptr<QuicSimpleServer> server_; std::unique_ptr<TestURLRequestContext> context_; @@ -513,9 +578,10 @@ TEST_P(URLRequestQuicTest, CancelPushIfCached_AllCached) { EXPECT_FALSE(end_entry_2->HasParams()); EXPECT_FALSE(GetOptionalNetErrorCodeFromParams(*end_entry_2)); -#if !defined(OS_FUCHSIA) && !defined(OS_IOS) +#if !defined(OS_FUCHSIA) && !defined(OS_IOS) && !defined(OS_MACOSX) // TODO(crbug.com/813631): Make this work on Fuchsia. // TODO(crbug.com/1032568): Make this work on iOS. + // TODO(crbug.com/1087378): Flaky on Mac. // Verify the reset error count received on the server side. EXPECT_LE(2u, GetRstErrorCountReceivedByServer(quic::QUIC_STREAM_CANCELLED)); #endif @@ -636,4 +702,42 @@ TEST_P(URLRequestQuicTest, RequestHeadersCallback) { EXPECT_EQ(OK, delegate.request_status()); } +// Tests that if there's an Expect-CT failure at the QUIC layer, a report is +// generated. +TEST_P(URLRequestQuicTest, ExpectCT) { + TransportSecurityState::SetRequireCTForTesting(true); + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + // enabled_features + {features::kPartitionConnectionsByNetworkIsolationKey, + features::kPartitionHttpServerPropertiesByNetworkIsolationKey, + features::kPartitionSSLSessionsByNetworkIsolationKey}, + // disabled_features + {}); + + MockCTPolicyEnforcerNonCompliant ct_enforcer; + context()->set_ct_policy_enforcer(&ct_enforcer); + Init(); + + GURL report_uri("https://report.test/"); + IsolationInfo isolation_info = IsolationInfo::CreateTransient(); + transport_security_state()->AddExpectCT( + kTestServerHost, base::Time::Now() + base::TimeDelta::FromDays(1), + true /* enforce */, report_uri, isolation_info.network_isolation_key()); + + base::RunLoop run_loop; + TestDelegate delegate; + std::unique_ptr<URLRequest> request = + CreateRequest(GURL(UrlFromPath(kHelloPath)), DEFAULT_PRIORITY, &delegate); + request->set_isolation_info(isolation_info); + request->Start(); + delegate.RunUntilComplete(); + + EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate.request_status()); + ASSERT_EQ(1, expect_ct_reporter()->num_failures()); + EXPECT_EQ(report_uri, expect_ct_reporter()->report_uri()); + EXPECT_EQ(isolation_info.network_isolation_key(), + expect_ct_reporter()->network_isolation_key()); +} + } // namespace net diff --git a/chromium/net/url_request/url_request_test_util.cc b/chromium/net/url_request/url_request_test_util.cc index 702f6a8d0de..b06d7924f46 100644 --- a/chromium/net/url_request/url_request_test_util.cc +++ b/chromium/net/url_request/url_request_test_util.cc @@ -594,7 +594,6 @@ void TestNetworkDelegate::OnPACScriptError(int line_number, } bool TestNetworkDelegate::OnCanGetCookies(const URLRequest& request, - const CookieList& cookie_list, bool allowed_from_caller) { bool allow = allowed_from_caller; if (cookie_options_bit_mask_ & NO_GET_COOKIES) diff --git a/chromium/net/url_request/url_request_test_util.h b/chromium/net/url_request/url_request_test_util.h index 064be87739f..5d6da89e066 100644 --- a/chromium/net/url_request/url_request_test_util.h +++ b/chromium/net/url_request/url_request_test_util.h @@ -342,7 +342,6 @@ class TestNetworkDelegate : public NetworkDelegateImpl { void OnURLRequestDestroyed(URLRequest* request) override; void OnPACScriptError(int line_number, const base::string16& error) override; bool OnCanGetCookies(const URLRequest& request, - const CookieList& cookie_list, bool allowed_from_caller) override; bool OnCanSetCookie(const URLRequest& request, const net::CanonicalCookie& cookie, diff --git a/chromium/net/url_request/url_request_unittest.cc b/chromium/net/url_request/url_request_unittest.cc index c9d24bfe0a3..e2ef3cadd5e 100644 --- a/chromium/net/url_request/url_request_unittest.cc +++ b/chromium/net/url_request/url_request_unittest.cc @@ -84,6 +84,7 @@ #include "net/cert/x509_util.h" #include "net/cert_net/cert_net_fetcher_url_request.h" #include "net/cookies/canonical_cookie_test_helpers.h" +#include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_store_test_helpers.h" #include "net/cookies/test_cookie_access_delegate.h" @@ -115,6 +116,7 @@ #include "net/ssl/ssl_server_config.h" #include "net/ssl/test_ssl_config_service.h" #include "net/test/cert_test_util.h" +#include "net/test/embedded_test_server/default_handlers.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/embedded_test_server_connection_listener.h" #include "net/test/embedded_test_server/http_request.h" @@ -161,6 +163,7 @@ using net::test::IsError; using net::test::IsOk; +using net::test_server::RegisterDefaultHandlers; using testing::AnyOf; using base::ASCIIToUTF16; @@ -324,7 +327,7 @@ class HttpTestServer : public EmbeddedTestServer { AddDefaultHandlers(document_root); } - HttpTestServer() { AddDefaultHandlers(base::FilePath()); } + HttpTestServer() { RegisterDefaultHandlers(this); } }; // Job that allows monitoring of its priority. @@ -1569,7 +1572,6 @@ class FilteringTestNetworkDelegate : public TestNetworkDelegate { void ResetBlockedSetCookieCount() { blocked_set_cookie_count_ = 0; } bool OnCanGetCookies(const URLRequest& request, - const net::CookieList& cookie_list, bool allowed_from_caller) override { // Filter out cookies if |block_get_cookies_| is set and // combine with |allowed_from_caller|. @@ -1580,7 +1582,7 @@ class FilteringTestNetworkDelegate : public TestNetworkDelegate { if (!allowed) ++blocked_get_cookie_count_; - return TestNetworkDelegate::OnCanGetCookies(request, cookie_list, allowed); + return TestNetworkDelegate::OnCanGetCookies(request, allowed); } void set_block_get_cookies() { block_get_cookies_ = true; } @@ -2398,10 +2400,10 @@ TEST_F(URLRequestTest, SameSiteCookiesSpecialScheme) { url::AddStandardScheme("chrome", url::SchemeType::SCHEME_WITH_HOST); EmbeddedTestServer https_test_server(EmbeddedTestServer::TYPE_HTTPS); - https_test_server.AddDefaultHandlers(base::FilePath()); + RegisterDefaultHandlers(&https_test_server); ASSERT_TRUE(https_test_server.Start()); EmbeddedTestServer http_test_server(EmbeddedTestServer::TYPE_HTTP); - http_test_server.AddDefaultHandlers(base::FilePath()); + RegisterDefaultHandlers(&http_test_server); // Ensure they are on different ports. ASSERT_TRUE(http_test_server.Start(https_test_server.port() + 1)); // Both hostnames should be 127.0.0.1 (so that we can use the same set of @@ -2488,11 +2490,9 @@ TEST_F(URLRequestTest, SameSiteCookiesSpecialScheme) { // Tests that __Secure- cookies can't be set on non-secure origins. TEST_F(URLRequestTest, SecureCookiePrefixOnNonsecureOrigin) { EmbeddedTestServer http_server; - http_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&http_server); EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); - https_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&https_server); ASSERT_TRUE(http_server.Start()); ASSERT_TRUE(https_server.Start()); @@ -2531,8 +2531,7 @@ TEST_F(URLRequestTest, SecureCookiePrefixOnNonsecureOrigin) { TEST_F(URLRequestTest, SecureCookiePrefixNonsecure) { EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); - https_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&https_server); ASSERT_TRUE(https_server.Start()); TestNetworkDelegate network_delegate; @@ -2570,8 +2569,7 @@ TEST_F(URLRequestTest, SecureCookiePrefixNonsecure) { TEST_F(URLRequestTest, SecureCookiePrefixSecure) { EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); - https_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&https_server); ASSERT_TRUE(https_server.Start()); TestNetworkDelegate network_delegate; @@ -2610,11 +2608,9 @@ TEST_F(URLRequestTest, SecureCookiePrefixSecure) { // cookies are enabled. TEST_F(URLRequestTest, StrictSecureCookiesOnNonsecureOrigin) { EmbeddedTestServer http_server; - http_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&http_server); EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); - https_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&https_server); ASSERT_TRUE(http_server.Start()); ASSERT_TRUE(https_server.Start()); @@ -3728,76 +3724,132 @@ TEST_F(URLRequestTestHTTP, GetTestLoadTiming) { } } -// TODO(svaldez): Update tests to use EmbeddedTestServer. -#if !defined(OS_IOS) -TEST_F(URLRequestTestHTTP, GetZippedTest) { - SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTP, - base::FilePath(kTestFilePath)); +namespace { - ASSERT_TRUE(test_server.Start()); +// Sends the correct Content-Length matching the compressed length. +const char kZippedContentLengthCompressed[] = "C"; +// Sends an incorrect Content-Length matching the uncompressed length. +const char kZippedContentLengthUncompressed[] = "U"; +// Sends an incorrect Content-Length shorter than the compressed length. +const char kZippedContentLengthShort[] = "S"; +// Sends an incorrect Content-Length between the compressed and uncompressed +// lengths. +const char kZippedContentLengthMedium[] = "M"; +// Sends an incorrect Content-Length larger than both compressed and +// uncompressed lengths. +const char kZippedContentLengthLong[] = "L"; + +// Sends |compressed_content| which, when decoded with deflate, should have +// length |uncompressed_length|. The Content-Length header will be sent based on +// which of the constants above is sent in the query string. +std::unique_ptr<test_server::HttpResponse> HandleZippedRequest( + const std::string& compressed_content, + size_t uncompressed_length, + const test_server::HttpRequest& request) { + GURL url = request.GetURL(); + if (url.path_piece() != "/compressedfiles/BullRunSpeech.txt") + return nullptr; - // Parameter that specifies the Content-Length field in the response: - // C - Compressed length. - // U - Uncompressed length. - // L - Large length (larger than both C & U). - // M - Medium length (between C & U). - // S - Small length (smaller than both C & U). - const char test_parameters[] = "CULMS"; - const int num_tests = base::size(test_parameters) - 1; // Skip NULL. - // C & U should be OK. - // L & M are larger than the data sent, and show an error. - // S has too little data, but we seem to accept it. - const bool test_expect_success[num_tests] = - { true, true, false, false, true }; + size_t length; + if (url.query_piece() == kZippedContentLengthCompressed) { + length = compressed_content.size(); + } else if (url.query_piece() == kZippedContentLengthUncompressed) { + length = uncompressed_length; + } else if (url.query_piece() == kZippedContentLengthShort) { + length = compressed_content.size() / 2; + } else if (url.query_piece() == kZippedContentLengthMedium) { + length = (compressed_content.size() + uncompressed_length) / 2; + } else if (url.query_piece() == kZippedContentLengthLong) { + length = compressed_content.size() + uncompressed_length; + } else { + return nullptr; + } + + std::string headers = "HTTP/1.1 200 OK\r\n"; + headers += "Content-Encoding: deflate\r\n"; + base::StringAppendF(&headers, "Content-Length: %zu\r\n", length); + return std::make_unique<test_server::RawHttpResponse>(headers, + compressed_content); +} +} // namespace + +TEST_F(URLRequestTestHTTP, GetZippedTest) { base::FilePath file_path; base::PathService::Get(base::DIR_SOURCE_ROOT, &file_path); file_path = file_path.Append(kTestFilePath); - file_path = file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt")); - std::string expected_content; - ASSERT_TRUE(base::ReadFileToString(file_path, &expected_content)); + std::string expected_content, compressed_content; + ASSERT_TRUE(base::ReadFileToString( + file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt")), + &expected_content)); + // This file is the output of the Python zlib.compress function on + // |expected_content|. + ASSERT_TRUE(base::ReadFileToString( + file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt.deflate")), + &compressed_content)); + + http_test_server()->RegisterRequestHandler(base::BindRepeating( + &HandleZippedRequest, compressed_content, expected_content.size())); + ASSERT_TRUE(http_test_server()->Start()); + + static const struct { + const char* parameter; + bool expect_success; + } kTests[] = { + // Sending the compressed Content-Length is correct. + {kZippedContentLengthCompressed, true}, + // Sending the uncompressed Content-Length is incorrect, but we accept it + // to workaround some broken servers. + {kZippedContentLengthUncompressed, true}, + // Sending too long of Content-Length is rejected. + {kZippedContentLengthLong, false}, + {kZippedContentLengthMedium, false}, + // Sending too short of Content-Length successfully fetches a response + // body, but it will be truncated. + {kZippedContentLengthShort, true}, + }; - for (int i = 0; i < num_tests; i++) { + for (const auto& test : kTests) { + SCOPED_TRACE(test.parameter); TestDelegate d; - { - std::string test_file = base::StringPrintf( - "compressedfiles/BullRunSpeech.txt?%c", test_parameters[i]); + std::string test_file = base::StringPrintf( + "/compressedfiles/BullRunSpeech.txt?%s", test.parameter); - TestNetworkDelegate network_delegate; // Must outlive URLRequest. - TestURLRequestContext context(true); - context.set_network_delegate(&network_delegate); - context.Init(); + TestNetworkDelegate network_delegate; // Must outlive URLRequest. + TestURLRequestContext context(true); + context.set_network_delegate(&network_delegate); + context.Init(); - std::unique_ptr<URLRequest> r( - context.CreateRequest(test_server.GetURL(test_file), DEFAULT_PRIORITY, - &d, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->Start(); - EXPECT_TRUE(r->is_pending()); + std::unique_ptr<URLRequest> r(context.CreateRequest( + http_test_server()->GetURL(test_file), DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + r->Start(); + EXPECT_TRUE(r->is_pending()); - d.RunUntilComplete(); + d.RunUntilComplete(); - EXPECT_EQ(1, d.response_started_count()); - EXPECT_FALSE(d.received_data_before_response()); - VLOG(1) << " Received " << d.bytes_received() << " bytes" - << " error = " << d.request_status(); - if (test_expect_success[i]) { - EXPECT_EQ(OK, d.request_status()) << " Parameter = \"" << test_file - << "\""; - if (test_parameters[i] == 'S') { - // When content length is smaller than both compressed length and - // uncompressed length, HttpStreamParser might not read the full - // response body. - continue; - } - EXPECT_EQ(expected_content, d.data_received()); + EXPECT_EQ(1, d.response_started_count()); + EXPECT_FALSE(d.received_data_before_response()); + VLOG(1) << " Received " << d.bytes_received() << " bytes" + << " error = " << d.request_status(); + if (test.expect_success) { + EXPECT_EQ(OK, d.request_status()) + << " Parameter = \"" << test_file << "\""; + if (strcmp(test.parameter, kZippedContentLengthShort) == 0) { + // When content length is smaller than both compressed length and + // uncompressed length, HttpStreamParser might not read the full + // response body. + EXPECT_EQ(expected_content.substr(0, d.data_received().size()), + d.data_received()); } else { - EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, d.request_status()) - << " Parameter = \"" << test_file << "\""; + EXPECT_EQ(expected_content, d.data_received()); } + } else { + EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, d.request_status()) + << " Parameter = \"" << test_file << "\""; } } } -#endif // !defined(OS_IOS) TEST_F(URLRequestTestHTTP, RedirectLoadTiming) { ASSERT_TRUE(http_test_server()->Start()); @@ -4997,8 +5049,8 @@ TEST_F(URLRequestTestHTTP, ProcessSTS) { default_context().transport_security_state(); TransportSecurityState::STSState sts_state; TransportSecurityState::PKPState pkp_state; - EXPECT_TRUE(security_state->GetDynamicSTSState(test_server_hostname, - &sts_state, nullptr)); + EXPECT_TRUE( + security_state->GetDynamicSTSState(test_server_hostname, &sts_state)); EXPECT_FALSE( security_state->GetDynamicPKPState(test_server_hostname, &pkp_state)); EXPECT_EQ(TransportSecurityState::STSState::MODE_FORCE_HTTPS, @@ -5031,8 +5083,8 @@ TEST_F(URLRequestTestHTTP, STSNotProcessedOnIP) { TransportSecurityState* security_state = default_context().transport_security_state(); TransportSecurityState::STSState sts_state; - EXPECT_FALSE(security_state->GetDynamicSTSState(test_server_hostname, - &sts_state, nullptr)); + EXPECT_FALSE( + security_state->GetDynamicSTSState(test_server_hostname, &sts_state)); } namespace { @@ -5245,8 +5297,8 @@ TEST_F(URLRequestTestHTTP, ProcessSTSOnce) { TransportSecurityState* security_state = default_context().transport_security_state(); TransportSecurityState::STSState sts_state; - EXPECT_TRUE(security_state->GetDynamicSTSState(test_server_hostname, - &sts_state, nullptr)); + EXPECT_TRUE( + security_state->GetDynamicSTSState(test_server_hostname, &sts_state)); EXPECT_EQ(TransportSecurityState::STSState::MODE_FORCE_HTTPS, sts_state.upgrade_mode); EXPECT_FALSE(sts_state.include_subdomains); @@ -5260,13 +5312,15 @@ class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter { MockExpectCTReporter() : num_failures_(0) {} ~MockExpectCTReporter() override = default; - void OnExpectCTFailed(const HostPortPair& host_port_pair, - const GURL& report_uri, - base::Time expiration, - const X509Certificate* validated_certificate_chain, - const X509Certificate* served_certificate_chain, - const SignedCertificateTimestampAndStatusList& - signed_certificate_timestamps) override { + void OnExpectCTFailed( + const HostPortPair& host_port_pair, + const GURL& report_uri, + base::Time expiration, + const X509Certificate* validated_certificate_chain, + const X509Certificate* served_certificate_chain, + const SignedCertificateTimestampAndStatusList& + signed_certificate_timestamps, + const NetworkIsolationKey& network_isolation_key) override { num_failures_++; } @@ -5414,8 +5468,8 @@ TEST_F(URLRequestTestHTTP, ExpectCTHeader) { d.RunUntilComplete(); TransportSecurityState::ExpectCTState state; - ASSERT_TRUE( - transport_security_state.GetDynamicExpectCTState(url.host(), &state)); + ASSERT_TRUE(transport_security_state.GetDynamicExpectCTState( + url.host(), NetworkIsolationKey(), &state)); EXPECT_TRUE(state.enforce); EXPECT_EQ(GURL("https://example.test"), state.report_uri); } @@ -5476,8 +5530,8 @@ TEST_F(URLRequestTestHTTP, MultipleExpectCTHeaders) { d.RunUntilComplete(); TransportSecurityState::ExpectCTState state; - ASSERT_TRUE( - transport_security_state.GetDynamicExpectCTState(url.host(), &state)); + ASSERT_TRUE(transport_security_state.GetDynamicExpectCTState( + url.host(), NetworkIsolationKey(), &state)); EXPECT_TRUE(state.enforce); EXPECT_EQ(GURL("https://example.test"), state.report_uri); } @@ -5488,7 +5542,7 @@ TEST_F(URLRequestTestHTTP, MultipleExpectCTHeaders) { TEST_F(URLRequestTestHTTP, NetworkErrorLogging_DontReportIfNetworkNotAccessed) { EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); - https_test_server.AddDefaultHandlers(base::FilePath(kTestFilePath)); + RegisterDefaultHandlers(&https_test_server); ASSERT_TRUE(https_test_server.Start()); GURL request_url = https_test_server.GetURL("/cachetime"); @@ -5552,7 +5606,7 @@ TEST_F(URLRequestTestHTTP, NetworkErrorLogging_BasicSuccess) { TEST_F(URLRequestTestHTTP, NetworkErrorLogging_BasicError) { EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); - https_test_server.AddDefaultHandlers(base::FilePath(kTestFilePath)); + RegisterDefaultHandlers(&https_test_server); ASSERT_TRUE(https_test_server.Start()); GURL request_url = https_test_server.GetURL("/close-socket"); @@ -5636,7 +5690,7 @@ TEST_F(URLRequestTestHTTP, NetworkErrorLogging_RedirectWithoutLocationHeader) { TEST_F(URLRequestTestHTTP, NetworkErrorLogging_Auth) { EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); - https_test_server.AddDefaultHandlers(base::FilePath(kTestFilePath)); + RegisterDefaultHandlers(&https_test_server); ASSERT_TRUE(https_test_server.Start()); GURL request_url = https_test_server.GetURL("/auth-basic"); @@ -5667,7 +5721,7 @@ TEST_F(URLRequestTestHTTP, NetworkErrorLogging_Auth) { TEST_F(URLRequestTestHTTP, NetworkErrorLogging_304Response) { EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); - https_test_server.AddDefaultHandlers(base::FilePath(kTestFilePath)); + RegisterDefaultHandlers(&https_test_server); ASSERT_TRUE(https_test_server.Start()); GURL request_url = https_test_server.GetURL("/auth-basic"); @@ -6127,7 +6181,12 @@ TEST_F(URLRequestTestHTTP, CapRefererHeaderLength) { req->Start(); d.RunUntilComplete(); - EXPECT_EQ("http://example.com/", d.data_received()); + // The request's referrer will be stripped since (1) there will be a + // mismatch between the request's referrer and the output of + // URLRequestJob::ComputeReferrerForPolicy and (2) the delegate, when + // offered the opportunity to cancel the request for this reason, will + // decline. + EXPECT_EQ("None", d.data_received()); } { std::string original_header = "http://example.com/"; @@ -6729,8 +6788,7 @@ TEST_F(URLRequestTest, ReportCookieActivity) { req->maybe_stored_cookies()[0].cookie->Name()); EXPECT_TRUE(req->maybe_stored_cookies()[0] .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + {CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); EXPECT_EQ("stored_cookie", req->maybe_stored_cookies()[1].cookie->Name()); EXPECT_TRUE(req->maybe_stored_cookies()[1].status.IsInclude()); EXPECT_EQ("stored_cookie", req->maybe_stored_cookies()[1].cookie->Name()); @@ -6769,17 +6827,16 @@ TEST_F(URLRequestTest, ReportCookieActivity) { ASSERT_EQ(2u, req->maybe_sent_cookies().size()); EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name()); - EXPECT_TRUE(req->maybe_sent_cookies()[0] - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_NOT_ON_PATH, - net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + req->maybe_sent_cookies()[0] + .access_result.status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH, + net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name()); - EXPECT_TRUE(req->maybe_sent_cookies()[1] - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + req->maybe_sent_cookies()[1] + .access_result.status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); auto entries = net_log.GetEntriesWithType(NetLogEventType::COOKIE_INCLUSION_STATUS); EXPECT_EQ(2u, entries.size()); @@ -6842,11 +6899,10 @@ TEST_F(URLRequestTest, ReportCookieActivity) { ASSERT_EQ(2u, req->maybe_sent_cookies().size()); EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name()); EXPECT_TRUE(req->maybe_sent_cookies()[0] - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_NOT_ON_PATH})); + .access_result.status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH})); EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name()); - EXPECT_TRUE(req->maybe_sent_cookies()[1].status.IsInclude()); + EXPECT_TRUE(req->maybe_sent_cookies()[1].access_result.status.IsInclude()); auto entries = net_log.GetEntriesWithType(NetLogEventType::COOKIE_INCLUSION_STATUS); EXPECT_EQ(2u, entries.size()); @@ -6863,6 +6919,200 @@ TEST_F(URLRequestTest, ReportCookieActivity) { } } +// Test that CookieInclusionStatus warnings for SameSite cookie compatibility +// pairs are applied correctly. +TEST_F(URLRequestTest, SameSiteCookieCompatPairWarnings) { + EmbeddedTestServer https_test_server(EmbeddedTestServer::TYPE_HTTPS); + RegisterDefaultHandlers(&https_test_server); + ASSERT_TRUE(https_test_server.Start()); + + GURL set_pair_url = https_test_server.GetURL( + "/set-cookie?name=value;SameSite=None;Secure&" + "name_legacy=value"); + GURL set_httponly_pair_url = https_test_server.GetURL( + "/set-cookie?name=value;SameSite=None;Secure;HttpOnly&" + "name_legacy=value;HttpOnly"); + GURL set_pair_and_other_url = https_test_server.GetURL( + "/set-cookie?name=value;SameSite=None;Secure&" + "name_legacy=value&" + "name2=value;SameSite=None;Secure"); + GURL set_two_pairs_url = https_test_server.GetURL( + "/set-cookie?name=value;SameSite=None;Secure&" + "name_legacy=value&" + "name2=value;SameSite=None;Secure&" + "compat-name2=value"); + GURL get_cookies_url = https_test_server.GetURL("/echoheader?Cookie"); + + struct TestCase { + // URL used to set cookies. + // Note: This test works because each URL uses a superset of the cookies + // used by URLs before it. + GURL set_cookies_url; + // Names of cookies and whether they are expected to be included for a + // cross-site get/set. (All are expected for a same-site request.) + std::map<std::string, bool> expected_cookies; + // Names of cookies expected to have a compat pair warning for a cross-site + // request. + std::set<std::string> expected_compat_warning_cookies; + // Whether all cookies should be HttpOnly. + bool expected_httponly = false; + } kTestCases[] = { + // Basic case with a single compat pair. + {set_pair_url, + {{"name", true}, {"name_legacy", false}}, + {"name", "name_legacy"}}, + // Compat pair with HttpOnly cookies (should not change behavior because + // this is an HTTP request). + {set_httponly_pair_url, + {{"name", true}, {"name_legacy", false}}, + {"name", "name_legacy"}, + true}, + // Pair should be marked, but extra cookie (not part of a pair) should + // not. + {set_pair_and_other_url, + {{"name", true}, {"name_legacy", false}, {"name2", true}}, + {"name", "name_legacy"}}, + // Two separate pairs should all be marked. + {set_two_pairs_url, + {{"name", true}, + {"name_legacy", false}, + {"name2", true}, + {"compat-name2", false}}, + {"name", "name_legacy", "name2", "compat-name2"}}}; + + // For each test case, this exercises: + // 1. Set cookies in a cross-site context to trigger compat pair warnings. + // 2. Set cookies in a same-site context and check that no compat pair + // warnings are applied (and also make sure the cookies are actually + // present for the subsequent tests). + // 3. Get cookies in a same-site context and check that no compat pair + // warnings are applied. + // 4. Get cookies in a cross-site context to trigger compat pair warnings. + for (const auto& test : kTestCases) { + { + // Set cookies in a cross-site context. + TestDelegate d; + std::unique_ptr<URLRequest> req(default_context().CreateRequest( + test.set_cookies_url, DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + req->Start(); + d.RunUntilComplete(); + + ASSERT_EQ(test.expected_cookies.size(), + req->maybe_stored_cookies().size()); + for (const auto& cookie : req->maybe_stored_cookies()) { + ASSERT_TRUE(cookie.cookie.has_value()); + EXPECT_EQ(cookie.cookie->IsHttpOnly(), test.expected_httponly); + + const std::string& cookie_name = cookie.cookie->Name(); + auto it = test.expected_cookies.find(cookie_name); + ASSERT_NE(test.expected_cookies.end(), it); + bool included = cookie.status.IsInclude(); + EXPECT_EQ(it->second, included); + + std::vector<CookieInclusionStatus::ExclusionReason> exclusions; + std::vector<CookieInclusionStatus::WarningReason> warnings; + if (!included) { + exclusions.push_back(CookieInclusionStatus:: + EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX); + warnings.push_back(CookieInclusionStatus:: + WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT); + } + if (base::Contains(test.expected_compat_warning_cookies, cookie_name)) { + warnings.push_back(CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR); + } + EXPECT_TRUE( + cookie.status.HasExactlyExclusionReasonsForTesting(exclusions)); + EXPECT_TRUE(cookie.status.HasExactlyWarningReasonsForTesting(warnings)); + } + } + { + // Set cookies in a same-site context. + TestDelegate d; + std::unique_ptr<URLRequest> req(default_context().CreateFirstPartyRequest( + test.set_cookies_url, DEFAULT_PRIORITY, &d, + TRAFFIC_ANNOTATION_FOR_TESTS)); + req->Start(); + d.RunUntilComplete(); + + ASSERT_EQ(test.expected_cookies.size(), + req->maybe_stored_cookies().size()); + for (const auto& cookie : req->maybe_stored_cookies()) { + ASSERT_TRUE(cookie.cookie.has_value()); + EXPECT_EQ(cookie.cookie->IsHttpOnly(), test.expected_httponly); + EXPECT_TRUE( + base::Contains(test.expected_cookies, cookie.cookie->Name())); + // Cookie was included and there are no warnings. + EXPECT_EQ(CookieInclusionStatus(), cookie.status); + } + } + { + // Get cookies in a same-site context. + TestDelegate d; + std::unique_ptr<URLRequest> req(default_context().CreateFirstPartyRequest( + get_cookies_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + req->Start(); + d.RunUntilComplete(); + + ASSERT_EQ(test.expected_cookies.size(), req->maybe_sent_cookies().size()); + for (const auto& cookie : req->maybe_sent_cookies()) { + EXPECT_EQ(cookie.cookie.IsHttpOnly(), test.expected_httponly); + EXPECT_TRUE( + base::Contains(test.expected_cookies, cookie.cookie.Name())); + EXPECT_THAT(d.data_received(), + ::testing::HasSubstr(cookie.cookie.Name() + "=value")); + // Cookie was included and there are no warnings. + EXPECT_EQ(CookieInclusionStatus(), cookie.access_result.status); + } + } + { + // Get cookies in a cross-site context. + TestDelegate d; + std::unique_ptr<URLRequest> req(default_context().CreateRequest( + get_cookies_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + req->Start(); + d.RunUntilComplete(); + + ASSERT_EQ(test.expected_cookies.size(), req->maybe_sent_cookies().size()); + for (const auto& cookie : req->maybe_sent_cookies()) { + EXPECT_EQ(cookie.cookie.IsHttpOnly(), test.expected_httponly); + + const std::string& cookie_name = cookie.cookie.Name(); + auto it = test.expected_cookies.find(cookie_name); + ASSERT_NE(test.expected_cookies.end(), it); + bool included = cookie.access_result.status.IsInclude(); + EXPECT_EQ(it->second, included); + + if (included) { + EXPECT_THAT(d.data_received(), + ::testing::HasSubstr(cookie.cookie.Name() + "=value")); + } else { + EXPECT_THAT(d.data_received(), ::testing::Not(::testing::HasSubstr( + cookie.cookie.Name() + "=value"))); + } + + std::vector<CookieInclusionStatus::ExclusionReason> exclusions; + std::vector<CookieInclusionStatus::WarningReason> warnings; + if (!included) { + exclusions.push_back(CookieInclusionStatus:: + EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX); + warnings.push_back(CookieInclusionStatus:: + WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT); + } + if (base::Contains(test.expected_compat_warning_cookies, cookie_name)) { + warnings.push_back(CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR); + } + EXPECT_TRUE( + cookie.access_result.status.HasExactlyExclusionReasonsForTesting( + exclusions)); + EXPECT_TRUE( + cookie.access_result.status.HasExactlyWarningReasonsForTesting( + warnings)); + } + } + } +} + // Test that the SameSite-by-default CookieInclusionStatus warnings do not get // set if the cookie would have been rejected for other reasons. // Regression test for https://crbug.com/1027318. @@ -6908,8 +7158,7 @@ TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) { // doesn't even make it to the cookie store (it is filtered out beforehand). EXPECT_TRUE(req->maybe_stored_cookies()[0] .status.HasExactlyExclusionReasonsForTesting( - {CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + {CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); EXPECT_FALSE(req->maybe_stored_cookies()[0].status.ShouldWarn()); // Cookie that would be included had it not been for the new SameSite rules @@ -6918,22 +7167,21 @@ TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) { req->maybe_stored_cookies()[1].cookie->Name()); EXPECT_TRUE(req->maybe_stored_cookies()[1] .status.HasExactlyExclusionReasonsForTesting( - {CanonicalCookie::CookieInclusionStatus:: + {CookieInclusionStatus:: EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})); EXPECT_TRUE(req->maybe_stored_cookies()[1] .status.HasExactlyWarningReasonsForTesting( - {CanonicalCookie::CookieInclusionStatus:: + {CookieInclusionStatus:: WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT})); // Cookie that is blocked because of invalid Secure attribute is not warned // about. EXPECT_EQ("invalidsecure", req->maybe_stored_cookies()[2].cookie->Name()); - EXPECT_TRUE( - req->maybe_stored_cookies()[2] - .status.HasExactlyExclusionReasonsForTesting( - {CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY, - CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})); + EXPECT_TRUE(req->maybe_stored_cookies()[2] + .status.HasExactlyExclusionReasonsForTesting( + {CookieInclusionStatus::EXCLUDE_SECURE_ONLY, + CookieInclusionStatus:: + EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})); EXPECT_FALSE(req->maybe_stored_cookies()[2].status.ShouldWarn()); } @@ -6944,14 +7192,13 @@ TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) { auto cookie1 = CanonicalCookie::Create(url, "cookienosamesite=1", base::Time::Now(), base::nullopt); base::RunLoop run_loop; - CanonicalCookie::CookieInclusionStatus status; + CookieInclusionStatus status; cm.SetCanonicalCookieAsync( std::move(cookie1), url, CookieOptions::MakeAllInclusive(), - base::BindLambdaForTesting( - [&](CanonicalCookie::CookieInclusionStatus result) { - status = result; - run_loop.Quit(); - })); + base::BindLambdaForTesting([&](CookieInclusionStatus result) { + status = result; + run_loop.Quit(); + })); run_loop.Run(); EXPECT_TRUE(status.IsInclude()); @@ -6970,14 +7217,14 @@ TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) { ASSERT_EQ(1u, req->maybe_sent_cookies().size()); EXPECT_EQ("cookienosamesite", req->maybe_sent_cookies()[0].cookie.Name()); EXPECT_TRUE(req->maybe_sent_cookies()[0] - .status.HasExactlyExclusionReasonsForTesting( - {CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES, - CanonicalCookie::CookieInclusionStatus:: + .access_result.status.HasExactlyExclusionReasonsForTesting( + {CookieInclusionStatus::EXCLUDE_USER_PREFERENCES, + CookieInclusionStatus:: EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})); // Cookie should not be warned about because it was blocked because of user // preferences. - EXPECT_FALSE(req->maybe_sent_cookies()[0].status.ShouldWarn()); + EXPECT_FALSE( + req->maybe_sent_cookies()[0].access_result.status.ShouldWarn()); } network_delegate.unset_block_get_cookies(); @@ -6988,14 +7235,13 @@ TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) { base::Time::Now(), base::nullopt); base::RunLoop run_loop; // Note: cookie1 from the previous testcase is still in the cookie store. - CanonicalCookie::CookieInclusionStatus status; + CookieInclusionStatus status; cm.SetCanonicalCookieAsync( std::move(cookie2), url, CookieOptions::MakeAllInclusive(), - base::BindLambdaForTesting( - [&](CanonicalCookie::CookieInclusionStatus result) { - status = result; - run_loop.Quit(); - })); + base::BindLambdaForTesting([&](CookieInclusionStatus result) { + status = result; + run_loop.Quit(); + })); run_loop.Run(); EXPECT_TRUE(status.IsInclude()); @@ -7017,24 +7263,24 @@ TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) { // Note: this cookie is first because the cookies are sorted by path length // with longest first. See CookieSorter() in cookie_monster.cc. EXPECT_EQ("cookiewithpath", req->maybe_sent_cookies()[0].cookie.Name()); - EXPECT_TRUE( - req->maybe_sent_cookies()[0] - .status.HasExactlyExclusionReasonsForTesting( - {CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH, - CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})); - EXPECT_FALSE(req->maybe_sent_cookies()[0].status.ShouldWarn()); + EXPECT_TRUE(req->maybe_sent_cookies()[0] + .access_result.status.HasExactlyExclusionReasonsForTesting( + {CookieInclusionStatus::EXCLUDE_NOT_ON_PATH, + CookieInclusionStatus:: + EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})); + EXPECT_FALSE( + req->maybe_sent_cookies()[0].access_result.status.ShouldWarn()); // Cookie that was only blocked because of unspecified SameSite should be // warned about. EXPECT_EQ("cookienosamesite", req->maybe_sent_cookies()[1].cookie.Name()); EXPECT_TRUE(req->maybe_sent_cookies()[1] - .status.HasExactlyExclusionReasonsForTesting( - {CanonicalCookie::CookieInclusionStatus:: + .access_result.status.HasExactlyExclusionReasonsForTesting( + {CookieInclusionStatus:: EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})); - EXPECT_TRUE( - req->maybe_sent_cookies()[1].status.HasExactlyWarningReasonsForTesting( - {CanonicalCookie::CookieInclusionStatus:: - WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT})); + EXPECT_TRUE(req->maybe_sent_cookies()[1] + .access_result.status.HasExactlyWarningReasonsForTesting( + {CookieInclusionStatus:: + WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT})); } } @@ -7060,8 +7306,7 @@ TEST_F(URLRequestTestHTTP, AuthChallengeCancelCookieCollect) { ASSERT_EQ(1u, request->maybe_stored_cookies().size()); EXPECT_TRUE(request->maybe_stored_cookies()[0] .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); EXPECT_EQ("got_challenged=true", request->maybe_stored_cookies()[0].cookie_string); @@ -7099,11 +7344,11 @@ TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) { // The number of cookies blocked from the most recent round trip. ASSERT_EQ(1u, request->maybe_stored_cookies().size()); - EXPECT_TRUE(request->maybe_stored_cookies() - .front() - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + request->maybe_stored_cookies() + .front() + .status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); // Now check the second round trip request->SetAuth(AuthCredentials(kUser, kSecret)); @@ -7153,11 +7398,11 @@ TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) { EXPECT_EQ("another_cookie", request->maybe_sent_cookies().front().cookie.Name()); EXPECT_EQ("true", request->maybe_sent_cookies().front().cookie.Value()); - EXPECT_TRUE(request->maybe_sent_cookies() - .front() - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + request->maybe_sent_cookies() + .front() + .access_result.status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); // Check maybe_sent_cookies on second roundtrip. request->set_maybe_sent_cookies({}); @@ -7188,11 +7433,11 @@ TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) { ASSERT_EQ(1u, request->maybe_sent_cookies().size()); EXPECT_EQ("one_more_cookie", request->maybe_sent_cookies().front().cookie.Name()); - EXPECT_TRUE(request->maybe_sent_cookies() - .front() - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + request->maybe_sent_cookies() + .front() + .access_result.status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); } } @@ -7503,11 +7748,11 @@ TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) { EXPECT_EQ("server-redirect", request->maybe_stored_cookies().front().cookie->Name()); EXPECT_EQ("true", request->maybe_stored_cookies().front().cookie->Value()); - EXPECT_TRUE(request->maybe_stored_cookies() - .front() - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + request->maybe_stored_cookies() + .front() + .status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); // Check maybe_stored_cookies on second round trip (and clearing from the // first). @@ -7526,11 +7771,11 @@ TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) { EXPECT_EQ("server-redirect", request->maybe_stored_cookies().front().cookie->Name()); EXPECT_EQ("other", request->maybe_stored_cookies().front().cookie->Value()); - EXPECT_TRUE(request->maybe_stored_cookies() - .front() - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + request->maybe_stored_cookies() + .front() + .status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); } // Check maybe_sent_cookies on first round trip. @@ -7561,11 +7806,11 @@ TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) { ASSERT_EQ(1u, request->maybe_sent_cookies().size()); EXPECT_EQ("another_cookie", request->maybe_sent_cookies().front().cookie.Name()); - EXPECT_TRUE(request->maybe_sent_cookies() - .front() - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + request->maybe_sent_cookies() + .front() + .access_result.status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); // Check maybe_sent_cookies on second round trip request->set_maybe_sent_cookies({}); @@ -7592,11 +7837,11 @@ TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) { EXPECT_EQ("one_more_cookie", request->maybe_sent_cookies().front().cookie.Name()); EXPECT_EQ("true", request->maybe_sent_cookies().front().cookie.Value()); - EXPECT_TRUE(request->maybe_sent_cookies() - .front() - .status.HasExactlyExclusionReasonsForTesting( - {net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES})); + EXPECT_TRUE( + request->maybe_sent_cookies() + .front() + .access_result.status.HasExactlyExclusionReasonsForTesting( + {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES})); } } @@ -8123,34 +8368,19 @@ class URLRequestTestReferrerPolicy : public URLRequestTest { URLRequestTestReferrerPolicy() = default; void InstantiateSameOriginServers(net::EmbeddedTestServer::Type type) { - origin_server_.reset(new EmbeddedTestServer(type)); - if (type == net::EmbeddedTestServer::TYPE_HTTPS) { - origin_server_->AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); - } else { - origin_server_->AddDefaultHandlers(base::FilePath(kTestFilePath)); - } + origin_server_ = std::make_unique<EmbeddedTestServer>(type); + RegisterDefaultHandlers(origin_server_.get()); ASSERT_TRUE(origin_server_->Start()); } void InstantiateCrossOriginServers(net::EmbeddedTestServer::Type origin_type, net::EmbeddedTestServer::Type dest_type) { - origin_server_.reset(new EmbeddedTestServer(origin_type)); - if (origin_type == net::EmbeddedTestServer::TYPE_HTTPS) { - origin_server_->AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); - } else { - origin_server_->AddDefaultHandlers(base::FilePath(kTestFilePath)); - } + origin_server_ = std::make_unique<EmbeddedTestServer>(origin_type); + RegisterDefaultHandlers(origin_server_.get()); ASSERT_TRUE(origin_server_->Start()); - destination_server_.reset(new EmbeddedTestServer(dest_type)); - if (dest_type == net::EmbeddedTestServer::TYPE_HTTPS) { - destination_server_->AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); - } else { - destination_server_->AddDefaultHandlers(base::FilePath(kTestFilePath)); - } + destination_server_ = std::make_unique<EmbeddedTestServer>(dest_type); + RegisterDefaultHandlers(destination_server_.get()); ASSERT_TRUE(destination_server_->Start()); } @@ -8454,8 +8684,7 @@ class HTTPSRequestTest : public TestWithTaskEnvironment { TEST_F(HTTPSRequestTest, HTTPSGetTest) { EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); TestDelegate d; @@ -8482,8 +8711,7 @@ TEST_F(HTTPSRequestTest, HTTPSGetTest) { TEST_F(HTTPSRequestTest, HTTPSMismatchedTest) { EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); bool err_allowed = true; @@ -8516,8 +8744,7 @@ TEST_F(HTTPSRequestTest, HTTPSMismatchedTest) { TEST_F(HTTPSRequestTest, HTTPSExpiredTest) { EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); // Iterate from false to true, just so that we do the opposite of the @@ -8578,8 +8805,7 @@ class SSLNetErrorTestDelegate : public TestDelegate { TEST_F(HTTPSRequestTest, SSLNetErrorReportedToDelegate) { EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); SSLNetErrorTestDelegate d; @@ -8675,7 +8901,7 @@ TEST_F(HTTPSRequestTest, HTTPSErrorsNoClobberTSSTest) { TransportSecurityState::STSState dynamic_sts_state; TransportSecurityState::PKPState dynamic_pkp_state; EXPECT_FALSE(transport_security_state.GetDynamicSTSState( - "hsts-hpkp-preloaded.test", &dynamic_sts_state, nullptr)); + "hsts-hpkp-preloaded.test", &dynamic_sts_state)); EXPECT_FALSE(transport_security_state.GetDynamicPKPState( "hsts-hpkp-preloaded.test", &dynamic_pkp_state)); @@ -8704,7 +8930,7 @@ TEST_F(HTTPSRequestTest, HTTPSErrorsNoClobberTSSTest) { TransportSecurityState::STSState new_dynamic_sts_state; TransportSecurityState::PKPState new_dynamic_pkp_state; EXPECT_FALSE(transport_security_state.GetDynamicSTSState( - "hsts-hpkp-preloaded.test", &new_dynamic_sts_state, nullptr)); + "hsts-hpkp-preloaded.test", &new_dynamic_sts_state)); EXPECT_FALSE(transport_security_state.GetDynamicPKPState( "hsts-hpkp-preloaded.test", &new_dynamic_pkp_state)); @@ -8723,8 +8949,7 @@ TEST_F(HTTPSRequestTest, HSTSPreservesPosts) { static const char kData[] = "hello world"; EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); @@ -8909,8 +9134,7 @@ TEST_F(HTTPSRequestTest, ClientAuthNoCertificate) { ssl_config.client_cert_type = SSLServerConfig::ClientCertType::OPTIONAL_CLIENT_CERT; test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); SSLClientAuthTestDelegate d; @@ -8956,8 +9180,7 @@ TEST_F(HTTPSRequestTest, ClientAuth) { ssl_config.client_cert_type = SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT; test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); { @@ -9038,8 +9261,7 @@ TEST_F(HTTPSRequestTest, ClientAuthFailSigning) { ssl_config.client_cert_type = SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT; test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); { @@ -9119,8 +9341,7 @@ TEST_F(HTTPSRequestTest, ClientAuthFailSigningRetry) { ssl_config.client_cert_type = SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT; test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); // Connect with a client certificate to put it in the client auth cache. @@ -9587,8 +9808,7 @@ class HTTPSCertNetFetchingTest : public HTTPSRequestTest { EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS); test_server.SetSSLConfig(cert_config); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); delegate->set_allow_certificate_errors(true); @@ -10287,8 +10507,7 @@ TEST_F(HTTPSAIATest, AIAFetching) { EmbeddedTestServer::ServerCertificateConfig cert_config; cert_config.intermediate = EmbeddedTestServer::IntermediateType::kByAIA; test_server.SetSSLConfig(cert_config); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); TestDelegate d; @@ -10589,8 +10808,7 @@ TEST_F(HTTPSCRLSetTest, CRLSetRevoked) { {{OCSPRevocationStatus::GOOD, EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}}); test_server.SetSSLConfig(cert_config); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); CertVerifier::Config cert_verifier_config = GetCertVerifierConfig(); @@ -10629,8 +10847,7 @@ TEST_F(HTTPSCRLSetTest, CRLSetRevokedBySubject) { {{OCSPRevocationStatus::GOOD, EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}}); test_server.SetSSLConfig(cert_config); - test_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server); ASSERT_TRUE(test_server.Start()); std::string common_name = test_server.GetCertificate()->subject().common_name; @@ -10705,8 +10922,7 @@ TEST_F(HTTPSLocalCRLSetTest, KnownInterceptionBlocked) { // Verify the connection succeeds without being flagged. EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS); - https_server.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&https_server); https_server.SetSSLConfig(EmbeddedTestServer::CERT_OK_BY_INTERMEDIATE); ASSERT_TRUE(https_server.Start()); @@ -11770,8 +11986,7 @@ class HTTPSEarlyDataTest : public TestWithTaskEnvironment { ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_3; ssl_config_.early_data_enabled = true; test_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config_); - test_server_.AddDefaultHandlers( - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); + RegisterDefaultHandlers(&test_server_); test_server_.RegisterRequestHandler( base::BindRepeating(&HandleZeroRTTRequest)); test_server_.SetConnectionListener(&listener_); |