#include <stdint.h>
#include <algorithm>
#include <iterator>
#include <limits>
#include <memory>
#include <optional>
#include <string_view>
#include <utility>
#include "base/android/android_info.h"
#include "base/base64.h"
#include "base/base64url.h"
#include "base/compiler_specific.h"
#include "base/containers/heap_array.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/escape.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/string_view_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "base/test/values_test_util.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "crypto/hash.h"
#include "net/http/http_transaction.h"
#if BUILDFLAG(ARKWEB_UNITTESTS)
#define private public
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#undef private
#else
#include "net/url_request/url_request.h"
#endif
#include "net/base/chunked_upload_data_stream.h"
#include "net/base/cronet_buildflags.h"
#include "net/base/directory_listing.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/features.h"
#include "net/base/hash_value.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
#include "net/base/net_errors.h"
#include "net/base/net_module.h"
#include "net/base/proxy_chain.h"
#include "net/base/proxy_server.h"
#include "net/base/proxy_string_util.h"
#include "net/base/request_priority.h"
#include "net/base/test_completion_callback.h"
#include "net/base/transport_info.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
#include "net/base/url_util.h"
#include "net/cert/asn1_util.h"
#include "net/cert/caching_cert_verifier.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/coalescing_cert_verifier.h"
#include "net/cert/crl_set.h"
#include "net/cert/do_nothing_ct_verifier.h"
#include "net/cert/ev_root_ca_metadata.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/multi_log_ct_verifier.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/cert/test_root_certs.h"
#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_setting_override.h"
#include "net/cookies/cookie_store_test_helpers.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/test_cookie_access_delegate.h"
#include "net/disk_cache/disk_cache.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/host_resolver_results.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_byte_range.h"
#include "net/http/http_cache.h"
#include "net/http/http_connection_info.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_status_code.h"
#include "net/http/http_transaction_test_util.h"
#include "net/http/http_util.h"
#include "net/http/no_vary_search_cache_storage_file_operations.h"
#include "net/http/transport_security_state.h"
#include "net/http/transport_security_state_source.h"
#include "net/log/file_net_log_observer.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
#include "net/net_buildflags.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/quic/mock_crypto_client_stream_factory.h"
#include "net/quic/quic_server_info.h"
#include "net/socket/read_buffering_stream_socket.h"
#include "net/socket/socket_test_util.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/client_cert_identity_test_util.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_private_key.h"
#include "net/ssl/ssl_server_config.h"
#include "net/ssl/test_ssl_config_service.h"
#include "net/storage_access_api/status.h"
#include "net/test/cert_test_util.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
#include "net/test/test_with_task_environment.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/test/url_request/url_request_mock_http_job.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/referrer_policy.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/storage_access_status_cache.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_http_job.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_redirect_job.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "net/url_request/websocket_handshake_userdata_key.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "url/origin.h"
#include "url/url_constants.h"
#include "url/url_util.h"
#if BUILDFLAG(IS_WIN)
#include <objbase.h>
#include <windows.h>
#include <shlobj.h>
#include <wrl/client.h>
#include "base/win/scoped_com_initializer.h"
#endif
#if BUILDFLAG(IS_APPLE)
#include "base/mac/mac_util.h"
#endif
#if BUILDFLAG(ENABLE_REPORTING)
#include "net/network_error_logging/network_error_logging_service.h"
#include "net/network_error_logging/network_error_logging_test_util.h"
#endif
#if BUILDFLAG(ENABLE_WEBSOCKETS)
#include "net/websockets/websocket_test_util.h"
#endif
using net::test::IsError;
using net::test::IsOk;
using net::test_server::RegisterDefaultHandlers;
using testing::_;
using testing::AnyOf;
using testing::ElementsAre;
using testing::HasSubstr;
using testing::IsEmpty;
using testing::Not;
using testing::Optional;
using testing::UnorderedElementsAre;
using base::ASCIIToUTF16;
using base::Time;
using std::string;
namespace net {
namespace {
namespace test_default {
#include "net/http/transport_security_state_static_unittest_default.h"
}
const std::u16string kSecret(u"secret");
const std::u16string kUser(u"user");
const base::FilePath::CharType kTestFilePath[] =
FILE_PATH_LITERAL("net/data/url_request_unittest");
void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
int connect_timing_flags) {
EXPECT_FALSE(load_timing_info.socket_reused);
EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
EXPECT_FALSE(load_timing_info.request_start_time.is_null());
EXPECT_FALSE(load_timing_info.request_start.is_null());
EXPECT_LE(load_timing_info.request_start,
load_timing_info.connect_timing.connect_start);
ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
connect_timing_flags);
EXPECT_LE(load_timing_info.connect_timing.connect_end,
load_timing_info.send_start);
EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
EXPECT_LE(load_timing_info.send_end, load_timing_info.receive_headers_start);
EXPECT_LE(load_timing_info.receive_headers_start,
load_timing_info.receive_headers_end);
EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
}
void TestLoadTimingNotReusedWithProxy(const LoadTimingInfo& load_timing_info,
int connect_timing_flags) {
EXPECT_FALSE(load_timing_info.socket_reused);
EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
EXPECT_FALSE(load_timing_info.request_start_time.is_null());
EXPECT_FALSE(load_timing_info.request_start.is_null());
EXPECT_LE(load_timing_info.request_start,
load_timing_info.proxy_resolve_start);
EXPECT_LE(load_timing_info.proxy_resolve_start,
load_timing_info.proxy_resolve_end);
EXPECT_LE(load_timing_info.proxy_resolve_end,
load_timing_info.connect_timing.connect_start);
ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
connect_timing_flags);
EXPECT_LE(load_timing_info.connect_timing.connect_end,
load_timing_info.send_start);
EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
EXPECT_LE(load_timing_info.send_end, load_timing_info.receive_headers_start);
EXPECT_LE(load_timing_info.receive_headers_start,
load_timing_info.receive_headers_end);
}
void TestLoadTimingReusedWithProxy(const LoadTimingInfo& load_timing_info) {
EXPECT_TRUE(load_timing_info.socket_reused);
EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
EXPECT_FALSE(load_timing_info.request_start_time.is_null());
EXPECT_FALSE(load_timing_info.request_start.is_null());
ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
EXPECT_LE(load_timing_info.request_start,
load_timing_info.proxy_resolve_start);
EXPECT_LE(load_timing_info.proxy_resolve_start,
load_timing_info.proxy_resolve_end);
EXPECT_LE(load_timing_info.proxy_resolve_end, load_timing_info.send_start);
EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
EXPECT_LE(load_timing_info.send_end, load_timing_info.receive_headers_start);
EXPECT_LE(load_timing_info.receive_headers_start,
load_timing_info.receive_headers_end);
}
CookieList GetAllCookies(URLRequestContext* request_context) {
CookieList cookie_list;
base::RunLoop run_loop;
request_context->cookie_store()->GetAllCookiesAsync(
base::BindLambdaForTesting([&](const CookieList& cookies) {
cookie_list = cookies;
run_loop.Quit();
}));
run_loop.Run();
return cookie_list;
}
void TestLoadTimingCacheHitNoNetwork(const LoadTimingInfo& load_timing_info) {
EXPECT_FALSE(load_timing_info.socket_reused);
EXPECT_EQ(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
EXPECT_FALSE(load_timing_info.request_start_time.is_null());
EXPECT_FALSE(load_timing_info.request_start.is_null());
ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
EXPECT_LE(load_timing_info.request_start, load_timing_info.send_start);
EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
EXPECT_LE(load_timing_info.send_end, load_timing_info.receive_headers_start);
EXPECT_LE(load_timing_info.receive_headers_start,
load_timing_info.receive_headers_end);
EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
}
class PriorityMonitoringURLRequestJob : public URLRequestTestJob {
public:
PriorityMonitoringURLRequestJob(URLRequest* request,
RequestPriority* request_priority)
: URLRequestTestJob(request), request_priority_(request_priority) {
*request_priority_ = DEFAULT_PRIORITY;
}
void SetPriority(RequestPriority priority) override {
*request_priority_ = priority;
URLRequestTestJob::SetPriority(priority);
}
private:
const raw_ptr<RequestPriority> request_priority_;
};
bool ContainsString(const std::string& haystack, const char* needle) {
return std::ranges::search(haystack, std::string_view(needle),
base::CaseInsensitiveCompareASCII<char>())
.begin() != haystack.end();
}
std::unique_ptr<UploadDataStream> CreateSimpleUploadData(
base::span<const uint8_t> data) {
auto reader = std::make_unique<UploadBytesElementReader>(data);
return ElementsUploadDataStream::CreateWithReader(std::move(reader));
}
void CheckSSLInfo(const SSLInfo& ssl_info) {
uint16_t cipher_suite =
SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
EXPECT_NE(0U, cipher_suite);
}
class BlockingNetworkDelegate : public TestNetworkDelegate {
public:
enum Stage {
NOT_BLOCKED = 0,
ON_BEFORE_URL_REQUEST = 1 << 0,
ON_BEFORE_SEND_HEADERS = 1 << 1,
ON_HEADERS_RECEIVED = 1 << 2,
};
enum BlockMode {
SYNCHRONOUS,
AUTO_CALLBACK,
USER_CALLBACK,
};
explicit BlockingNetworkDelegate(BlockMode block_mode);
BlockingNetworkDelegate(const BlockingNetworkDelegate&) = delete;
BlockingNetworkDelegate& operator=(const BlockingNetworkDelegate&) = delete;
void RunUntilBlocked();
void DoCallback(int response);
void set_retval(int retval) {
ASSERT_NE(USER_CALLBACK, block_mode_);
ASSERT_NE(ERR_IO_PENDING, retval);
ASSERT_NE(OK, retval);
retval_ = retval;
}
void set_redirect_url(const GURL& url) { redirect_url_ = url; }
void set_block_on(int block_on) { block_on_ = block_on; }
Stage stage_blocked_for_callback() const {
EXPECT_EQ(USER_CALLBACK, block_mode_);
return stage_blocked_for_callback_;
}
private:
void OnBlocked();
void RunCallback(int response, CompletionOnceCallback callback);
int OnBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url) override;
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
const HttpResponseHeaders* original_response_headers,
scoped_refptr<HttpResponseHeaders>* override_response_headers,
const IPEndPoint& endpoint,
std::optional<GURL>* preserve_fragment_on_redirect_url,
const std::optional<net::SSLInfo>& ssl_info) override;
void Reset();
int MaybeBlockStage(Stage stage, CompletionOnceCallback callback);
const BlockMode block_mode_;
int retval_ = OK;
GURL redirect_url_;
int block_on_ = 0;
Stage stage_blocked_for_callback_ = NOT_BLOCKED;
CompletionOnceCallback callback_;
base::OnceClosure on_blocked_;
base::WeakPtrFactory<BlockingNetworkDelegate> weak_factory_{this};
};
BlockingNetworkDelegate::BlockingNetworkDelegate(BlockMode block_mode)
: block_mode_(block_mode) {}
void BlockingNetworkDelegate::RunUntilBlocked() {
base::RunLoop run_loop;
on_blocked_ = run_loop.QuitClosure();
run_loop.Run();
}
void BlockingNetworkDelegate::DoCallback(int response) {
ASSERT_EQ(USER_CALLBACK, block_mode_);
ASSERT_NE(NOT_BLOCKED, stage_blocked_for_callback_);
CompletionOnceCallback callback = std::move(callback_);
Reset();
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&BlockingNetworkDelegate::RunCallback,
weak_factory_.GetWeakPtr(), response,
std::move(callback)));
}
void BlockingNetworkDelegate::OnBlocked() {
std::move(on_blocked_).Run();
}
void BlockingNetworkDelegate::RunCallback(int response,
CompletionOnceCallback callback) {
std::move(callback).Run(response);
}
int BlockingNetworkDelegate::OnBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url) {
if (redirect_url_ == request->url())
return OK;
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeURLRequest(
request, base::NullCallback(), new_url));
if (!redirect_url_.is_empty())
*new_url = redirect_url_;
return MaybeBlockStage(ON_BEFORE_URL_REQUEST, std::move(callback));
}
int BlockingNetworkDelegate::OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) {
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
request, headers, base::NullCallback()));
return MaybeBlockStage(
ON_BEFORE_SEND_HEADERS,
base::BindOnce(
[](OnBeforeStartTransactionCallback callback, int result) {
std::move(callback).Run(result, std::nullopt);
},
std::move(callback)));
}
int BlockingNetworkDelegate::OnHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
const HttpResponseHeaders* original_response_headers,
scoped_refptr<HttpResponseHeaders>* override_response_headers,
const IPEndPoint& endpoint,
std::optional<GURL>* preserve_fragment_on_redirect_url,
const std::optional<net::SSLInfo>& ssl_info) {
CHECK_NE(ERR_IO_PENDING,
TestNetworkDelegate::OnHeadersReceived(
request, base::NullCallback(), original_response_headers,
override_response_headers, endpoint,
preserve_fragment_on_redirect_url, ssl_info));
return MaybeBlockStage(ON_HEADERS_RECEIVED, std::move(callback));
}
void BlockingNetworkDelegate::Reset() {
EXPECT_NE(NOT_BLOCKED, stage_blocked_for_callback_);
stage_blocked_for_callback_ = NOT_BLOCKED;
callback_.Reset();
}
int BlockingNetworkDelegate::MaybeBlockStage(
BlockingNetworkDelegate::Stage stage,
CompletionOnceCallback callback) {
EXPECT_EQ(NOT_BLOCKED, stage_blocked_for_callback_);
if ((block_on_ & stage) == 0) {
return OK;
}
switch (block_mode_) {
case SYNCHRONOUS:
EXPECT_NE(OK, retval_);
return retval_;
case AUTO_CALLBACK:
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&BlockingNetworkDelegate::RunCallback,
weak_factory_.GetWeakPtr(), retval_,
std::move(callback)));
return ERR_IO_PENDING;
case USER_CALLBACK:
callback_ = std::move(callback);
stage_blocked_for_callback_ = stage;
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&BlockingNetworkDelegate::OnBlocked,
weak_factory_.GetWeakPtr()));
return ERR_IO_PENDING;
}
NOTREACHED();
}
class OCSPErrorTestDelegate : public TestDelegate {
public:
void OnSSLCertificateError(URLRequest* request,
int net_error,
const SSLInfo& ssl_info,
bool fatal) override {
ssl_info_ = ssl_info;
on_ssl_certificate_error_called_ = true;
TestDelegate::OnSSLCertificateError(request, net_error, ssl_info, fatal);
}
bool on_ssl_certificate_error_called() {
return on_ssl_certificate_error_called_;
}
const SSLInfo& ssl_info() { return ssl_info_; }
private:
bool on_ssl_certificate_error_called_ = false;
SSLInfo ssl_info_;
};
#if !BUILDFLAG(IS_IOS)
std::array<uint8_t, crypto::hash::kSha256Size> GetTestRootCertSPKIHash() {
scoped_refptr<X509Certificate> root_cert =
ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem");
CHECK(root_cert);
std::string_view root_spki;
CHECK(asn1::ExtractSPKIFromDERCert(
x509_util::CryptoBufferAsStringPiece(root_cert->cert_buffer()),
&root_spki));
return crypto::hash::Sha256(root_spki);
}
#endif
}
class URLRequestTest : public PlatformTest, public WithTaskEnvironment {
public:
URLRequestTest() = default;
~URLRequestTest() override {
base::RunLoop().RunUntilIdle();
SetTransportSecurityStateSourceForTesting(nullptr);
}
void SetUp() override {
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_net_log(NetLog::Get());
SetUpContextBuilder(*context_builder);
context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
default_context_ = context_builder->Build();
PlatformTest::SetUp();
}
void TearDown() override { default_context_.reset(); }
virtual void SetUpContextBuilder(URLRequestContextBuilder& builder) {}
TestNetworkDelegate& default_network_delegate() {
return *static_cast<TestNetworkDelegate*>(
default_context_->network_delegate());
}
URLRequestContext& default_context() const { return *default_context_; }
void CreateTestFile(const char* data,
size_t data_size,
base::FilePath* test_file) {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::FilePath absolute_temp_dir =
base::MakeAbsoluteFilePath(temp_dir_.GetPath());
ASSERT_TRUE(base::CreateTemporaryFileInDir(absolute_temp_dir, test_file));
ASSERT_TRUE(base::WriteFile(*test_file, std::string_view(data, data_size)));
}
static std::unique_ptr<ConfiguredProxyResolutionService>
CreateFixedProxyResolutionService(const std::string& proxy) {
return ConfiguredProxyResolutionService::CreateFixedForTest(
proxy, TRAFFIC_ANNOTATION_FOR_TESTS);
}
std::unique_ptr<URLRequest> CreateFirstPartyRequest(
const URLRequestContext& context,
const GURL& url,
URLRequest::Delegate* delegate) {
auto req = context.CreateRequest(url, DEFAULT_PRIORITY, delegate,
TRAFFIC_ANNOTATION_FOR_TESTS);
req->set_initiator(url::Origin::Create(url));
req->set_site_for_cookies(SiteForCookies::FromUrl(url));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, url::Origin::Create(url),
url::Origin::Create(url), req->site_for_cookies()));
return req;
}
protected:
RecordingNetLogObserver net_log_observer_;
std::unique_ptr<URLRequestContext> default_context_;
base::ScopedTempDir temp_dir_;
};
TEST_F(URLRequestTest, AboutBlankTest) {
TestDelegate d;
{
std::unique_ptr<URLRequest> r(
default_context().CreateRequest(GURL("about:blank"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_TRUE(!r->is_pending());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(d.bytes_received(), 0);
EXPECT_TRUE(r->GetResponseRemoteEndpoint().address().empty());
EXPECT_EQ(0, r->GetResponseRemoteEndpoint().port());
}
}
TEST_F(URLRequestTest, InvalidUrlTest) {
TestDelegate d;
{
std::unique_ptr<URLRequest> r(
default_context().CreateRequest(GURL("invalid url"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_TRUE(d.request_failed());
}
}
TEST_F(URLRequestTest, WsUrlTest) {
const url::Origin kOrigin = url::Origin::Create(GURL("http://foo.test/"));
TestDelegate d;
std::unique_ptr<URLRequest> r(
default_context().CreateRequest(GURL("ws://foo.test/"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, SiteForCookies::FromOrigin(kOrigin)));
r->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.request_failed());
EXPECT_THAT(d.request_status(), IsError(ERR_UNKNOWN_URL_SCHEME));
}
TEST_F(URLRequestTest, WssUrlTest) {
const url::Origin kOrigin = url::Origin::Create(GURL("https://foo.test/"));
TestDelegate d;
std::unique_ptr<URLRequest> r(
default_context().CreateRequest(GURL("wss://foo.test/"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, SiteForCookies::FromOrigin(kOrigin)));
r->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.request_failed());
EXPECT_THAT(d.request_status(), IsError(ERR_UNKNOWN_URL_SCHEME));
}
TEST_F(URLRequestTest, InvalidReferrerTest) {
default_network_delegate().set_cancel_request_with_policy_violating_referrer(
true);
TestDelegate d;
std::unique_ptr<URLRequest> req = default_context().CreateRequest(
GURL("http://localhost/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS);
req->SetReferrer("https://somewhere.com/");
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.request_failed());
}
TEST_F(URLRequestTest, RecordsSameOriginReferrerHistogram) {
default_network_delegate().set_cancel_request_with_policy_violating_referrer(
false);
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://google.com");
req->set_referrer_policy(ReferrerPolicy::NEVER_CLEAR);
base::HistogramTester histograms;
req->Start();
d.RunUntilComplete();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerPolicyForRequest.SameOrigin",
static_cast<int>(ReferrerPolicy::NEVER_CLEAR), 1);
}
TEST_F(URLRequestTest, RecordsCrossOriginReferrerHistogram) {
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://origin.com");
req->set_referrer_policy(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE);
base::HistogramTester histograms;
req->Start();
d.RunUntilComplete();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerPolicyForRequest.CrossOrigin",
static_cast<int>(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
1);
}
TEST_F(URLRequestTest, RecordsReferrerHistogramAgainOnRedirect) {
auto context_builder = CreateTestURLRequestContextBuilder();
auto network_delegate = std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS);
network_delegate->set_redirect_url(GURL("http://redirect.com/"));
context_builder->set_network_delegate(std::move(network_delegate));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://google.com");
req->set_referrer_policy(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE);
base::HistogramTester histograms;
req->Start();
d.RunUntilRedirect();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerPolicyForRequest.SameOrigin",
static_cast<int>(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
1);
req->FollowDeferredRedirect(std::nullopt,
std::nullopt);
d.RunUntilComplete();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerPolicyForRequest.CrossOrigin",
static_cast<int>(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
1);
}
TEST_F(URLRequestTest, RecordsReferrrerWithInformativePath) {
auto context_builder = CreateTestURLRequestContextBuilder();
auto network_delegate = std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS);
network_delegate->set_cancel_request_with_policy_violating_referrer(true);
network_delegate->set_redirect_url(GURL("http://redirect.com/"));
context_builder->set_network_delegate(std::move(network_delegate));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://google.com/very-informative-path");
base::HistogramTester histograms;
req->Start();
d.RunUntilRedirect();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerHasInformativePath.SameOrigin",
true,
1);
req->FollowDeferredRedirect(std::nullopt,
std::nullopt);
d.RunUntilComplete();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerHasInformativePath.CrossOrigin", true, 1);
}
TEST_F(URLRequestTest, RecordsReferrerWithInformativeQuery) {
auto context_builder = CreateTestURLRequestContextBuilder();
auto network_delegate = std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS);
network_delegate->set_cancel_request_with_policy_violating_referrer(true);
network_delegate->set_redirect_url(GURL("http://redirect.com/"));
context_builder->set_network_delegate(std::move(network_delegate));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://google.com/?very-informative-query");
base::HistogramTester histograms;
req->Start();
d.RunUntilRedirect();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerHasInformativePath.SameOrigin",
true,
1);
req->FollowDeferredRedirect(std::nullopt,
std::nullopt);
d.RunUntilComplete();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerHasInformativePath.CrossOrigin", true, 1);
}
TEST_F(URLRequestTest, RecordsReferrerWithoutInformativePathOrQuery) {
auto context_builder = CreateTestURLRequestContextBuilder();
auto network_delegate = std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS);
network_delegate->set_cancel_request_with_policy_violating_referrer(false);
network_delegate->set_redirect_url(GURL("http://origin.com/"));
context_builder->set_network_delegate(std::move(network_delegate));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://origin.com");
base::HistogramTester histograms;
req->Start();
d.RunUntilRedirect();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerHasInformativePath.CrossOrigin", false, 1);
req->FollowDeferredRedirect(std::nullopt,
std::nullopt);
d.RunUntilComplete();
histograms.ExpectUniqueSample(
"Net.URLRequest.ReferrerHasInformativePath.SameOrigin", false, 1);
}
class URLRequestInterceptorWithLoadTimingInfo : public URLRequestInterceptor {
public:
static std::string ok_data() { return URLRequestTestJob::test_data_1(); }
static std::string ok_headers() { return URLRequestTestJob::test_headers(); }
URLRequestInterceptorWithLoadTimingInfo() = default;
~URLRequestInterceptorWithLoadTimingInfo() override = default;
std::unique_ptr<URLRequestJob> MaybeInterceptRequest(
URLRequest* request) const override {
std::unique_ptr<URLRequestTestJob> job =
std::make_unique<URLRequestTestJob>(request, ok_headers(), ok_data(),
true);
job->set_load_timing_info(main_request_load_timing_info_);
return job;
}
void set_main_request_load_timing_info(
const LoadTimingInfo& main_request_load_timing_info) {
main_request_load_timing_info_ = main_request_load_timing_info;
}
private:
mutable LoadTimingInfo main_request_load_timing_info_;
};
class URLRequestLoadTimingTest : public URLRequestTest {
public:
URLRequestLoadTimingTest() {
std::unique_ptr<URLRequestInterceptorWithLoadTimingInfo> interceptor =
std::make_unique<URLRequestInterceptorWithLoadTimingInfo>();
interceptor_ = interceptor.get();
URLRequestFilter::GetInstance()->AddHostnameInterceptor(
"http", "test_intercept", std::move(interceptor));
}
~URLRequestLoadTimingTest() override {
URLRequestFilter::GetInstance()->ClearHandlers();
}
URLRequestInterceptorWithLoadTimingInfo* interceptor() const {
return interceptor_;
}
private:
raw_ptr<URLRequestInterceptorWithLoadTimingInfo, DanglingUntriaged>
interceptor_;
};
LoadTimingInfo NormalLoadTimingInfo(base::TimeTicks now,
int connect_time_flags,
bool used_proxy) {
LoadTimingInfo load_timing;
load_timing.socket_log_id = 1;
if (used_proxy) {
load_timing.proxy_resolve_start = now + base::Days(1);
load_timing.proxy_resolve_end = now + base::Days(2);
}
LoadTimingInfo::ConnectTiming& connect_timing = load_timing.connect_timing;
if (connect_time_flags & CONNECT_TIMING_HAS_DNS_TIMES) {
connect_timing.domain_lookup_start = now + base::Days(3);
connect_timing.domain_lookup_end = now + base::Days(4);
}
connect_timing.connect_start = now + base::Days(5);
if (connect_time_flags & CONNECT_TIMING_HAS_SSL_TIMES) {
connect_timing.ssl_start = now + base::Days(6);
connect_timing.ssl_end = now + base::Days(7);
}
connect_timing.connect_end = now + base::Days(8);
load_timing.send_start = now + base::Days(9);
load_timing.send_end = now + base::Days(10);
load_timing.receive_headers_start = now + base::Days(11);
load_timing.receive_headers_end = now + base::Days(12);
return load_timing;
}
LoadTimingInfo NormalLoadTimingInfoReused(base::TimeTicks now,
bool used_proxy) {
LoadTimingInfo load_timing;
load_timing.socket_log_id = 1;
load_timing.socket_reused = true;
if (used_proxy) {
load_timing.proxy_resolve_start = now + base::Days(1);
load_timing.proxy_resolve_end = now + base::Days(2);
}
load_timing.send_start = now + base::Days(9);
load_timing.send_end = now + base::Days(10);
load_timing.receive_headers_start = now + base::Days(11);
load_timing.receive_headers_end = now + base::Days(12);
return load_timing;
}
LoadTimingInfo RunURLRequestInterceptorLoadTimingTest(
const LoadTimingInfo& job_load_timing,
const URLRequestContext& context,
URLRequestInterceptorWithLoadTimingInfo* interceptor) {
interceptor->set_main_request_load_timing_info(job_load_timing);
TestDelegate d;
std::unique_ptr<URLRequest> req(
context.CreateRequest(GURL("http://test_intercept/foo"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
LoadTimingInfo resulting_load_timing;
req->GetLoadTimingInfo(&resulting_load_timing);
EXPECT_EQ(job_load_timing.socket_reused, resulting_load_timing.socket_reused);
EXPECT_EQ(job_load_timing.socket_log_id, resulting_load_timing.socket_log_id);
EXPECT_EQ(job_load_timing.send_start, resulting_load_timing.send_start);
EXPECT_EQ(job_load_timing.send_end, resulting_load_timing.send_end);
EXPECT_EQ(job_load_timing.receive_headers_start,
resulting_load_timing.receive_headers_start);
EXPECT_EQ(job_load_timing.receive_headers_end,
resulting_load_timing.receive_headers_end);
EXPECT_EQ(job_load_timing.push_start, resulting_load_timing.push_start);
EXPECT_EQ(job_load_timing.push_end, resulting_load_timing.push_end);
return resulting_load_timing;
}
TEST_F(URLRequestLoadTimingTest, InterceptLoadTiming) {
base::TimeTicks now = base::TimeTicks::Now();
LoadTimingInfo job_load_timing =
NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_DNS_TIMES, false);
LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
job_load_timing, default_context(), interceptor());
EXPECT_EQ(job_load_timing.proxy_resolve_start,
load_timing_result.proxy_resolve_start);
EXPECT_EQ(job_load_timing.proxy_resolve_end,
load_timing_result.proxy_resolve_end);
EXPECT_EQ(job_load_timing.connect_timing.domain_lookup_start,
load_timing_result.connect_timing.domain_lookup_start);
EXPECT_EQ(job_load_timing.connect_timing.domain_lookup_end,
load_timing_result.connect_timing.domain_lookup_end);
EXPECT_EQ(job_load_timing.connect_timing.connect_start,
load_timing_result.connect_timing.connect_start);
EXPECT_EQ(job_load_timing.connect_timing.connect_end,
load_timing_result.connect_timing.connect_end);
EXPECT_EQ(job_load_timing.connect_timing.ssl_start,
load_timing_result.connect_timing.ssl_start);
EXPECT_EQ(job_load_timing.connect_timing.ssl_end,
load_timing_result.connect_timing.ssl_end);
TestLoadTimingNotReused(load_timing_result, CONNECT_TIMING_HAS_DNS_TIMES);
}
TEST_F(URLRequestLoadTimingTest, InterceptLoadTimingProxy) {
base::TimeTicks now = base::TimeTicks::Now();
LoadTimingInfo job_load_timing =
NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_SSL_TIMES, true);
LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
job_load_timing, default_context(), interceptor());
EXPECT_EQ(job_load_timing.proxy_resolve_start,
load_timing_result.proxy_resolve_start);
EXPECT_EQ(job_load_timing.proxy_resolve_end,
load_timing_result.proxy_resolve_end);
EXPECT_EQ(job_load_timing.connect_timing.domain_lookup_start,
load_timing_result.connect_timing.domain_lookup_start);
EXPECT_EQ(job_load_timing.connect_timing.domain_lookup_end,
load_timing_result.connect_timing.domain_lookup_end);
EXPECT_EQ(job_load_timing.connect_timing.connect_start,
load_timing_result.connect_timing.connect_start);
EXPECT_EQ(job_load_timing.connect_timing.connect_end,
load_timing_result.connect_timing.connect_end);
EXPECT_EQ(job_load_timing.connect_timing.ssl_start,
load_timing_result.connect_timing.ssl_start);
EXPECT_EQ(job_load_timing.connect_timing.ssl_end,
load_timing_result.connect_timing.ssl_end);
TestLoadTimingNotReusedWithProxy(load_timing_result,
CONNECT_TIMING_HAS_SSL_TIMES);
}
TEST_F(URLRequestLoadTimingTest, InterceptLoadTimingEarlyProxyResolution) {
base::TimeTicks now = base::TimeTicks::Now();
LoadTimingInfo job_load_timing =
NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_DNS_TIMES, true);
job_load_timing.proxy_resolve_start = now - base::Days(6);
job_load_timing.proxy_resolve_end = now - base::Days(5);
job_load_timing.connect_timing.domain_lookup_start = now - base::Days(4);
job_load_timing.connect_timing.domain_lookup_end = now - base::Days(3);
job_load_timing.connect_timing.connect_start = now - base::Days(2);
job_load_timing.connect_timing.connect_end = now - base::Days(1);
LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
job_load_timing, default_context(), interceptor());
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.proxy_resolve_start);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.proxy_resolve_end);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.connect_timing.domain_lookup_start);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.connect_timing.domain_lookup_end);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.connect_timing.connect_start);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.connect_timing.connect_end);
TestLoadTimingNotReusedWithProxy(load_timing_result,
CONNECT_TIMING_HAS_DNS_TIMES);
}
TEST_F(URLRequestLoadTimingTest,
InterceptLoadTimingEarlyProxyResolutionReused) {
base::TimeTicks now = base::TimeTicks::Now();
LoadTimingInfo job_load_timing = NormalLoadTimingInfoReused(now, true);
job_load_timing.proxy_resolve_start = now - base::Days(4);
job_load_timing.proxy_resolve_end = now - base::Days(3);
LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
job_load_timing, default_context(), interceptor());
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.proxy_resolve_start);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.proxy_resolve_end);
TestLoadTimingReusedWithProxy(load_timing_result);
}
TEST_F(URLRequestLoadTimingTest, InterceptLoadTimingEarlyConnect) {
base::TimeTicks now = base::TimeTicks::Now();
LoadTimingInfo job_load_timing =
NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_SSL_TIMES, false);
job_load_timing.connect_timing.connect_start = now - base::Days(1);
job_load_timing.connect_timing.ssl_start = now - base::Days(2);
job_load_timing.connect_timing.ssl_end = now - base::Days(3);
job_load_timing.connect_timing.connect_end = now - base::Days(4);
LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
job_load_timing, default_context(), interceptor());
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.connect_timing.connect_start);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.connect_timing.ssl_start);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.connect_timing.ssl_end);
EXPECT_EQ(load_timing_result.request_start,
load_timing_result.connect_timing.connect_end);
TestLoadTimingNotReused(load_timing_result, CONNECT_TIMING_HAS_SSL_TIMES);
}
TEST_F(URLRequestLoadTimingTest, InterceptLoadTimingEarlyConnectWithProxy) {
base::TimeTicks now = base::TimeTicks::Now();
LoadTimingInfo job_load_timing =
NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY, true);
job_load_timing.connect_timing.connect_start = now - base::Days(1);
job_load_timing.connect_timing.connect_end = now - base::Days(2);
LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
job_load_timing, default_context(), interceptor());
EXPECT_EQ(load_timing_result.proxy_resolve_end,
load_timing_result.connect_timing.connect_start);
EXPECT_EQ(load_timing_result.proxy_resolve_end,
load_timing_result.connect_timing.connect_end);
TestLoadTimingNotReusedWithProxy(load_timing_result,
CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
}
TEST_F(URLRequestTest, NetworkDelegateProxyError) {
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_proxy_resolution_service(
CreateFixedProxyResolutionService("myproxy:70"));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddSimulatedTimeoutFailure("*");
context_builder->set_host_resolver(std::move(host_resolver));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(GURL("http://example.com"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_method("GET");
req->Start();
d.RunUntilComplete();
EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
req->proxy_chain());
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, d.request_status());
EXPECT_THAT(req->response_info().resolve_error_info.error,
IsError(ERR_DNS_TIMED_OUT));
EXPECT_EQ(1, network_delegate.error_count());
EXPECT_THAT(network_delegate.last_error(),
IsError(ERR_PROXY_CONNECTION_FAILED));
EXPECT_EQ(1, network_delegate.completed_requests());
}
TEST_F(URLRequestTest, DnsNameHttpsOnlyErrorCausesSchemeUpgrade) {
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
const std::string kHost = "foo.a.test";
const GURL https_url = https_server.GetURL(kHost, "/defaultresponse");
GURL::Replacements replacements;
replacements.SetSchemeStr(url::kHttpScheme);
const GURL http_url = https_url.ReplaceComponents(replacements);
auto host_resolver = std::make_unique<MockHostResolver>();
MockHostResolverBase::RuleResolver::RuleKey unencrypted_resolve_key;
unencrypted_resolve_key.scheme = url::kHttpScheme;
unencrypted_resolve_key.hostname_pattern = kHost;
host_resolver->rules()->AddRule(std::move(unencrypted_resolve_key),
ERR_DNS_NAME_HTTPS_ONLY);
MockHostResolverBase::RuleResolver::RuleKey encrypted_resolve_key;
encrypted_resolve_key.scheme = url::kHttpsScheme;
encrypted_resolve_key.hostname_pattern = kHost;
host_resolver->rules()->AddRule(std::move(encrypted_resolve_key),
https_server.GetIPLiteralString());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::move(host_resolver));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_FALSE(req->url().SchemeIsCryptographic());
req->Start();
d.RunUntilComplete();
EXPECT_EQ(d.received_redirect_count(), 1);
EXPECT_EQ(0, network_delegate.error_count());
EXPECT_EQ(200, req->GetResponseCode());
ASSERT_TRUE(req->response_headers());
EXPECT_EQ(200, req->response_headers()->response_code());
EXPECT_TRUE(req->url().SchemeIsCryptographic());
EXPECT_TRUE(req->url().SchemeIs(url::kHttpsScheme));
}
TEST_F(URLRequestTest, DnsNameHttpsOnlyErrorCausesSchemeUpgradeDeferred) {
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
const std::string kHost = "foo.a.test";
const GURL https_url = https_server.GetURL(kHost, "/defaultresponse");
GURL::Replacements replacements;
replacements.SetSchemeStr(url::kHttpScheme);
const GURL http_url = https_url.ReplaceComponents(replacements);
auto host_resolver = std::make_unique<MockHostResolver>();
MockHostResolverBase::RuleResolver::RuleKey unencrypted_resolve_key;
unencrypted_resolve_key.scheme = url::kHttpScheme;
unencrypted_resolve_key.hostname_pattern = kHost;
host_resolver->rules()->AddRule(std::move(unencrypted_resolve_key),
ERR_DNS_NAME_HTTPS_ONLY);
MockHostResolverBase::RuleResolver::RuleKey encrypted_resolve_key;
encrypted_resolve_key.scheme = url::kHttpsScheme;
encrypted_resolve_key.hostname_pattern = kHost;
host_resolver->rules()->AddRule(std::move(encrypted_resolve_key),
https_server.GetIPLiteralString());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::move(host_resolver));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_FALSE(req->url().SchemeIsCryptographic());
req->Start();
d.RunUntilRedirect();
EXPECT_EQ(d.received_redirect_count(), 1);
req->FollowDeferredRedirect(std::nullopt,
std::nullopt);
d.RunUntilComplete();
EXPECT_EQ(0, network_delegate.error_count());
EXPECT_EQ(200, req->GetResponseCode());
ASSERT_TRUE(req->response_headers());
EXPECT_EQ(200, req->response_headers()->response_code());
EXPECT_TRUE(req->url().SchemeIsCryptographic());
EXPECT_TRUE(req->url().SchemeIs(url::kHttpsScheme));
}
#if BUILDFLAG(ENABLE_WEBSOCKETS)
TEST_F(URLRequestTest, DnsHttpsRecordPresentCausesWsSchemeUpgrade) {
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
const std::string kHost = "foo.a.test";
const GURL https_url = https_server.GetURL(kHost, "/defaultresponse");
GURL::Replacements replacements;
replacements.SetSchemeStr(url::kWsScheme);
const GURL ws_url = https_url.ReplaceComponents(replacements);
auto host_resolver = std::make_unique<MockHostResolver>();
MockHostResolverBase::RuleResolver::RuleKey unencrypted_resolve_key;
unencrypted_resolve_key.scheme = url::kHttpScheme;
unencrypted_resolve_key.hostname_pattern = kHost;
host_resolver->rules()->AddRule(std::move(unencrypted_resolve_key),
ERR_DNS_NAME_HTTPS_ONLY);
MockHostResolverBase::RuleResolver::RuleKey encrypted_resolve_key;
encrypted_resolve_key.scheme = url::kHttpsScheme;
encrypted_resolve_key.hostname_pattern = kHost;
host_resolver->rules()->AddRule(std::move(encrypted_resolve_key),
https_server.GetIPLiteralString());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::move(host_resolver));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
ws_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS,
true));
EXPECT_FALSE(req->url().SchemeIsCryptographic());
HttpRequestHeaders headers = WebSocketCommonTestHeaders();
req->SetExtraRequestHeaders(headers);
auto websocket_stream_create_helper =
std::make_unique<TestWebSocketHandshakeStreamCreateHelper>();
req->SetUserData(kWebSocketHandshakeUserDataKey,
std::move(websocket_stream_create_helper));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(d.received_redirect_count(), 1);
EXPECT_EQ(network_delegate.error_count(), 1);
EXPECT_EQ(network_delegate.last_error(), ERR_INVALID_RESPONSE);
EXPECT_TRUE(req->url().SchemeIsCryptographic());
EXPECT_TRUE(req->url().SchemeIs(url::kWssScheme));
}
#endif
TEST_F(URLRequestTest, DnsHttpsRecordAbsentNoSchemeUpgrade) {
EmbeddedTestServer http_server(EmbeddedTestServer::TYPE_HTTP);
RegisterDefaultHandlers(&http_server);
ASSERT_TRUE(http_server.Start());
const std::string kHost = "foo.a.test";
const GURL http_url = http_server.GetURL(kHost, "/defaultresponse");
auto context_builder = CreateTestURLRequestContextBuilder();
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddRule(kHost, http_server.GetIPLiteralString());
context_builder->set_host_resolver(std::move(host_resolver));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_FALSE(req->url().SchemeIsCryptographic());
req->Start();
d.RunUntilComplete();
EXPECT_EQ(d.received_redirect_count(), 0);
EXPECT_EQ(0, network_delegate.error_count());
EXPECT_EQ(200, req->GetResponseCode());
ASSERT_TRUE(req->response_headers());
EXPECT_EQ(200, req->response_headers()->response_code());
EXPECT_EQ(http_url, req->url());
EXPECT_FALSE(req->url().SchemeIsCryptographic());
EXPECT_TRUE(req->url().SchemeIs(url::kHttpScheme));
}
TEST_F(URLRequestTest, SkipSecureDnsDisabledByDefault) {
auto context_builder = CreateTestURLRequestContextBuilder();
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddRule("example.com", "127.0.0.1");
context_builder->set_host_resolver(std::move(host_resolver));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(GURL("http://example.com"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(SecureDnsPolicy::kAllow,
static_cast<MockHostResolver*>(context->host_resolver())
->last_secure_dns_policy());
}
TEST_F(URLRequestTest, SkipSecureDnsEnabled) {
auto context_builder = CreateTestURLRequestContextBuilder();
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddRule("example.com", "127.0.0.1");
context_builder->set_host_resolver(std::move(host_resolver));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(GURL("http://example.com"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetSecureDnsPolicy(SecureDnsPolicy::kDisable);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(SecureDnsPolicy::kDisable,
static_cast<MockHostResolver*>(context->host_resolver())
->last_secure_dns_policy());
}
TEST_F(URLRequestTest, RequestCompletionForEmptyResponse) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL("/nocontent"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(204, req->GetResponseCode());
EXPECT_EQ("", d.data_received());
EXPECT_EQ(1, default_network_delegate().completed_requests());
}
TEST_F(URLRequestTest, SetPriorityBasic) {
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_EQ(DEFAULT_PRIORITY, req->priority());
req->SetPriority(LOW);
EXPECT_EQ(LOW, req->priority());
req->Start();
EXPECT_EQ(LOW, req->priority());
req->SetPriority(MEDIUM);
EXPECT_EQ(MEDIUM, req->priority());
}
TEST_F(URLRequestTest, SetJobPriorityBeforeJobStart) {
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_EQ(DEFAULT_PRIORITY, req->priority());
RequestPriority job_priority;
std::unique_ptr<URLRequestJob> job =
std::make_unique<PriorityMonitoringURLRequestJob>(req.get(),
&job_priority);
TestScopedURLInterceptor interceptor(req->url(), std::move(job));
EXPECT_EQ(DEFAULT_PRIORITY, job_priority);
req->SetPriority(LOW);
req->Start();
EXPECT_EQ(LOW, job_priority);
}
TEST_F(URLRequestTest, SetJobPriority) {
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
RequestPriority job_priority;
std::unique_ptr<URLRequestJob> job =
std::make_unique<PriorityMonitoringURLRequestJob>(req.get(),
&job_priority);
TestScopedURLInterceptor interceptor(req->url(), std::move(job));
req->SetPriority(LOW);
req->Start();
EXPECT_EQ(LOW, job_priority);
req->SetPriority(MEDIUM);
EXPECT_EQ(MEDIUM, req->priority());
EXPECT_EQ(MEDIUM, job_priority);
}
TEST_F(URLRequestTest, PriorityIgnoreLimits) {
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
GURL("http://test_intercept/foo"), MAXIMUM_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_EQ(MAXIMUM_PRIORITY, req->priority());
RequestPriority job_priority;
std::unique_ptr<URLRequestJob> job =
std::make_unique<PriorityMonitoringURLRequestJob>(req.get(),
&job_priority);
TestScopedURLInterceptor interceptor(req->url(), std::move(job));
req->SetLoadFlags(LOAD_IGNORE_LIMITS);
EXPECT_EQ(MAXIMUM_PRIORITY, req->priority());
req->SetPriority(MAXIMUM_PRIORITY);
EXPECT_EQ(MAXIMUM_PRIORITY, req->priority());
req->Start();
EXPECT_EQ(MAXIMUM_PRIORITY, req->priority());
EXPECT_EQ(MAXIMUM_PRIORITY, job_priority);
}
TEST_F(URLRequestTest, NotifyDelegateConnectedSkippedOnEarlyFailure) {
TestDelegate delegate;
auto request =
default_context().CreateRequest(GURL("invalid url"), DEFAULT_PRIORITY,
&delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
request->Start();
delegate.RunUntilComplete();
EXPECT_THAT(delegate.transports(), IsEmpty());
}
TEST_F(URLRequestTest, OnConnected) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
TestDelegate delegate;
auto request = default_context().CreateRequest(test_server.GetURL("/echo"),
DEFAULT_PRIORITY, &delegate,
TRAFFIC_ANNOTATION_FOR_TESTS);
request->Start();
delegate.RunUntilComplete();
TransportInfo expected_transport;
expected_transport.endpoint =
IPEndPoint(IPAddress::IPv4Localhost(), test_server.port());
expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport));
auto entries = net_log_observer_.GetEntries();
size_t start_event_index = ExpectLogContainsSomewhere(
entries, 0,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::BEGIN);
size_t end_event_index = ExpectLogContainsSomewhereAfter(
entries, start_event_index,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::END);
EXPECT_FALSE(LogContainsEntryWithTypeAfter(
entries, end_event_index + 1,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED));
ASSERT_LT(end_event_index, entries.size());
EXPECT_FALSE(GetOptionalNetErrorCodeFromParams(entries[end_event_index]));
}
TEST_F(URLRequestTest, OnConnectedRedirect) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
TestDelegate delegate;
GURL url = test_server.GetURL("/server-redirect?" +
test_server.GetURL("/echo").spec());
auto request = default_context().CreateRequest(
url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
request->Start();
delegate.RunUntilRedirect();
TransportInfo expected_transport;
expected_transport.endpoint =
IPEndPoint(IPAddress::IPv4Localhost(), test_server.port());
expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport));
request->FollowDeferredRedirect({},
{});
delegate.RunUntilComplete();
EXPECT_THAT(delegate.transports(),
ElementsAre(expected_transport, expected_transport));
}
TEST_F(URLRequestTest, OnConnectedError) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
TestDelegate delegate;
delegate.set_on_connected_result(ERR_NOT_IMPLEMENTED);
auto request = default_context().CreateRequest(test_server.GetURL("/echo"),
DEFAULT_PRIORITY, &delegate,
TRAFFIC_ANNOTATION_FOR_TESTS);
request->Start();
delegate.RunUntilComplete();
TransportInfo expected_transport;
expected_transport.endpoint =
IPEndPoint(IPAddress::IPv4Localhost(), test_server.port());
expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport));
EXPECT_TRUE(delegate.request_failed());
EXPECT_THAT(delegate.request_status(), IsError(ERR_NOT_IMPLEMENTED));
auto entries = net_log_observer_.GetEntries();
size_t start_event_index = ExpectLogContainsSomewhere(
entries, 0,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::BEGIN);
size_t end_event_index = ExpectLogContainsSomewhereAfter(
entries, start_event_index,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::END);
EXPECT_FALSE(LogContainsEntryWithTypeAfter(
entries, end_event_index + 1,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED));
ASSERT_LT(end_event_index, entries.size());
EXPECT_EQ(ERR_NOT_IMPLEMENTED,
GetOptionalNetErrorCodeFromParams(entries[end_event_index]));
}
TEST_F(URLRequestTest, OnConnectedAsync) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
TestDelegate d;
d.set_on_connected_run_callback(true);
d.set_on_connected_result(OK);
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/defaultresponse"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
auto entries = net_log_observer_.GetEntries();
size_t start_event_index = ExpectLogContainsSomewhere(
entries, 0,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::BEGIN);
size_t end_event_index = ExpectLogContainsSomewhereAfter(
entries, start_event_index,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::END);
EXPECT_FALSE(LogContainsEntryWithTypeAfter(
entries, end_event_index + 1,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED));
ASSERT_LT(end_event_index, entries.size());
EXPECT_FALSE(GetOptionalNetErrorCodeFromParams(entries[end_event_index]));
}
TEST_F(URLRequestTest, OnConnectedAsyncError) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
TestDelegate d;
d.set_on_connected_run_callback(true);
d.set_on_connected_result(ERR_NOT_IMPLEMENTED);
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/defaultresponse"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsError(ERR_NOT_IMPLEMENTED));
auto entries = net_log_observer_.GetEntries();
size_t start_event_index = ExpectLogContainsSomewhere(
entries, 0,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::BEGIN);
size_t end_event_index = ExpectLogContainsSomewhereAfter(
entries, start_event_index,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::END);
EXPECT_FALSE(LogContainsEntryWithTypeAfter(
entries, end_event_index + 1,
NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED));
ASSERT_LT(end_event_index, entries.size());
EXPECT_EQ(ERR_NOT_IMPLEMENTED,
GetOptionalNetErrorCodeFromParams(entries[end_event_index]));
}
TEST_F(URLRequestTest, DelayedCookieCallback) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCookieStore(std::make_unique<DelayedCookieMonster>());
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto context = context_builder->Build();
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
*context, test_server.GetURL("/set-cookie?CookieToNotSend=1"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
EXPECT_EQ(1, network_delegate.set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
*context, test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
std::string::npos);
EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
TEST_F(URLRequestTest, DelayedCookieCallbackAsync) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
GURL::Replacements replace_scheme;
replace_scheme.SetSchemeStr("https");
GURL url = test_server.base_url().ReplaceComponents(replace_scheme);
auto cookie1 = CanonicalCookie::CreateForTesting(
url, "AlreadySetCookie=1;Secure", base::Time::Now());
auto delayed_cm = std::make_unique<DelayedCookieMonster>();
delayed_cm->SetCanonicalCookieAsync(std::move(cookie1), url,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
auto cookie2 = CanonicalCookie::CreateForTesting(
url, "AlreadySetCookie=1;Secure", base::Time::Now());
auto cm = std::make_unique<CookieMonster>(nullptr, nullptr);
cm->SetCanonicalCookieAsync(std::move(cookie2), url,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
auto async_context_builder = CreateTestURLRequestContextBuilder();
async_context_builder->SetCookieStore(std::move(delayed_cm));
auto& async_filter_network_delegate =
*async_context_builder->set_network_delegate(
std::make_unique<FilteringTestNetworkDelegate>());
auto async_context = async_context_builder->Build();
async_filter_network_delegate.SetCookieFilter("CookieBlockedOnCanGetCookie");
TestDelegate async_delegate;
auto sync_context_builder = CreateTestURLRequestContextBuilder();
sync_context_builder->SetCookieStore(std::move(cm));
auto& sync_filter_network_delegate =
*sync_context_builder->set_network_delegate(
std::make_unique<FilteringTestNetworkDelegate>());
auto sync_context = sync_context_builder->Build();
sync_filter_network_delegate.SetCookieFilter("CookieBlockedOnCanGetCookie");
TestDelegate sync_delegate;
std::vector<std::string> cookie_lines(
{
"CookieNotSet=1;Secure",
"CookieBlockedOnCanGetCookie=1",
"AlreadySetCookie=1",
"CookieSet=1"});
for (auto first_cookie_line : cookie_lines) {
for (auto second_cookie_line : cookie_lines) {
std::unique_ptr<URLRequest> request = CreateFirstPartyRequest(
*async_context,
test_server.GetURL("/set-cookie?" + first_cookie_line + "&" +
second_cookie_line),
&async_delegate);
request->Start();
async_delegate.RunUntilComplete();
EXPECT_THAT(async_delegate.request_status(), IsOk());
request = CreateFirstPartyRequest(
*sync_context,
test_server.GetURL("/set-cookie?" + first_cookie_line + "&" +
second_cookie_line),
&sync_delegate);
request->Start();
sync_delegate.RunUntilComplete();
EXPECT_THAT(sync_delegate.request_status(), IsOk());
int expected_set_cookie_count = 0;
int expected_blocked_cookie_count = 0;
expected_set_cookie_count += 2;
if (first_cookie_line == "CookieBlockedOnCanGetCookie=1")
++expected_blocked_cookie_count;
if (second_cookie_line == "CookieBlockedOnCanGetCookie=1")
++expected_blocked_cookie_count;
EXPECT_EQ(expected_set_cookie_count,
async_filter_network_delegate.set_cookie_called_count());
EXPECT_EQ(expected_blocked_cookie_count,
async_filter_network_delegate.blocked_set_cookie_count());
EXPECT_EQ(expected_set_cookie_count,
sync_filter_network_delegate.set_cookie_called_count());
EXPECT_EQ(expected_blocked_cookie_count,
sync_filter_network_delegate.blocked_set_cookie_count());
async_filter_network_delegate.ResetSetCookieCalledCount();
async_filter_network_delegate.ResetBlockedSetCookieCount();
sync_filter_network_delegate.ResetSetCookieCalledCount();
sync_filter_network_delegate.ResetBlockedSetCookieCount();
}
}
}
TEST_F(URLRequestTest, DoNotSendCookies) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/set-cookie?CookieToNotSend=1"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->set_disallow_credentials();
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
}
TEST_F(URLRequestTest, DoNotSaveCookies) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
EXPECT_EQ(1, default_network_delegate().set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
&d);
req->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
EXPECT_EQ(1, default_network_delegate().set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("CookieToNotSave=1") ==
std::string::npos);
EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
EXPECT_EQ(1, default_network_delegate().set_cookie_count());
}
}
TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/set-cookie?CookieToNotSend=1"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
auto entries = net_log_observer_.GetEntries();
for (const auto& entry : entries) {
EXPECT_NE(entry.type,
NetLogEventType::COOKIE_GET_BLOCKED_BY_NETWORK_DELEGATE);
}
}
{
TestDelegate d;
default_network_delegate().set_cookie_options(
TestNetworkDelegate::NO_GET_COOKIES);
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
std::string::npos);
EXPECT_EQ(1, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
auto entries = net_log_observer_.GetEntries();
ExpectLogContainsSomewhereAfter(
entries, 0, NetLogEventType::COOKIE_GET_BLOCKED_BY_NETWORK_DELEGATE,
NetLogEventPhase::NONE);
}
}
TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
auto entries = net_log_observer_.GetEntries();
for (const auto& entry : entries) {
EXPECT_NE(entry.type,
NetLogEventType::COOKIE_SET_BLOCKED_BY_NETWORK_DELEGATE);
}
}
{
TestDelegate d;
default_network_delegate().set_cookie_options(
TestNetworkDelegate::NO_SET_COOKIE);
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(2, default_network_delegate().blocked_set_cookie_count());
auto entries = net_log_observer_.GetEntries();
ExpectLogContainsSomewhereAfter(
entries, 0, NetLogEventType::COOKIE_SET_BLOCKED_BY_NETWORK_DELEGATE,
NetLogEventPhase::NONE);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("CookieToNotSave=1") ==
std::string::npos);
EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(2, default_network_delegate().blocked_set_cookie_count());
}
}
TEST_F(URLRequestTest, DoNotSaveEmptyCookies) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/set-cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
EXPECT_EQ(0, default_network_delegate().set_cookie_count());
}
}
TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/set-cookie?CookieToNotSend=1"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
default_network_delegate().set_cookie_options(
TestNetworkDelegate::NO_GET_COOKIES);
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
std::string::npos);
EXPECT_EQ(1, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
}
TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
default_network_delegate().set_cookie_options(
TestNetworkDelegate::NO_SET_COOKIE);
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(2, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("CookieToNotSave=1") ==
std::string::npos);
EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(2, default_network_delegate().blocked_set_cookie_count());
}
}
class URLRequestSameSiteCookiesTest
: public URLRequestTest,
public ::testing::WithParamInterface<bool> {
public:
URLRequestSameSiteCookiesTest() {
if (DoesCookieSameSiteConsiderRedirectChain()) {
feature_list_.InitAndEnableFeature(
features::kCookieSameSiteConsidersRedirectChain);
}
}
bool DoesCookieSameSiteConsiderRedirectChain() { return GetParam(); }
private:
base::test::ScopedFeatureList feature_list_;
};
TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
const std::string kHost = "example.test";
const std::string kSubHost = "subdomain.example.test";
const std::string kCrossHost = "cross-origin.test";
const url::Origin kOrigin =
url::Origin::Create(test_server.GetURL(kHost, "/"));
const url::Origin kSubOrigin =
url::Origin::Create(test_server.GetURL(kSubHost, "/"));
const url::Origin kCrossOrigin =
url::Origin::Create(test_server.GetURL(kCrossHost, "/"));
const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
const SiteForCookies kCrossSiteForCookies =
SiteForCookies::FromOrigin(kCrossOrigin);
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
test_server.GetURL(kHost,
"/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
"LaxSameSiteCookie=1;SameSite=Lax"),
&d);
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
EXPECT_EQ(2, default_network_delegate().set_cookie_count());
}
for (IsolationInfo::RequestType request_type :
{IsolationInfo::RequestType::kMainFrame,
IsolationInfo::RequestType::kSubFrame,
IsolationInfo::RequestType::kOther}) {
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(request_type, kOrigin, kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(kSiteForCookies);
req->Start();
d.RunUntilComplete();
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(
SiteForCookies::FromUrl(test_server.GetURL(kSubHost, "/")));
req->set_initiator(kSubOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(kCrossSiteForCookies);
req->set_initiator(kCrossOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kCrossOrigin);
req->set_method("GET");
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kCrossOrigin);
req->set_method("GET");
req->set_force_main_frame_for_same_site_cookies(true);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kCrossOrigin);
req->set_method("POST");
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin,
kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kCrossOrigin);
req->set_method("GET");
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
ASSERT_EQ(2u, req->maybe_sent_cookies().size());
CookieInclusionStatus expected_strict_status =
CookieInclusionStatus::MakeFromReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::EXCLUDE_SAMESITE_STRICT});
CookieInclusionStatus expected_lax_status =
CookieInclusionStatus::MakeFromReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::EXCLUDE_SAMESITE_LAX});
EXPECT_EQ(expected_strict_status,
req->maybe_sent_cookies()[0].access_result.status);
EXPECT_EQ(expected_lax_status,
req->maybe_sent_cookies()[1].access_result.status);
}
}
TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies_Redirect) {
EmbeddedTestServer http_server;
RegisterDefaultHandlers(&http_server);
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(http_server.Start());
ASSERT_TRUE(https_server.Start());
const std::string kHost = "foo.a.test";
const std::string kSameSiteHost = "bar.a.test";
const std::string kCrossSiteHost = "b.test";
const url::Origin kOrigin =
url::Origin::Create(https_server.GetURL(kHost, "/"));
const url::Origin kHttpOrigin =
url::Origin::Create(http_server.GetURL(kHost, "/"));
const url::Origin kSameSiteOrigin =
url::Origin::Create(https_server.GetURL(kSameSiteHost, "/"));
const url::Origin kCrossSiteOrigin =
url::Origin::Create(https_server.GetURL(kCrossSiteHost, "/"));
const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
const SiteForCookies kHttpSiteForCookies =
SiteForCookies::FromOrigin(kHttpOrigin);
const SiteForCookies kCrossSiteForCookies =
SiteForCookies::FromOrigin(kCrossSiteOrigin);
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
https_server.GetURL(
kHost,
"/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
"LaxSameSiteCookie=1;SameSite=Lax"),
&d);
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
ASSERT_EQ(2u, GetAllCookies(&default_context()).size());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
https_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1u, req->url_chain().size());
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
}
{
TestDelegate d;
GURL url = https_server.GetURL(
kHost, "/server-redirect?" +
https_server.GetURL(kHost, "/echoheader?Cookie").spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, kSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(2u, req->url_chain().size());
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
}
{
TestDelegate d;
GURL url = https_server.GetURL(
kSameSiteHost,
"/server-redirect?" +
https_server.GetURL(kHost, "/echoheader?Cookie").spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kSameSiteOrigin,
kSameSiteOrigin, kSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(2u, req->url_chain().size());
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
}
{
TestDelegate d;
GURL url = http_server.GetURL(
kHost, "/server-redirect?" +
https_server.GetURL(kHost, "/echoheader?Cookie").spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame,
kHttpOrigin, kHttpOrigin, kHttpSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kHttpSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(2u, req->url_chain().size());
EXPECT_EQ(
DoesCookieSameSiteConsiderRedirectChain(),
std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
}
{
TestDelegate d;
GURL url = https_server.GetURL(
kCrossSiteHost,
"/server-redirect?" +
https_server.GetURL(kHost, "/echoheader?Cookie").spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kCrossSiteOrigin,
kCrossSiteOrigin, kCrossSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kCrossSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(2u, req->url_chain().size());
EXPECT_EQ(
DoesCookieSameSiteConsiderRedirectChain(),
std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
}
{
TestDelegate d;
GURL middle_url = https_server.GetURL(
kCrossSiteHost,
"/server-redirect?" +
https_server.GetURL(kHost, "/echoheader?Cookie").spec());
GURL url =
https_server.GetURL(kHost, "/server-redirect?" + middle_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, kSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(3u, req->url_chain().size());
EXPECT_EQ(
DoesCookieSameSiteConsiderRedirectChain(),
std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
}
{
TestDelegate d;
GURL url = https_server.GetURL(
kCrossSiteHost,
"/server-redirect?" +
https_server.GetURL(kHost, "/echoheader?Cookie").spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(2u, req->url_chain().size());
EXPECT_EQ(
DoesCookieSameSiteConsiderRedirectChain(),
std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_EQ(
DoesCookieSameSiteConsiderRedirectChain(),
std::string::npos == d.data_received().find("LaxSameSiteCookie=1"));
}
{
TestDelegate d;
GURL middle_url = https_server.GetURL(
kCrossSiteHost,
"/server-redirect?" +
https_server.GetURL(kHost, "/echoheader?Cookie").spec());
GURL url =
https_server.GetURL(kHost, "/server-redirect?" + middle_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(3u, req->url_chain().size());
EXPECT_EQ(
DoesCookieSameSiteConsiderRedirectChain(),
std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_EQ(
DoesCookieSameSiteConsiderRedirectChain(),
std::string::npos == d.data_received().find("LaxSameSiteCookie=1"));
}
}
TEST_P(URLRequestSameSiteCookiesTest, SettingSameSiteCookies) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
const std::string kHost = "example.test";
const std::string kSubHost = "subdomain.example.test";
const std::string kCrossHost = "cross-origin.test";
const url::Origin kOrigin =
url::Origin::Create(test_server.GetURL(kHost, "/"));
const url::Origin kSubOrigin =
url::Origin::Create(test_server.GetURL(kSubHost, "/"));
const url::Origin kCrossOrigin =
url::Origin::Create(test_server.GetURL(kCrossHost, "/"));
const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
const SiteForCookies kCrossSiteForCookies =
SiteForCookies::FromOrigin(kCrossOrigin);
int expected_cookies = 0;
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost,
"/set-cookie?Strict1=1;SameSite=Strict&"
"Lax1=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
expected_cookies += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_cookies, default_network_delegate().set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost,
"/set-cookie?Strict2=1;SameSite=Strict&"
"Lax2=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kCrossOrigin);
expected_cookies += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_cookies, default_network_delegate().set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost,
"/set-cookie?Strict3=1;SameSite=Strict&"
"Lax3=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame,
kSubOrigin, kSubOrigin, kSiteForCookies));
req->set_site_for_cookies(
SiteForCookies::FromUrl(test_server.GetURL(kSubHost, "/")));
req->set_initiator(kCrossOrigin);
expected_cookies += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_cookies, default_network_delegate().set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost,
"/set-cookie?Strict4=1;SameSite=Strict&"
"Lax4=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(
SiteForCookies::FromUrl(test_server.GetURL(kSubHost, "/")));
expected_cookies += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_cookies, default_network_delegate().set_cookie_count());
}
int expected_network_delegate_set_cookie_count;
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost,
"/set-cookie?Strict5=1;SameSite=Strict&"
"Lax5=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(kCrossSiteForCookies);
req->set_initiator(kCrossOrigin);
expected_cookies += 0;
expected_network_delegate_set_cookie_count = expected_cookies + 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_network_delegate_set_cookie_count,
default_network_delegate().set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost,
"/set-cookie?Strict6=1;SameSite=Strict&"
"Lax6=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin,
kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kCrossOrigin);
expected_cookies += 0;
expected_network_delegate_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_network_delegate_set_cookie_count,
default_network_delegate().set_cookie_count());
ASSERT_EQ(2u, req->maybe_stored_cookies().size());
CookieInclusionStatus expected_strict_status =
CookieInclusionStatus::MakeFromReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::EXCLUDE_SAMESITE_STRICT},
{} );
CookieInclusionStatus expected_lax_status =
CookieInclusionStatus::MakeFromReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::EXCLUDE_SAMESITE_LAX},
{} );
EXPECT_EQ(expected_strict_status,
req->maybe_stored_cookies()[0].access_result.status);
EXPECT_EQ(expected_lax_status,
req->maybe_stored_cookies()[1].access_result.status);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL(kHost,
"/set-cookie?Strict7=1;SameSite=Strict&"
"Lax7=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kCrossOrigin);
req->set_force_main_frame_for_same_site_cookies(true);
expected_cookies += 2;
expected_network_delegate_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_network_delegate_set_cookie_count,
default_network_delegate().set_cookie_count());
}
}
TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookiesSpecialScheme) {
url::ScopedSchemeRegistryForTests scoped_registry;
url::AddStandardScheme("chrome", url::SchemeType::SCHEME_WITH_HOST);
EmbeddedTestServer https_test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&https_test_server);
ASSERT_TRUE(https_test_server.Start());
EmbeddedTestServer http_test_server(EmbeddedTestServer::TYPE_HTTP);
RegisterDefaultHandlers(&http_test_server);
ASSERT_TRUE(http_test_server.Start());
ASSERT_NE(https_test_server.port(), http_test_server.port());
ASSERT_EQ(https_test_server.host_port_pair().host(),
http_test_server.host_port_pair().host());
auto cad = std::make_unique<TestCookieAccessDelegate>();
cad->SetIgnoreSameSiteRestrictionsScheme("chrome", true);
auto cm = std::make_unique<CookieMonster>(nullptr, nullptr);
cm->SetCookieAccessDelegate(std::move(cad));
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCookieStore(std::move(cm));
auto context = context_builder->Build();
{
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server.GetURL(
"/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
"LaxSameSiteCookie=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(
SiteForCookies::FromUrl(GURL("chrome://whatever/")));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0u, GetAllCookies(context.get()).size());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
https_test_server.GetURL(
"/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
"LaxSameSiteCookie=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(
SiteForCookies::FromUrl(GURL("chrome://whatever/")));
req->Start();
d.RunUntilComplete();
CookieList cookies = GetAllCookies(context.get());
EXPECT_EQ(2u, cookies.size());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
https_test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(
SiteForCookies::FromUrl(GURL("chrome://whatever/")));
req->Start();
d.RunUntilComplete();
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(
SiteForCookies::FromUrl(GURL("chrome://whatever/")));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie"));
EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie"));
}
}
TEST_P(URLRequestSameSiteCookiesTest, SettingSameSiteCookies_Redirect) {
EmbeddedTestServer http_server;
RegisterDefaultHandlers(&http_server);
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(http_server.Start());
ASSERT_TRUE(https_server.Start());
auto& network_delegate = default_network_delegate();
const std::string kHost = "foo.a.test";
const std::string kSameSiteHost = "bar.a.test";
const std::string kCrossSiteHost = "b.test";
const url::Origin kOrigin =
url::Origin::Create(https_server.GetURL(kHost, "/"));
const url::Origin kHttpOrigin =
url::Origin::Create(http_server.GetURL(kHost, "/"));
const url::Origin kSameSiteOrigin =
url::Origin::Create(https_server.GetURL(kSameSiteHost, "/"));
const url::Origin kCrossSiteOrigin =
url::Origin::Create(https_server.GetURL(kCrossSiteHost, "/"));
const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
const SiteForCookies kHttpSiteForCookies =
SiteForCookies::FromOrigin(kHttpOrigin);
const SiteForCookies kCrossSiteForCookies =
SiteForCookies::FromOrigin(kCrossSiteOrigin);
int expected_cookies = 0;
int expected_set_cookie_count = 0;
{
TestDelegate d;
GURL set_cookie_url = https_server.GetURL(
kHost, "/set-cookie?Strict1=1;SameSite=Strict&Lax1=1;SameSite=Lax");
GURL url =
https_server.GetURL(kHost, "/server-redirect?" + set_cookie_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, kSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
expected_cookies += 2;
expected_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
}
{
TestDelegate d;
GURL set_cookie_url = https_server.GetURL(
kHost, "/set-cookie?Strict2=1;SameSite=Strict&Lax2=1;SameSite=Lax");
GURL url = https_server.GetURL(kSameSiteHost,
"/server-redirect?" + set_cookie_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kSameSiteOrigin,
kSameSiteOrigin, kSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kSameSiteOrigin);
expected_cookies += 2;
expected_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
}
{
TestDelegate d;
GURL set_cookie_url = https_server.GetURL(
kHost, "/set-cookie?Strict3=1;SameSite=Strict&Lax3=1;SameSite=Lax");
GURL url = https_server.GetURL(kCrossSiteHost,
"/server-redirect?" + set_cookie_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kCrossSiteOrigin,
kCrossSiteOrigin, kCrossSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kCrossSiteForCookies);
req->set_initiator(kCrossSiteOrigin);
expected_cookies += 2;
expected_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
}
{
TestDelegate d;
GURL set_cookie_url = https_server.GetURL(
kHost, "/set-cookie?Strict4=1;SameSite=Strict&Lax4=1;SameSite=Lax");
GURL url =
https_server.GetURL(kHost, "/server-redirect?" + set_cookie_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
expected_cookies += 2;
expected_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
}
{
TestDelegate d;
GURL set_cookie_url = https_server.GetURL(
kHost, "/set-cookie?Strict5=1;SameSite=Strict&Lax5=1;SameSite=Lax");
GURL url = https_server.GetURL(kSameSiteHost,
"/server-redirect?" + set_cookie_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kSameSiteOrigin, kSameSiteOrigin,
kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kSameSiteOrigin);
expected_cookies += 2;
expected_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
}
{
TestDelegate d;
GURL set_cookie_url = https_server.GetURL(
kHost, "/set-cookie?Strict6=1;SameSite=Strict&Lax6=1;SameSite=Lax");
GURL url = https_server.GetURL(kCrossSiteHost,
"/server-redirect?" + set_cookie_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
expected_cookies += DoesCookieSameSiteConsiderRedirectChain() ? 0 : 2;
expected_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
}
{
TestDelegate d;
GURL set_cookie_url = https_server.GetURL(
kHost, "/set-cookie?Strict7=1;SameSite=Strict&Lax7=1;SameSite=Lax");
GURL middle_url = https_server.GetURL(
kCrossSiteHost, "/server-redirect?" + set_cookie_url.spec());
GURL url =
https_server.GetURL(kHost, "/server-redirect?" + middle_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies));
req->set_site_for_cookies(kSiteForCookies);
req->set_initiator(kOrigin);
expected_cookies += DoesCookieSameSiteConsiderRedirectChain() ? 0 : 2;
expected_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
}
{
TestDelegate d;
GURL set_cookie_url = https_server.GetURL(
kHost, "/set-cookie?Strict9=1;SameSite=Strict&Lax9=1;SameSite=Lax");
GURL url =
http_server.GetURL(kHost, "/server-redirect?" + set_cookie_url.spec());
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kOther, kHttpOrigin,
kHttpOrigin, kHttpSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kHttpSiteForCookies);
req->set_initiator(kOrigin);
expected_cookies += DoesCookieSameSiteConsiderRedirectChain() ? 0 : 2;
expected_set_cookie_count += 2;
req->Start();
d.RunUntilComplete();
EXPECT_EQ(expected_cookies,
static_cast<int>(GetAllCookies(&default_context()).size()));
EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
}
}
INSTANTIATE_TEST_SUITE_P(,
URLRequestSameSiteCookiesTest,
::testing::Bool());
TEST_F(URLRequestTest, PartitionedCookiesRedirect) {
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
const std::string kHost = "a.test";
const std::string kCrossSiteHost = "b.test";
const GURL create_cookie_url = https_server.GetURL(kHost, "/");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCookieStore(
std::make_unique<CookieMonster>(nullptr, nullptr));
auto context = context_builder->Build();
auto& cm = *static_cast<CookieMonster*>(context->cookie_store());
{
auto same_site_partitioned_cookie = CanonicalCookie::CreateForTesting(
create_cookie_url, "samesite_partitioned=1;Secure;Partitioned",
base::Time::Now(), std::nullopt,
CookiePartitionKey::FromURLForTesting(
create_cookie_url,
CookiePartitionKey::AncestorChainBit::kSameSite));
ASSERT_TRUE(same_site_partitioned_cookie);
ASSERT_TRUE(same_site_partitioned_cookie->IsPartitioned());
base::test::TestFuture<CookieAccessResult> future;
cm.SetCanonicalCookieAsync(
std::move(same_site_partitioned_cookie), create_cookie_url,
CookieOptions::MakeAllInclusive(), future.GetCallback());
ASSERT_TRUE(future.Get().status.IsInclude());
}
{
auto cross_site_partitioned_cookie = CanonicalCookie::CreateForTesting(
create_cookie_url, "xsite_partitioned=1;Secure;Partitioned",
base::Time::Now(), std::nullopt,
CookiePartitionKey::FromURLForTesting(
https_server.GetURL(kCrossSiteHost, "/")));
ASSERT_TRUE(cross_site_partitioned_cookie);
ASSERT_TRUE(cross_site_partitioned_cookie->IsPartitioned());
base::test::TestFuture<CookieAccessResult> future;
cm.SetCanonicalCookieAsync(
std::move(cross_site_partitioned_cookie), create_cookie_url,
CookieOptions::MakeAllInclusive(), future.GetCallback());
ASSERT_TRUE(future.Get().status.IsInclude());
}
const auto kCrossSiteOrigin =
url::Origin::Create(https_server.GetURL(kCrossSiteHost, "/"));
const auto kCrossSiteSiteForCookies =
SiteForCookies::FromOrigin(kCrossSiteOrigin);
TestDelegate d;
GURL url = https_server.GetURL(
kCrossSiteHost,
"/server-redirect?" +
https_server.GetURL(kHost, "/echoheader?Cookie").spec());
std::unique_ptr<URLRequest> req = context->CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS);
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, kCrossSiteOrigin,
kCrossSiteOrigin, kCrossSiteSiteForCookies));
req->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
req->set_site_for_cookies(kCrossSiteSiteForCookies);
req->set_initiator(kCrossSiteOrigin);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(2u, req->url_chain().size());
EXPECT_NE(std::string::npos,
d.data_received().find("samesite_partitioned=1"));
EXPECT_EQ(std::string::npos, d.data_received().find("xsite_partitioned=1"));
}
TEST_F(URLRequestTest, SecureCookiePrefixOnNonsecureOrigin) {
EmbeddedTestServer http_server;
RegisterDefaultHandlers(&http_server);
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(http_server.Start());
ASSERT_TRUE(https_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
http_server.GetURL("a.test",
"/set-cookie?__Secure-nonsecure-origin=1;Secure&"
"cookienotsecure=1"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), https_server.GetURL("a.test", "/echoheader?Cookie"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(d.data_received().find("__Secure-nonsecure-origin=1"),
std::string::npos);
EXPECT_NE(d.data_received().find("cookienotsecure=1"), std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
}
TEST_F(URLRequestTest, SecureCookiePrefixNonsecure) {
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), https_server.GetURL("/set-cookie?__Secure-foo=1"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().set_cookie_count());
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), https_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(d.data_received().find("__Secure-foo=1"), std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
}
TEST_F(URLRequestTest, SecureCookiePrefixSecure) {
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
https_server.GetURL("/set-cookie?__Secure-bar=1;Secure"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), https_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_NE(d.data_received().find("__Secure-bar=1"), std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
}
TEST_F(URLRequestTest, StrictSecureCookiesOnNonsecureOrigin) {
EmbeddedTestServer http_server;
RegisterDefaultHandlers(&http_server);
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(http_server.Start());
ASSERT_TRUE(https_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(),
http_server.GetURL("a.test",
"/set-cookie?nonsecure-origin=1;Secure&"
"cookienotsecure=1"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
default_context(), https_server.GetURL("a.test", "/echoheader?Cookie"),
&d);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(d.data_received().find("nonsecure-origin=1"), std::string::npos);
EXPECT_NE(d.data_received().find("cookienotsecure=1"), std::string::npos);
EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
}
}
class FixedDateNetworkDelegate : public TestNetworkDelegate {
public:
explicit FixedDateNetworkDelegate(std::string_view fixed_date)
: fixed_date_(fixed_date) {}
FixedDateNetworkDelegate(const FixedDateNetworkDelegate&) = delete;
FixedDateNetworkDelegate& operator=(const FixedDateNetworkDelegate&) = delete;
~FixedDateNetworkDelegate() override = default;
void set_fixed_date(std::string_view fixed_date) {
fixed_date_ = static_cast<std::string>(fixed_date);
}
int OnHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
const HttpResponseHeaders* original_response_headers,
scoped_refptr<HttpResponseHeaders>* override_response_headers,
const IPEndPoint& endpoint,
std::optional<GURL>* preserve_fragment_on_redirect_url,
const std::optional<net::SSLInfo>& ssl_info) override;
private:
std::string fixed_date_;
};
int FixedDateNetworkDelegate::OnHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
const HttpResponseHeaders* original_response_headers,
scoped_refptr<HttpResponseHeaders>* override_response_headers,
const IPEndPoint& endpoint,
std::optional<GURL>* preserve_fragment_on_redirect_url,
const std::optional<net::SSLInfo>& ssl_info) {
*override_response_headers = base::MakeRefCounted<HttpResponseHeaders>(
original_response_headers->raw_headers());
(*override_response_headers)->SetHeader("Date", fixed_date_);
return TestNetworkDelegate::OnHeadersReceived(
request, std::move(callback), original_response_headers,
override_response_headers, endpoint, preserve_fragment_on_redirect_url,
ssl_info);
}
TEST_F(URLRequestTest, AcceptClockSkewCookieWithWrongDateTimezone) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<FixedDateNetworkDelegate>("04-Jan-2004 04:09:25 UTC"));
auto context = context_builder->Build();
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
*context,
test_server.GetURL(
"/set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"),
&d);
req->Start();
d.RunUntilComplete();
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
*context, test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("StillGood=1") == std::string::npos);
}
{
TestDelegate d;
network_delegate.set_fixed_date("18-Apr-1977 22:49:13 UTC");
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
*context,
test_server.GetURL(
"/set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"),
&d);
req->Start();
d.RunUntilComplete();
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
*context, test_server.GetURL("/echoheader?Cookie"), &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("StillGood=1") != std::string::npos);
}
}
TEST_F(URLRequestTest, DoNotOverrideReferrer) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://foo.com/");
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kReferer, "http://bar.com/");
req->SetExtraRequestHeaders(headers);
req->Start();
d.RunUntilComplete();
EXPECT_EQ("http://foo.com/", d.data_received());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_server.GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kReferer, "http://bar.com/");
req->SetExtraRequestHeaders(headers);
req->SetLoadFlags(LOAD_VALIDATE_CACHE);
req->Start();
d.RunUntilComplete();
EXPECT_EQ("None", d.data_received());
}
}
class URLRequestTestHTTP : public URLRequestTest {
public:
const url::Origin origin1_;
const url::Origin origin2_;
const IsolationInfo isolation_info1_;
const IsolationInfo isolation_info2_;
URLRequestTestHTTP()
: origin1_(url::Origin::Create(GURL("https://foo.test/"))),
origin2_(url::Origin::Create(GURL("https://bar.test/"))),
isolation_info1_(IsolationInfo::CreateForInternalRequest(origin1_)),
isolation_info2_(IsolationInfo::CreateForInternalRequest(origin2_)),
test_server_(base::FilePath(kTestFilePath)) {
}
protected:
class NET_EXPORT UnsafeRedirectProtocolHandler
: public URLRequestJobFactory::ProtocolHandler {
public:
UnsafeRedirectProtocolHandler() = default;
UnsafeRedirectProtocolHandler(const UnsafeRedirectProtocolHandler&) =
delete;
UnsafeRedirectProtocolHandler& operator=(
const UnsafeRedirectProtocolHandler&) = delete;
~UnsafeRedirectProtocolHandler() override = default;
std::unique_ptr<URLRequestJob> CreateJob(
URLRequest* request) const override {
NOTREACHED();
}
bool IsSafeRedirectTarget(const GURL& location) const override {
return false;
}
};
void SetUpContextBuilder(URLRequestContextBuilder& builder) override {
builder.SetProtocolHandler(
"unsafe", std::make_unique<UnsafeRedirectProtocolHandler>());
}
void HTTPRedirectMethodTest(const GURL& redirect_url,
const std::string& request_method,
const std::string& redirect_method,
bool include_data) {
static const char kData[] = "hello world";
TestDelegate d;
std::unique_ptr<URLRequest> req =
CreateFirstPartyRequest(default_context(), redirect_url, &d);
req->set_method(request_method);
if (include_data) {
req->set_upload(
CreateSimpleUploadData(base::byte_span_from_cstring(kData)));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kContentLength,
base::NumberToString(std::size(kData) - 1));
headers.SetHeader(HttpRequestHeaders::kContentType, "text/plain");
req->SetExtraRequestHeaders(headers);
}
req->Start();
d.RunUntilComplete();
EXPECT_EQ(redirect_method, req->method());
EXPECT_EQ(OK, d.request_status());
if (include_data) {
if (request_method == redirect_method) {
EXPECT_TRUE(req->extra_request_headers().HasHeader(
HttpRequestHeaders::kContentLength));
EXPECT_TRUE(req->extra_request_headers().HasHeader(
HttpRequestHeaders::kContentType));
EXPECT_EQ(kData, d.data_received());
} else {
EXPECT_FALSE(req->extra_request_headers().HasHeader(
HttpRequestHeaders::kContentLength));
EXPECT_FALSE(req->extra_request_headers().HasHeader(
HttpRequestHeaders::kContentType));
EXPECT_NE(kData, d.data_received());
}
}
if (HasFailure())
LOG(WARNING) << "Request method was: " << request_method;
}
void HTTPRedirectOriginHeaderTest(const GURL& redirect_url,
const std::string& request_method,
const std::string& redirect_method,
const std::string& expected_origin_value) {
TestDelegate d;
std::unique_ptr<URLRequest> req =
CreateFirstPartyRequest(default_context(), redirect_url, &d);
req->set_method(request_method);
req->SetExtraRequestHeaderByName(
HttpRequestHeaders::kOrigin,
redirect_url.DeprecatedGetOriginAsURL().spec(), false);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(redirect_method, req->method());
if (expected_origin_value.empty()) {
EXPECT_FALSE(
req->extra_request_headers().HasHeader(HttpRequestHeaders::kOrigin));
} else {
EXPECT_EQ(expected_origin_value, req->extra_request_headers().GetHeader(
HttpRequestHeaders::kOrigin));
}
}
void HTTPUploadDataOperationTest(const std::string& method) {
const int kMsgSize = 20000;
const int kIterations = 50;
auto upload_bytes = base::HeapArray<char>::Uninit(kMsgSize);
char marker = 'a';
const size_t kStrideSize = 10;
for (size_t idx = 0; idx < kMsgSize / kStrideSize; idx++) {
auto span =
upload_bytes.as_span().subspan(idx * kStrideSize, kStrideSize);
std::ranges::fill(span, '-');
if (idx % 100 == 0) {
span[kStrideSize - 1] = marker;
if (++marker > 'z')
marker = 'a';
}
}
for (int i = 0; i < kIterations; ++i) {
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server_.GetURL("/echo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_method(method);
r->set_upload(
CreateSimpleUploadData(base::as_bytes(upload_bytes.as_span())));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
ASSERT_EQ(1, d.response_started_count())
<< "request failed. Error: " << d.request_status();
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(base::as_string_view(upload_bytes.as_span()),
d.data_received());
}
}
HttpTestServer* http_test_server() { return &test_server_; }
private:
base::test::ScopedFeatureList feature_list_;
HttpTestServer test_server_;
};
namespace {
std::unique_ptr<test_server::HttpResponse> HandleRedirectConnect(
const test_server::HttpRequest& request) {
if (request.headers.find("Host") == request.headers.end() ||
request.headers.at("Host") != "www.redirect.com" ||
request.method != test_server::METHOD_CONNECT) {
return nullptr;
}
auto http_response = std::make_unique<test_server::BasicHttpResponse>();
http_response->set_code(HTTP_FOUND);
http_response->AddCustomHeader("Location",
"http://www.destination.com/foo.js");
return std::move(http_response);
}
}
TEST_F(URLRequestTestHTTP, ProxyTunnelRedirectTest) {
http_test_server()->RegisterRequestHandler(
base::BindRepeating(&HandleRedirectConnect));
ASSERT_TRUE(http_test_server()->Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_proxy_resolution_service(
CreateFixedProxyResolutionService(
http_test_server()->host_port_pair().ToString()));
auto context = context_builder->Build();
TestDelegate d;
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
GURL("https://www.redirect.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
http_test_server()->host_port_pair()),
r->proxy_chain());
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, d.request_status());
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(0, d.received_redirect_count());
}
}
TEST_F(URLRequestTestHTTP, NetworkDelegateTunnelConnectionFailed) {
ASSERT_TRUE(http_test_server()->Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_proxy_resolution_service(
CreateFixedProxyResolutionService(
http_test_server()->host_port_pair().ToString()));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto context = context_builder->Build();
TestDelegate d;
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
GURL("https://www.redirect.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
http_test_server()->host_port_pair()),
r->proxy_chain());
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, d.request_status());
EXPECT_EQ(0, d.received_redirect_count());
EXPECT_EQ(1, network_delegate.error_count());
EXPECT_THAT(network_delegate.last_error(),
IsError(ERR_TUNNEL_CONNECTION_FAILED));
}
}
TEST_F(URLRequestTestHTTP, NetworkDelegateBlockAsynchronously) {
static const BlockingNetworkDelegate::Stage blocking_stages[] = {
BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST,
BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS,
BlockingNetworkDelegate::ON_HEADERS_RECEIVED};
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::USER_CALLBACK));
network_delegate.set_block_on(
BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST |
BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS |
BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
for (auto stage : blocking_stages) {
network_delegate.RunUntilBlocked();
EXPECT_EQ(stage, network_delegate.stage_blocked_for_callback());
network_delegate.DoCallback(OK);
}
d.RunUntilComplete();
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_proxy_resolution_service(
CreateFixedProxyResolutionService(
http_test_server()->host_port_pair().ToString()));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::AUTO_CALLBACK));
auto context = context_builder->Build();
network_delegate.set_block_on(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST);
network_delegate.set_retval(ERR_EMPTY_RESPONSE);
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_FALSE(r->proxy_chain().IsValid());
EXPECT_EQ(ERR_EMPTY_RESPONSE, d.request_status());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
void NetworkDelegateCancelRequest(BlockingNetworkDelegate::BlockMode block_mode,
BlockingNetworkDelegate::Stage stage,
const GURL& url) {
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(block_mode));
network_delegate.set_retval(ERR_BLOCKED_BY_CLIENT);
network_delegate.set_block_on(stage);
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
if (stage == BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST ||
stage == BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS) {
EXPECT_FALSE(r->proxy_chain().IsValid());
} else if (stage == BlockingNetworkDelegate::ON_HEADERS_RECEIVED) {
EXPECT_TRUE(r->proxy_chain().is_direct());
} else {
NOTREACHED();
}
EXPECT_EQ(ERR_BLOCKED_BY_CLIENT, d.request_status());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously1) {
ASSERT_TRUE(http_test_server()->Start());
NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS,
BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST,
http_test_server()->GetURL("/"));
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously2) {
ASSERT_TRUE(http_test_server()->Start());
NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS,
BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS,
http_test_server()->GetURL("/"));
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously3) {
ASSERT_TRUE(http_test_server()->Start());
NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS,
BlockingNetworkDelegate::ON_HEADERS_RECEIVED,
http_test_server()->GetURL("/"));
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously1) {
ASSERT_TRUE(http_test_server()->Start());
NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK,
BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST,
http_test_server()->GetURL("/"));
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously2) {
ASSERT_TRUE(http_test_server()->Start());
NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK,
BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS,
http_test_server()->GetURL("/"));
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously3) {
ASSERT_TRUE(http_test_server()->Start());
NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK,
BlockingNetworkDelegate::ON_HEADERS_RECEIVED,
http_test_server()->GetURL("/"));
}
TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_proxy_resolution_service(
CreateFixedProxyResolutionService(
http_test_server()->host_port_pair().ToString()));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::AUTO_CALLBACK));
auto context = context_builder->Build();
GURL redirect_url("http://does.not.resolve.test/simple.html");
network_delegate.set_redirect_url(redirect_url);
{
GURL original_url("http://does.not.resolve.test/defaultresponse");
std::unique_ptr<URLRequest> r(context->CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilRedirect();
EXPECT_EQ(307, r->GetResponseCode());
EXPECT_EQ(307, r->response_headers()->response_code());
std::string location;
ASSERT_TRUE(
r->response_headers()->EnumerateHeader(nullptr, "Location", &location));
EXPECT_EQ(redirect_url, GURL(location));
r->FollowDeferredRedirect(std::nullopt ,
std::nullopt );
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
http_test_server()->host_port_pair()),
r->proxy_chain());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(redirect_url, r->url());
EXPECT_EQ(original_url, r->original_url());
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestSynchronously) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_proxy_resolution_service(
CreateFixedProxyResolutionService(
http_test_server()->host_port_pair().ToString()));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS));
auto context = context_builder->Build();
GURL redirect_url("http://does.not.resolve.test/simple.html");
network_delegate.set_redirect_url(redirect_url);
{
GURL original_url("http://does.not.resolve.test/defaultresponse");
std::unique_ptr<URLRequest> r(context->CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilRedirect();
EXPECT_EQ(307, r->GetResponseCode());
EXPECT_EQ(307, r->response_headers()->response_code());
std::string location;
ASSERT_TRUE(
r->response_headers()->EnumerateHeader(nullptr, "Location", &location));
EXPECT_EQ(redirect_url, GURL(location));
r->FollowDeferredRedirect(std::nullopt ,
std::nullopt );
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
http_test_server()->host_port_pair()),
r->proxy_chain());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(redirect_url, r->url());
EXPECT_EQ(original_url, r->original_url());
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestPost) {
ASSERT_TRUE(http_test_server()->Start());
const char kData[] = "hello world";
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::AUTO_CALLBACK));
network_delegate.set_block_on(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST);
GURL redirect_url(http_test_server()->GetURL("/echo"));
network_delegate.set_redirect_url(redirect_url);
auto context = context_builder->Build();
{
GURL original_url(http_test_server()->GetURL("/defaultresponse"));
std::unique_ptr<URLRequest> r(context->CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_method("POST");
r->set_upload(CreateSimpleUploadData(base::byte_span_from_cstring(kData)));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kContentLength,
base::NumberToString(std::size(kData) - 1));
r->SetExtraRequestHeaders(headers);
r->Start();
d.RunUntilRedirect();
EXPECT_EQ(307, r->GetResponseCode());
EXPECT_EQ(307, r->response_headers()->response_code());
std::string location;
ASSERT_TRUE(
r->response_headers()->EnumerateHeader(nullptr, "Location", &location));
EXPECT_EQ(redirect_url, GURL(location));
r->FollowDeferredRedirect(std::nullopt ,
std::nullopt );
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(redirect_url, r->url());
EXPECT_EQ(original_url, r->original_url());
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
EXPECT_EQ("POST", r->method());
EXPECT_EQ(kData, d.data_received());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestOnHeadersReceived) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_proxy_resolution_service(
CreateFixedProxyResolutionService(
http_test_server()->host_port_pair().ToString()));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::AUTO_CALLBACK));
auto context = context_builder->Build();
network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
GURL redirect_url("http://does.not.resolve.test/simple.html");
network_delegate.set_redirect_on_headers_received_url(redirect_url);
{
GURL original_url("http://does.not.resolve.test/defaultresponse");
std::unique_ptr<URLRequest> r(context->CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
http_test_server()->host_port_pair()),
r->proxy_chain());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(redirect_url, r->url());
EXPECT_EQ(original_url, r->original_url());
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(2, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncNoAction) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS));
auto context = context_builder->Build();
d.set_credentials(AuthCredentials(kUser, kSecret));
{
GURL url(http_test_server()->GetURL("/auth-basic"));
std::unique_ptr<URLRequest> r(context->CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_TRUE(d.auth_required_called());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateOverrideHeadersWithAuth) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
default_network_delegate().set_add_header_to_first_response(true);
{
GURL url(http_test_server()->GetURL("/auth-basic"));
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_TRUE(d.auth_required_called());
EXPECT_FALSE(r->response_headers()->HasHeader("X-Network-Delegate"));
}
{
GURL url(http_test_server()->GetURL("/defaultresponse"));
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_TRUE(r->response_headers()->HasHeader("X-Network-Delegate"));
}
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting1) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::USER_CALLBACK));
network_delegate.set_block_on(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST);
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
network_delegate.RunUntilBlocked();
EXPECT_EQ(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST,
network_delegate.stage_blocked_for_callback());
EXPECT_EQ(0, network_delegate.completed_requests());
r->Cancel();
EXPECT_EQ(1, network_delegate.completed_requests());
EXPECT_EQ(1, network_delegate.canceled_requests());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting2) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::USER_CALLBACK));
network_delegate.set_block_on(
BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS);
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
network_delegate.RunUntilBlocked();
EXPECT_EQ(BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS,
network_delegate.stage_blocked_for_callback());
EXPECT_EQ(0, network_delegate.completed_requests());
r->Cancel();
EXPECT_EQ(1, network_delegate.completed_requests());
EXPECT_EQ(1, network_delegate.canceled_requests());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting3) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::USER_CALLBACK));
network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
network_delegate.RunUntilBlocked();
EXPECT_EQ(BlockingNetworkDelegate::ON_HEADERS_RECEIVED,
network_delegate.stage_blocked_for_callback());
EXPECT_EQ(0, network_delegate.completed_requests());
r->Cancel();
EXPECT_EQ(1, network_delegate.completed_requests());
EXPECT_EQ(1, network_delegate.canceled_requests());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
}
namespace {
std::unique_ptr<test_server::HttpResponse> HandleServerAuthConnect(
const test_server::HttpRequest& request) {
if (request.headers.find("Host") == request.headers.end() ||
request.headers.at("Host") != "www.server-auth.com" ||
request.method != test_server::METHOD_CONNECT) {
return nullptr;
}
auto http_response = std::make_unique<test_server::BasicHttpResponse>();
http_response->set_code(HTTP_UNAUTHORIZED);
http_response->AddCustomHeader("WWW-Authenticate",
"Basic realm=\"WallyWorld\"");
return http_response;
}
}
TEST_F(URLRequestTestHTTP, UnexpectedServerAuthTest) {
http_test_server()->RegisterRequestHandler(
base::BindRepeating(&HandleServerAuthConnect));
ASSERT_TRUE(http_test_server()->Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_proxy_resolution_service(
CreateFixedProxyResolutionService(
http_test_server()->host_port_pair().ToString()));
auto context = context_builder->Build();
TestDelegate d;
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
GURL("https://www.server-auth.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
http_test_server()->host_port_pair()),
r->proxy_chain());
EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, d.request_status());
}
}
TEST_F(URLRequestTestHTTP, GetTest_NoCache) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
EXPECT_EQ(http_test_server()->host_port_pair().host(),
r->GetResponseRemoteEndpoint().ToStringWithoutPort());
EXPECT_EQ(http_test_server()->host_port_pair().port(),
r->GetResponseRemoteEndpoint().port());
}
}
TEST_F(URLRequestTestHTTP, GetTest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
EXPECT_EQ(http_test_server()->host_port_pair().host(),
r->GetResponseRemoteEndpoint().ToStringWithoutPort());
EXPECT_EQ(http_test_server()->host_port_pair().port(),
r->GetResponseRemoteEndpoint().port());
}
}
TEST_F(URLRequestTestHTTP, GetTestLoadTiming) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
LoadTimingInfo load_timing_info;
r->GetLoadTimingInfo(&load_timing_info);
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
EXPECT_EQ(http_test_server()->host_port_pair().host(),
r->GetResponseRemoteEndpoint().ToStringWithoutPort());
EXPECT_EQ(http_test_server()->host_port_pair().port(),
r->GetResponseRemoteEndpoint().port());
}
}
namespace {
constexpr std::string_view kZippedContentLengthCompressed = "C";
constexpr std::string_view kZippedContentLengthUncompressed = "U";
constexpr std::string_view kZippedContentLengthShort = "S";
constexpr std::string_view kZippedContentLengthMedium = "M";
constexpr std::string_view kZippedContentLengthLong = "L";
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() != "/compressedfiles/BullRunSpeech.txt") {
return nullptr;
}
size_t length;
if (url.query() == kZippedContentLengthCompressed) {
length = compressed_content.size();
} else if (url.query() == kZippedContentLengthUncompressed) {
length = uncompressed_length;
} else if (url.query() == kZippedContentLengthShort) {
length = compressed_content.size() / 2;
} else if (url.query() == kZippedContentLengthMedium) {
length = (compressed_content.size() + uncompressed_length) / 2;
} else if (url.query() == 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);
}
}
TEST_F(URLRequestTestHTTP, GetZippedTest) {
base::FilePath file_path;
base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &file_path);
file_path = file_path.Append(kTestFilePath);
std::string expected_content, compressed_content;
ASSERT_TRUE(base::ReadFileToString(
file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt")),
&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 {
std::string_view parameter;
bool expect_success;
} kTests[] = {
{kZippedContentLengthCompressed, true},
{kZippedContentLengthUncompressed, true},
{kZippedContentLengthLong, false},
{kZippedContentLengthMedium, false},
{kZippedContentLengthShort, true},
};
for (const auto& test : kTests) {
SCOPED_TRACE(test.parameter);
TestDelegate d;
std::string test_file = base::StringPrintf(
"/compressedfiles/BullRunSpeech.txt?%s", test.parameter);
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto context = context_builder->Build();
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();
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 (test.parameter == kZippedContentLengthShort) {
EXPECT_EQ(expected_content.substr(0, d.data_received().size()),
d.data_received());
} else {
EXPECT_EQ(expected_content, d.data_received());
}
} else {
EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, d.request_status())
<< " Parameter = \"" << test_file << "\"";
}
}
}
TEST_F(URLRequestTestHTTP, RedirectLoadTiming) {
ASSERT_TRUE(http_test_server()->Start());
GURL destination_url = http_test_server()->GetURL("/");
GURL original_url =
http_test_server()->GetURL("/server-redirect?" + destination_url.spec());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(destination_url, req->url());
EXPECT_EQ(original_url, req->original_url());
ASSERT_EQ(2U, req->url_chain().size());
EXPECT_EQ(original_url, req->url_chain()[0]);
EXPECT_EQ(destination_url, req->url_chain()[1]);
LoadTimingInfo load_timing_info_before_redirect;
EXPECT_TRUE(default_network_delegate().GetLoadTimingInfoBeforeRedirect(
&load_timing_info_before_redirect));
TestLoadTimingNotReused(load_timing_info_before_redirect,
CONNECT_TIMING_HAS_DNS_TIMES);
LoadTimingInfo load_timing_info;
req->GetLoadTimingInfo(&load_timing_info);
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
EXPECT_NE(load_timing_info_before_redirect.socket_log_id,
load_timing_info.socket_log_id);
EXPECT_LE(load_timing_info_before_redirect.receive_headers_end,
load_timing_info.connect_timing.connect_start);
}
TEST_F(URLRequestTestHTTP, MultipleRedirectTest) {
ASSERT_TRUE(http_test_server()->Start());
GURL destination_url = http_test_server()->GetURL("/");
GURL middle_redirect_url =
http_test_server()->GetURL("/server-redirect?" + destination_url.spec());
GURL original_url = http_test_server()->GetURL("/server-redirect?" +
middle_redirect_url.spec());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(2, d.received_redirect_count());
EXPECT_EQ(destination_url, req->url());
EXPECT_EQ(original_url, req->original_url());
ASSERT_EQ(3U, req->url_chain().size());
EXPECT_EQ(original_url, req->url_chain()[0]);
EXPECT_EQ(middle_redirect_url, req->url_chain()[1]);
EXPECT_EQ(destination_url, req->url_chain()[2]);
}
TEST_F(URLRequestTestHTTP, RedirectEscaping) {
ASSERT_TRUE(http_test_server()->Start());
GURL destination_base = http_test_server()->GetURL("/defaultresponse");
std::string destination_url =
destination_base.spec() + "#\xE2\x98\x83_%E2%98%83_\xE0\xE0";
std::string destination_escaped =
destination_base.spec() + "#%E2%98%83_%E2%98%83_%E0%E0";
GURL original_url = http_test_server()->GetURL(
"/server-redirect?" +
base::EscapeQueryParamValue(destination_url, false));
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(destination_escaped, req->url().spec());
EXPECT_EQ(original_url, req->original_url());
ASSERT_EQ(2U, req->url_chain().size());
EXPECT_EQ(original_url, req->url_chain()[0]);
EXPECT_EQ(destination_escaped, req->url_chain()[1].spec());
}
const char kFirstDelegateInfo[] = "Wonderful delegate";
const char16_t kFirstDelegateInfo16[] = u"Wonderful delegate";
const char kSecondDelegateInfo[] = "Exciting delegate";
const char16_t kSecondDelegateInfo16[] = u"Exciting delegate";
class AsyncDelegateLogger : public base::RefCounted<AsyncDelegateLogger> {
public:
using Callback = base::OnceCallback<void()>;
AsyncDelegateLogger(const AsyncDelegateLogger&) = delete;
AsyncDelegateLogger& operator=(const AsyncDelegateLogger&) = delete;
static void Run(URLRequest* url_request,
LoadState expected_first_load_state,
LoadState expected_second_load_state,
LoadState expected_third_load_state,
Callback callback) {
auto logger = base::WrapRefCounted(new AsyncDelegateLogger(
url_request, expected_first_load_state, expected_second_load_state,
expected_third_load_state, std::move(callback)));
logger->Start();
}
static size_t CheckDelegateInfo(const std::vector<NetLogEntry>& entries,
size_t log_position) {
if (log_position + 3 >= entries.size()) {
ADD_FAILURE() << "Not enough log entries";
return entries.size();
}
std::string delegate_info;
EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::BEGIN, entries[log_position].phase);
EXPECT_EQ(
kFirstDelegateInfo,
GetStringValueFromParams(entries[log_position], "delegate_blocked_by"));
++log_position;
EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
++log_position;
EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::BEGIN, entries[log_position].phase);
EXPECT_EQ(
kSecondDelegateInfo,
GetStringValueFromParams(entries[log_position], "delegate_blocked_by"));
++log_position;
EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
return log_position + 1;
}
private:
friend class base::RefCounted<AsyncDelegateLogger>;
AsyncDelegateLogger(URLRequest* url_request,
LoadState expected_first_load_state,
LoadState expected_second_load_state,
LoadState expected_third_load_state,
Callback callback)
: url_request_(url_request),
expected_first_load_state_(expected_first_load_state),
expected_second_load_state_(expected_second_load_state),
expected_third_load_state_(expected_third_load_state),
callback_(std::move(callback)) {}
~AsyncDelegateLogger() = default;
void Start() {
url_request_->LogBlockedBy(kFirstDelegateInfo);
LoadStateWithParam load_state = url_request_->GetLoadState();
EXPECT_EQ(expected_first_load_state_, load_state.state);
EXPECT_NE(kFirstDelegateInfo16, load_state.param);
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&AsyncDelegateLogger::LogSecondDelegate, this));
}
void LogSecondDelegate() {
url_request_->LogAndReportBlockedBy(kSecondDelegateInfo);
LoadStateWithParam load_state = url_request_->GetLoadState();
EXPECT_EQ(expected_second_load_state_, load_state.state);
if (expected_second_load_state_ == LOAD_STATE_WAITING_FOR_DELEGATE) {
EXPECT_EQ(kSecondDelegateInfo16, load_state.param);
} else {
EXPECT_NE(kSecondDelegateInfo16, load_state.param);
}
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&AsyncDelegateLogger::LogComplete, this));
}
void LogComplete() {
url_request_->LogUnblocked();
LoadStateWithParam load_state = url_request_->GetLoadState();
EXPECT_EQ(expected_third_load_state_, load_state.state);
if (expected_second_load_state_ == LOAD_STATE_WAITING_FOR_DELEGATE)
EXPECT_EQ(std::u16string(), load_state.param);
std::move(callback_).Run();
}
raw_ptr<URLRequest> url_request_;
const int expected_first_load_state_;
const int expected_second_load_state_;
const int expected_third_load_state_;
Callback callback_;
};
class AsyncLoggingNetworkDelegate : public TestNetworkDelegate {
public:
AsyncLoggingNetworkDelegate() = default;
AsyncLoggingNetworkDelegate(const AsyncLoggingNetworkDelegate&) = delete;
AsyncLoggingNetworkDelegate& operator=(const AsyncLoggingNetworkDelegate&) =
delete;
~AsyncLoggingNetworkDelegate() override = default;
int OnBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url) override {
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeURLRequest(
request, base::NullCallback(), new_url));
return RunCallbackAsynchronously(request, std::move(callback));
}
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override {
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
request, headers, base::NullCallback()));
return RunCallbackAsynchronously(
request, base::BindOnce(
[](OnBeforeStartTransactionCallback callback, int result) {
std::move(callback).Run(result, std::nullopt);
},
std::move(callback)));
}
int OnHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
const HttpResponseHeaders* original_response_headers,
scoped_refptr<HttpResponseHeaders>* override_response_headers,
const IPEndPoint& endpoint,
std::optional<GURL>* preserve_fragment_on_redirect_url,
const std::optional<net::SSLInfo>& ssl_info) override {
CHECK_NE(ERR_IO_PENDING,
TestNetworkDelegate::OnHeadersReceived(
request, base::NullCallback(), original_response_headers,
override_response_headers, endpoint,
preserve_fragment_on_redirect_url, ssl_info));
return RunCallbackAsynchronously(request, std::move(callback));
}
private:
static int RunCallbackAsynchronously(URLRequest* request,
CompletionOnceCallback callback) {
AsyncDelegateLogger::Run(request, LOAD_STATE_WAITING_FOR_DELEGATE,
LOAD_STATE_WAITING_FOR_DELEGATE,
LOAD_STATE_WAITING_FOR_DELEGATE,
base::BindOnce(std::move(callback), OK));
return ERR_IO_PENDING;
}
};
class AsyncLoggingUrlRequestDelegate : public TestDelegate {
public:
enum CancelStage {
NO_CANCEL = 0,
CANCEL_ON_RECEIVED_REDIRECT,
CANCEL_ON_RESPONSE_STARTED,
CANCEL_ON_READ_COMPLETED
};
explicit AsyncLoggingUrlRequestDelegate(CancelStage cancel_stage)
: cancel_stage_(cancel_stage) {
if (cancel_stage == CANCEL_ON_RECEIVED_REDIRECT)
set_cancel_in_received_redirect(true);
else if (cancel_stage == CANCEL_ON_RESPONSE_STARTED)
set_cancel_in_response_started(true);
else if (cancel_stage == CANCEL_ON_READ_COMPLETED)
set_cancel_in_received_data(true);
}
AsyncLoggingUrlRequestDelegate(const AsyncLoggingUrlRequestDelegate&) =
delete;
AsyncLoggingUrlRequestDelegate& operator=(
const AsyncLoggingUrlRequestDelegate&) = delete;
~AsyncLoggingUrlRequestDelegate() override = default;
void OnReceivedRedirect(URLRequest* request,
const RedirectInfo& redirect_info,
bool* defer_redirect) override {
*defer_redirect = true;
AsyncDelegateLogger::Run(
request, LOAD_STATE_WAITING_FOR_DELEGATE,
LOAD_STATE_WAITING_FOR_DELEGATE, LOAD_STATE_WAITING_FOR_DELEGATE,
base::BindOnce(
&AsyncLoggingUrlRequestDelegate::OnReceivedRedirectLoggingComplete,
base::Unretained(this), request, redirect_info));
}
void OnResponseStarted(URLRequest* request, int net_error) override {
AsyncDelegateLogger::Run(
request, LOAD_STATE_WAITING_FOR_DELEGATE,
LOAD_STATE_WAITING_FOR_DELEGATE, LOAD_STATE_WAITING_FOR_DELEGATE,
base::BindOnce(
&AsyncLoggingUrlRequestDelegate::OnResponseStartedLoggingComplete,
base::Unretained(this), request, net_error));
}
void OnReadCompleted(URLRequest* request, int bytes_read) override {
AsyncDelegateLogger::Run(
request, LOAD_STATE_IDLE, LOAD_STATE_IDLE, LOAD_STATE_IDLE,
base::BindOnce(
&AsyncLoggingUrlRequestDelegate::AfterReadCompletedLoggingComplete,
base::Unretained(this), request, bytes_read));
}
private:
void OnReceivedRedirectLoggingComplete(URLRequest* request,
const RedirectInfo& redirect_info) {
bool defer_redirect = false;
TestDelegate::OnReceivedRedirect(request, redirect_info, &defer_redirect);
if (cancel_stage_ == CANCEL_ON_RECEIVED_REDIRECT)
return;
if (!defer_redirect) {
request->FollowDeferredRedirect(std::nullopt ,
std::nullopt );
}
}
void OnResponseStartedLoggingComplete(URLRequest* request, int net_error) {
TestDelegate::OnResponseStarted(request, net_error);
}
void AfterReadCompletedLoggingComplete(URLRequest* request, int bytes_read) {
TestDelegate::OnReadCompleted(request, bytes_read);
}
const CancelStage cancel_stage_;
};
TEST_F(URLRequestTestHTTP, DelegateInfoBeforeStart) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate request_delegate;
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_net_log(NetLog::Get());
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY,
&request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
LoadStateWithParam load_state = r->GetLoadState();
EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
EXPECT_EQ(std::u16string(), load_state.param);
AsyncDelegateLogger::Run(
r.get(), LOAD_STATE_WAITING_FOR_DELEGATE,
LOAD_STATE_WAITING_FOR_DELEGATE, LOAD_STATE_IDLE,
base::BindOnce(&URLRequest::Start, base::Unretained(r.get())));
request_delegate.RunUntilComplete();
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_EQ(OK, request_delegate.request_status());
}
auto entries = net_log_observer_.GetEntries();
size_t log_position = ExpectLogContainsSomewhereAfter(
entries, 0, NetLogEventType::DELEGATE_INFO, NetLogEventPhase::BEGIN);
log_position = AsyncDelegateLogger::CheckDelegateInfo(entries, log_position);
EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
NetLogEventType::DELEGATE_INFO));
}
TEST_F(URLRequestTestHTTP, NetworkDelegateInfo) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate request_delegate;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<AsyncLoggingNetworkDelegate>());
context_builder->set_net_log(NetLog::Get());
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/simple.html"), DEFAULT_PRIORITY,
&request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
LoadStateWithParam load_state = r->GetLoadState();
EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
EXPECT_EQ(std::u16string(), load_state.param);
r->Start();
request_delegate.RunUntilComplete();
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_EQ(OK, request_delegate.request_status());
EXPECT_EQ(1, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
size_t log_position = 0;
auto entries = net_log_observer_.GetEntries();
static const NetLogEventType kExpectedEvents[] = {
NetLogEventType::NETWORK_DELEGATE_BEFORE_URL_REQUEST,
NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION,
NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED,
};
for (NetLogEventType event : kExpectedEvents) {
SCOPED_TRACE(NetLogEventTypeToString(event));
log_position = ExpectLogContainsSomewhereAfter(
entries, log_position + 1, event, NetLogEventPhase::BEGIN);
log_position =
AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
ASSERT_LT(log_position, entries.size());
EXPECT_EQ(event, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
}
EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
NetLogEventType::DELEGATE_INFO));
}
TEST_F(URLRequestTestHTTP, NetworkDelegateInfoRedirect) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate request_delegate;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<AsyncLoggingNetworkDelegate>());
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/server-redirect?simple.html"),
DEFAULT_PRIORITY, &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
LoadStateWithParam load_state = r->GetLoadState();
EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
EXPECT_EQ(std::u16string(), load_state.param);
r->Start();
request_delegate.RunUntilComplete();
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_EQ(OK, request_delegate.request_status());
EXPECT_EQ(2, network_delegate.created_requests());
EXPECT_EQ(0, network_delegate.destroyed_requests());
}
EXPECT_EQ(1, network_delegate.destroyed_requests());
size_t log_position = 0;
auto entries = net_log_observer_.GetEntries();
static const NetLogEventType kExpectedEvents[] = {
NetLogEventType::NETWORK_DELEGATE_BEFORE_URL_REQUEST,
NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION,
NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED,
};
for (NetLogEventType event : kExpectedEvents) {
SCOPED_TRACE(NetLogEventTypeToString(event));
log_position = ExpectLogContainsSomewhereAfter(
entries, log_position + 1, event, NetLogEventPhase::BEGIN);
log_position =
AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
ASSERT_LT(log_position, entries.size());
EXPECT_EQ(event, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
}
log_position = ExpectLogContainsSomewhereAfter(
entries, log_position + 1,
NetLogEventType::URL_REQUEST_DELEGATE_RECEIVED_REDIRECT,
NetLogEventPhase::BEGIN);
for (NetLogEventType event : kExpectedEvents) {
SCOPED_TRACE(NetLogEventTypeToString(event));
log_position = ExpectLogContainsSomewhereAfter(
entries, log_position + 1, event, NetLogEventPhase::BEGIN);
log_position =
AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
ASSERT_LT(log_position, entries.size());
EXPECT_EQ(event, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
}
EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
NetLogEventType::DELEGATE_INFO));
}
TEST_F(URLRequestTestHTTP, URLRequestDelegateInfo) {
ASSERT_TRUE(http_test_server()->Start());
AsyncLoggingUrlRequestDelegate request_delegate(
AsyncLoggingUrlRequestDelegate::NO_CANCEL);
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_net_log(NetLog::Get());
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/chunked?waitBetweenChunks=20"),
DEFAULT_PRIORITY, &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
LoadStateWithParam load_state = r->GetLoadState();
r->Start();
request_delegate.RunUntilComplete();
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_EQ(OK, request_delegate.request_status());
}
auto entries = net_log_observer_.GetEntries();
size_t log_position = 0;
log_position = ExpectLogContainsSomewhereAfter(
entries, log_position + 1,
NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED,
NetLogEventPhase::BEGIN);
log_position =
AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
ASSERT_LT(log_position, entries.size());
EXPECT_EQ(NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED,
entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
NetLogEventType::DELEGATE_INFO));
EXPECT_FALSE(LogContainsEntryWithTypeAfter(
entries, log_position + 1,
NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED));
}
TEST_F(URLRequestTestHTTP, URLRequestDelegateInfoOnRedirect) {
ASSERT_TRUE(http_test_server()->Start());
AsyncLoggingUrlRequestDelegate request_delegate(
AsyncLoggingUrlRequestDelegate::NO_CANCEL);
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_net_log(NetLog::Get());
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/server-redirect?simple.html"),
DEFAULT_PRIORITY, &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
LoadStateWithParam load_state = r->GetLoadState();
r->Start();
request_delegate.RunUntilComplete();
EXPECT_EQ(200, r->GetResponseCode());
EXPECT_EQ(OK, request_delegate.request_status());
}
auto entries = net_log_observer_.GetEntries();
size_t log_position = 0;
static const NetLogEventType kExpectedEvents[] = {
NetLogEventType::URL_REQUEST_DELEGATE_RECEIVED_REDIRECT,
NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED,
};
for (NetLogEventType event : kExpectedEvents) {
SCOPED_TRACE(NetLogEventTypeToString(event));
log_position = ExpectLogContainsSomewhereAfter(entries, log_position, event,
NetLogEventPhase::BEGIN);
log_position =
AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
ASSERT_LT(log_position, entries.size());
EXPECT_EQ(event, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
}
EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
NetLogEventType::DELEGATE_INFO));
}
TEST_F(URLRequestTestHTTP, URLRequestDelegateOnRedirectCancelled) {
ASSERT_TRUE(http_test_server()->Start());
const AsyncLoggingUrlRequestDelegate::CancelStage kCancelStages[] = {
AsyncLoggingUrlRequestDelegate::CANCEL_ON_RECEIVED_REDIRECT,
AsyncLoggingUrlRequestDelegate::CANCEL_ON_RESPONSE_STARTED,
AsyncLoggingUrlRequestDelegate::CANCEL_ON_READ_COMPLETED,
};
for (auto cancel_stage : kCancelStages) {
AsyncLoggingUrlRequestDelegate request_delegate(cancel_stage);
RecordingNetLogObserver net_log_observer;
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_net_log(NetLog::Get());
auto context = context_builder->Build();
{
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/server-redirect?simple.html"),
DEFAULT_PRIORITY, &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
LoadStateWithParam load_state = r->GetLoadState();
r->Start();
request_delegate.RunUntilComplete();
EXPECT_EQ(ERR_ABORTED, request_delegate.request_status());
base::RunLoop().RunUntilIdle();
}
auto entries = net_log_observer.GetEntries();
size_t log_position = 0;
static const NetLogEventType kExpectedEvents[] = {
NetLogEventType::URL_REQUEST_DELEGATE_RECEIVED_REDIRECT,
NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED,
};
for (NetLogEventType event : kExpectedEvents) {
SCOPED_TRACE(NetLogEventTypeToString(event));
log_position = ExpectLogContainsSomewhereAfter(
entries, log_position, event, NetLogEventPhase::BEGIN);
log_position =
AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
ASSERT_LT(log_position, entries.size());
EXPECT_EQ(event, entries[log_position].type);
EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
}
EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
NetLogEventType::DELEGATE_INFO));
}
}
namespace {
const char kExtraHeader[] = "Allow-Snafu";
const char kExtraValue[] = "fubar";
class RedirectWithAdditionalHeadersDelegate : public TestDelegate {
void OnReceivedRedirect(URLRequest* request,
const RedirectInfo& redirect_info,
bool* defer_redirect) override {
TestDelegate::OnReceivedRedirect(request, redirect_info, defer_redirect);
request->SetExtraRequestHeaderByName(kExtraHeader, kExtraValue, false);
}
};
}
TEST_F(URLRequestTestHTTP, RedirectWithAdditionalHeadersTest) {
ASSERT_TRUE(http_test_server()->Start());
GURL destination_url =
http_test_server()->GetURL("/echoheader?" + std::string(kExtraHeader));
GURL original_url =
http_test_server()->GetURL("/server-redirect?" + destination_url.spec());
RedirectWithAdditionalHeadersDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
const HttpRequestHeaders& headers = req->extra_request_headers();
EXPECT_EQ(kExtraValue, headers.GetHeader(kExtraHeader));
EXPECT_FALSE(req->is_pending());
EXPECT_FALSE(req->is_redirecting());
EXPECT_EQ(kExtraValue, d.data_received());
}
namespace {
const char kExtraHeaderToRemove[] = "To-Be-Removed";
class RedirectWithHeaderRemovalDelegate : public TestDelegate {
void OnReceivedRedirect(URLRequest* request,
const RedirectInfo& redirect_info,
bool* defer_redirect) override {
TestDelegate::OnReceivedRedirect(request, redirect_info, defer_redirect);
request->RemoveRequestHeaderByName(kExtraHeaderToRemove);
}
};
}
TEST_F(URLRequestTestHTTP, RedirectWithHeaderRemovalTest) {
ASSERT_TRUE(http_test_server()->Start());
GURL destination_url = http_test_server()->GetURL(
"/echoheader?" + std::string(kExtraHeaderToRemove));
GURL original_url =
http_test_server()->GetURL("/server-redirect?" + destination_url.spec());
RedirectWithHeaderRemovalDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetExtraRequestHeaderByName(kExtraHeaderToRemove, "dummy", false);
req->Start();
d.RunUntilComplete();
const HttpRequestHeaders& headers = req->extra_request_headers();
EXPECT_FALSE(headers.GetHeader(kExtraHeaderToRemove));
EXPECT_FALSE(req->is_pending());
EXPECT_FALSE(req->is_redirecting());
EXPECT_EQ("None", d.data_received());
}
TEST_F(URLRequestTestHTTP, CancelAfterStart) {
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
GURL("http://www.google.com/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
r->Cancel();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(0, d.bytes_received());
EXPECT_FALSE(d.received_data_before_response());
}
}
TEST_F(URLRequestTestHTTP, CancelInResponseStarted) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
d.set_cancel_in_response_started(true);
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(0, d.bytes_received());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(ERR_ABORTED, d.request_status());
}
}
TEST_F(URLRequestTestHTTP, CancelOnDataReceived) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
d.set_cancel_in_received_data(true);
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_NE(0, d.received_bytes_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(ERR_ABORTED, d.request_status());
}
}
TEST_F(URLRequestTestHTTP, CancelDuringEofRead) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
d.set_cancel_in_received_data(true);
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(0, d.received_bytes_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(ERR_ABORTED, d.request_status());
}
}
TEST_F(URLRequestTestHTTP, CancelByDestroyingAfterStart) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.set_on_complete(base::DoNothing());
}
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
}
TEST_F(URLRequestTestHTTP, CancelWhileReadingFromCache) {
ASSERT_TRUE(http_test_server()->Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
r->Cancel();
d.RunUntilComplete();
EXPECT_EQ(ERR_ABORTED, d.request_status());
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(0, d.bytes_received());
EXPECT_FALSE(d.received_data_before_response());
}
}
TEST_F(URLRequestTestHTTP, PostTest) {
ASSERT_TRUE(http_test_server()->Start());
HTTPUploadDataOperationTest("POST");
}
TEST_F(URLRequestTestHTTP, PutTest) {
ASSERT_TRUE(http_test_server()->Start());
HTTPUploadDataOperationTest("PUT");
}
TEST_F(URLRequestTestHTTP, PostEmptyTest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_method("POST");
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
ASSERT_EQ(1, d.response_started_count())
<< "request failed. Error: " << d.request_status();
EXPECT_FALSE(d.received_data_before_response());
EXPECT_TRUE(d.data_received().empty());
}
}
TEST_F(URLRequestTestHTTP, PostFileTest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_method("POST");
base::FilePath dir;
base::PathService::Get(base::DIR_EXE, &dir);
base::SetCurrentDirectory(dir);
std::vector<std::unique_ptr<UploadElementReader>> element_readers;
base::FilePath path;
base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &path);
path = path.Append(kTestFilePath);
path = path.Append(FILE_PATH_LITERAL("with-headers.html"));
element_readers.push_back(std::make_unique<UploadFileElementReader>(
base::SingleThreadTaskRunner::GetCurrentDefault().get(), path, 0,
std::numeric_limits<uint64_t>::max(), base::Time()));
r->set_upload(std::make_unique<ElementsUploadDataStream>(
std::move(element_readers), 0));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
std::optional<int64_t> size64 = base::GetFileSize(path);
ASSERT_TRUE(size64.has_value());
ASSERT_LE(size64.value(), std::numeric_limits<int>::max());
int size = static_cast<int>(size64.value());
auto buf = std::make_unique<char[]>(size);
ASSERT_EQ(size, base::ReadFile(path, buf.get(), size));
ASSERT_EQ(1, d.response_started_count())
<< "request failed. Error: " << d.request_status();
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(size, d.bytes_received());
EXPECT_EQ(std::string(&buf[0], size), d.data_received());
}
}
TEST_F(URLRequestTestHTTP, PostUnreadableFileTest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_method("POST");
std::vector<std::unique_ptr<UploadElementReader>> element_readers;
element_readers.push_back(std::make_unique<UploadFileElementReader>(
base::SingleThreadTaskRunner::GetCurrentDefault().get(),
base::FilePath(FILE_PATH_LITERAL(
"c:\\path\\to\\non\\existant\\file.randomness.12345")),
0, std::numeric_limits<uint64_t>::max(), base::Time()));
r->set_upload(std::make_unique<ElementsUploadDataStream>(
std::move(element_readers), 0));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_TRUE(d.request_failed());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
EXPECT_EQ(ERR_FILE_NOT_FOUND, d.request_status());
}
}
namespace {
void AddDataToUpload(ChunkedUploadDataStream::Writer* writer) {
const auto append = [writer](std::string_view str, bool is_done) {
writer->AppendData(base::as_byte_span(str), is_done);
};
append("a", false);
append("bcd", false);
append("this is a longer chunk than before.", false);
append("\r\n\r\n", false);
append("0", false);
append("2323", true);
}
void VerifyReceivedDataMatchesChunks(URLRequest* r, TestDelegate* d) {
const std::string expected_data =
"abcdthis is a longer chunk than before.\r\n\r\n02323";
ASSERT_EQ(1, d->response_started_count())
<< "request failed. Error: " << d->request_status();
EXPECT_FALSE(d->received_data_before_response());
EXPECT_EQ(expected_data.size(), static_cast<size_t>(d->bytes_received()));
EXPECT_EQ(expected_data, d->data_received());
}
}
TEST_F(URLRequestTestHTTP, TestPostChunkedDataBeforeStart) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
auto upload_data_stream = std::make_unique<ChunkedUploadDataStream>(0);
std::unique_ptr<ChunkedUploadDataStream::Writer> writer =
upload_data_stream->CreateWriter();
r->set_upload(std::move(upload_data_stream));
r->set_method("POST");
AddDataToUpload(writer.get());
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
VerifyReceivedDataMatchesChunks(r.get(), &d);
}
}
TEST_F(URLRequestTestHTTP, TestPostChunkedDataJustAfterStart) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
auto upload_data_stream = std::make_unique<ChunkedUploadDataStream>(0);
std::unique_ptr<ChunkedUploadDataStream::Writer> writer =
upload_data_stream->CreateWriter();
r->set_upload(std::move(upload_data_stream));
r->set_method("POST");
r->Start();
EXPECT_TRUE(r->is_pending());
AddDataToUpload(writer.get());
d.RunUntilComplete();
VerifyReceivedDataMatchesChunks(r.get(), &d);
}
}
TEST_F(URLRequestTestHTTP, TestPostChunkedDataAfterStart) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
auto upload_data_stream = std::make_unique<ChunkedUploadDataStream>(0);
std::unique_ptr<ChunkedUploadDataStream::Writer> writer =
upload_data_stream->CreateWriter();
r->set_upload(std::move(upload_data_stream));
r->set_method("POST");
r->Start();
EXPECT_TRUE(r->is_pending());
base::RunLoop().RunUntilIdle();
base::RunLoop run_loop;
d.set_on_complete(run_loop.QuitClosure());
AddDataToUpload(writer.get());
run_loop.Run();
VerifyReceivedDataMatchesChunks(r.get(), &d);
}
}
TEST_F(URLRequestTestHTTP, ResponseHeadersTest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/with-headers.html"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
const HttpResponseHeaders* headers = req->response_headers();
EXPECT_EQ(headers, req->response_info().headers.get());
EXPECT_EQ(headers->GetNormalizedHeader("cache-control"), "private");
EXPECT_EQ(headers->GetNormalizedHeader("content-type"),
"text/html; charset=ISO-8859-1");
EXPECT_EQ(headers->GetNormalizedHeader("x-multiple-entries"), "a, b");
}
#if !BUILDFLAG(IS_IOS)
TEST_F(URLRequestTestHTTP, ProcessSTS) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
std::string test_server_hostname = "a.test";
https_test_server.SetCertHostnames({test_server_hostname});
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddRule(test_server_hostname,
https_test_server.GetIPLiteralString());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::move(host_resolver));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> request(context->CreateRequest(
https_test_server.GetURL(test_server_hostname, "/hsts-headers.html"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
TransportSecurityState* security_state = context->transport_security_state();
TransportSecurityState::STSState sts_state;
TransportSecurityState::PKPState pkp_state;
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,
sts_state.upgrade_mode);
EXPECT_TRUE(sts_state.include_subdomains);
EXPECT_FALSE(pkp_state.include_subdomains);
#if BUILDFLAG(IS_ANDROID)
#else
EXPECT_FALSE(pkp_state.HasPublicKeyPins());
#endif
}
TEST_F(URLRequestTestHTTP, STSNotProcessedOnIP) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
ASSERT_TRUE(https_test_server.GetURL("/").HostIsIPAddress());
std::string test_server_hostname = https_test_server.GetURL("/").GetHost();
TestDelegate d;
std::unique_ptr<URLRequest> request(default_context().CreateRequest(
https_test_server.GetURL("/hsts-headers.html"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
TransportSecurityState* security_state =
default_context().transport_security_state();
TransportSecurityState::STSState sts_state;
EXPECT_FALSE(
security_state->GetDynamicSTSState(test_server_hostname, &sts_state));
}
TEST_F(URLRequestTestHTTP, STSNotProcessedOnLocalhost) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(
net::features::kIgnoreHSTSForLocalhost);
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.SetSSLConfig(
net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
ASSERT_TRUE(net::IsLocalHostname(https_test_server.GetURL("/").GetHost()));
TestDelegate d;
std::unique_ptr<URLRequest> request(default_context().CreateRequest(
https_test_server.GetURL("/hsts-headers.html"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
TransportSecurityState* security_state =
default_context().transport_security_state();
TransportSecurityState::STSState sts_state;
EXPECT_FALSE(security_state->GetDynamicSTSState("localhost", &sts_state));
}
TEST_F(URLRequestTestHTTP, STSProcessedOnLocalhostWhenFeatureDisabled) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndDisableFeature(
net::features::kIgnoreHSTSForLocalhost);
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.SetSSLConfig(
net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
ASSERT_TRUE(net::IsLocalHostname(https_test_server.GetURL("/").GetHost()));
TestDelegate d;
std::unique_ptr<URLRequest> request(default_context().CreateRequest(
https_test_server.GetURL("/hsts-headers.html"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
TransportSecurityState* security_state =
default_context().transport_security_state();
TransportSecurityState::STSState sts_state;
EXPECT_TRUE(security_state->GetDynamicSTSState("localhost", &sts_state));
}
TEST_F(URLRequestTestHTTP, PKPBypassRecorded) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(
net::features::kStaticKeyPinningEnforcement);
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.SetSSLConfig(
net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
ASSERT_TRUE(cert);
CertVerifyResult verify_result;
verify_result.verified_cert = cert;
verify_result.is_issued_by_known_root = false;
SHA256HashValue hash;
hash.fill(1);
verify_result.public_key_hashes.push_back(hash);
auto cert_verifier = std::make_unique<MockCertVerifier>();
cert_verifier->AddResultForCert(cert.get(), verify_result, OK);
std::string test_server_hostname = "www.example.org";
SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCertVerifier(std::move(cert_verifier));
auto context = context_builder->Build();
context->transport_security_state()->EnableStaticPinsForTesting();
context->transport_security_state()->SetPinningListAlwaysTimelyForTesting(
true);
TestDelegate d;
std::unique_ptr<URLRequest> request(context->CreateRequest(
https_test_server.GetURL(test_server_hostname, "/simple.html"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->set_isolation_info(
IsolationInfo::CreateTransient(std::nullopt));
request->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
TransportSecurityState::PKPState pkp_state;
EXPECT_TRUE(context->transport_security_state()->GetStaticPKPState(
test_server_hostname, &pkp_state));
EXPECT_TRUE(pkp_state.HasPublicKeyPins());
EXPECT_TRUE(request->ssl_info().pkp_bypassed);
}
TEST_F(URLRequestTestHTTP, ProcessSTSOnce) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
std::string test_server_hostname = "a.test";
https_test_server.SetCertHostnames({test_server_hostname});
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddRule(test_server_hostname,
https_test_server.GetIPLiteralString());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::move(host_resolver));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> request(context->CreateRequest(
https_test_server.GetURL(test_server_hostname,
"/hsts-multiple-headers.html"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
TransportSecurityState* security_state = context->transport_security_state();
TransportSecurityState::STSState sts_state;
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);
EXPECT_FALSE(sts_state.include_subdomains);
}
#endif
#if BUILDFLAG(ENABLE_REPORTING)
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_DontReportIfNetworkNotAccessed) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&https_test_server);
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/cachetime");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->set_isolation_info(isolation_info1_);
request->Start();
d.RunUntilComplete();
ASSERT_EQ(1u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error =
nel_service.errors()[0];
EXPECT_EQ(request_url, error.uri);
EXPECT_EQ(200, error.status_code);
EXPECT_EQ(OK, error.type);
request = context->CreateRequest(request_url, DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS);
request->set_isolation_info(isolation_info1_);
request->Start();
d.RunUntilComplete();
EXPECT_FALSE(request->response_info().network_accessed);
EXPECT_TRUE(request->response_info().was_cached);
EXPECT_EQ(1u, nel_service.errors().size());
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_BasicSuccess) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/simple.html");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
ASSERT_EQ(1u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error =
nel_service.errors()[0];
EXPECT_EQ(request_url, error.uri);
EXPECT_EQ(200, error.status_code);
EXPECT_EQ(OK, error.type);
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_BasicError) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&https_test_server);
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/close-socket");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
ASSERT_EQ(1u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error =
nel_service.errors()[0];
EXPECT_EQ(request_url, error.uri);
EXPECT_EQ(0, error.status_code);
EXPECT_EQ(ERR_EMPTY_RESPONSE, error.type);
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_Redirect) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/redirect-test.html");
GURL redirect_url = https_test_server.GetURL("/with-headers.html");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
ASSERT_EQ(2u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error1 =
nel_service.errors()[0];
EXPECT_EQ(request_url, error1.uri);
EXPECT_EQ(302, error1.status_code);
EXPECT_EQ(OK, error1.type);
const TestNetworkErrorLoggingService::RequestDetails& error2 =
nel_service.errors()[1];
EXPECT_EQ(redirect_url, error2.uri);
EXPECT_EQ(200, error2.status_code);
EXPECT_EQ(OK, error2.type);
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_RedirectWithoutLocationHeader) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/308-without-location-header");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
ASSERT_EQ(1u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error =
nel_service.errors()[0];
EXPECT_EQ(request_url, error.uri);
EXPECT_EQ(308, error.status_code);
EXPECT_EQ(OK, error.type);
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_Auth) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&https_test_server);
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/auth-basic");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
ASSERT_EQ(2u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error1 =
nel_service.errors()[0];
EXPECT_EQ(request_url, error1.uri);
EXPECT_EQ(401, error1.status_code);
EXPECT_EQ(OK, error1.type);
const TestNetworkErrorLoggingService::RequestDetails& error2 =
nel_service.errors()[1];
EXPECT_EQ(request_url, error2.uri);
EXPECT_EQ(200, error2.status_code);
EXPECT_EQ(OK, error2.type);
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_304Response) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&https_test_server);
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/auth-basic");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
{
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> r(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info(isolation_info1_);
r->Start();
d.RunUntilComplete();
}
ASSERT_EQ(2u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error1 =
nel_service.errors()[0];
EXPECT_EQ(request_url, error1.uri);
EXPECT_EQ(401, error1.status_code);
EXPECT_EQ(OK, error1.type);
const TestNetworkErrorLoggingService::RequestDetails& error2 =
nel_service.errors()[1];
EXPECT_EQ(request_url, error2.uri);
EXPECT_EQ(200, error2.status_code);
EXPECT_EQ(OK, error2.type);
{
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> r(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetLoadFlags(LOAD_VALIDATE_CACHE);
r->set_isolation_info(isolation_info1_);
r->Start();
d.RunUntilComplete();
EXPECT_TRUE(r->was_cached());
}
ASSERT_EQ(3u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error3 =
nel_service.errors()[2];
EXPECT_EQ(request_url, error3.uri);
EXPECT_EQ(304, error3.status_code);
EXPECT_EQ(OK, error3.type);
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelInResponseStarted) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/simple.html");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
d.set_cancel_in_response_started(true);
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
ASSERT_EQ(1u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error =
nel_service.errors()[0];
EXPECT_EQ(request_url, error.uri);
EXPECT_EQ(200, error.status_code);
EXPECT_EQ(ERR_ABORTED, error.type);
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelOnDataReceived) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/simple.html");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
d.set_cancel_in_received_data(true);
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
ASSERT_EQ(1u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error =
nel_service.errors()[0];
EXPECT_EQ(request_url, error.uri);
EXPECT_EQ(200, error.status_code);
EXPECT_EQ(ERR_ABORTED, error.type);
}
TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelRedirect) {
EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server.ServeFilesFromSourceDirectory(
base::FilePath(kTestFilePath));
ASSERT_TRUE(https_test_server.Start());
GURL request_url = https_test_server.GetURL("/redirect-test.html");
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_error_logging_enabled(true);
auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
std::make_unique<TestNetworkErrorLoggingService>());
auto context = context_builder->Build();
TestDelegate d;
d.set_cancel_in_received_redirect(true);
std::unique_ptr<URLRequest> request(context->CreateRequest(
request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
ASSERT_EQ(1u, nel_service.errors().size());
const TestNetworkErrorLoggingService::RequestDetails& error =
nel_service.errors()[0];
EXPECT_EQ(request_url, error.uri);
EXPECT_EQ(302, error.status_code);
EXPECT_EQ(OK, error.type);
}
#endif
TEST_F(URLRequestTestHTTP, ContentTypeNormalizationTest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/content-type-normalization.html"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
std::string mime_type;
req->GetMimeType(&mime_type);
EXPECT_EQ("text/html", mime_type);
std::string charset;
req->GetCharset(&charset);
EXPECT_EQ("utf-8", charset);
req->Cancel();
}
TEST_F(URLRequestTestHTTP, FileRedirect) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/redirect-to-file.html"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(ERR_UNKNOWN_URL_SCHEME, d.request_status());
EXPECT_EQ(1, d.received_redirect_count());
}
TEST_F(URLRequestTestHTTP, DataRedirect) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/redirect-to-data.html"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(ERR_UNKNOWN_URL_SCHEME, d.request_status());
EXPECT_EQ(1, d.received_redirect_count());
}
TEST_F(URLRequestTestHTTP, RestrictUnsafeRedirect) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL(
"/server-redirect?unsafe://here-there-be-dragons"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(ERR_UNSAFE_REDIRECT, d.request_status());
EXPECT_EQ(0, d.received_redirect_count());
}
TEST_F(URLRequestTestHTTP, RedirectToInvalidURL) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/redirect-to-invalid-url.html"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(ERR_INVALID_REDIRECT, d.request_status());
EXPECT_EQ(0, d.received_redirect_count());
}
TEST_F(URLRequestTestHTTP, CacheRedirect) {
ASSERT_TRUE(http_test_server()->Start());
GURL redirect_url =
http_test_server()->GetURL("/redirect302-to-echo-cacheable");
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(isolation_info1_);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(http_test_server()->GetURL("/echo"), req->url());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(isolation_info1_);
req->Start();
d.RunUntilRedirect();
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(0, d.response_started_count());
EXPECT_TRUE(req->was_cached());
req->FollowDeferredRedirect(std::nullopt ,
std::nullopt );
d.RunUntilComplete();
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(http_test_server()->GetURL("/echo"), req->url());
}
}
TEST_F(URLRequestTestHTTP, NoCacheOnNetworkDelegateRedirect) {
ASSERT_TRUE(http_test_server()->Start());
GURL initial_url = http_test_server()->GetURL("/cachetime");
{
GURL redirect_to_url = http_test_server()->GetURL("/echo");
default_network_delegate().set_redirect_on_headers_received_url(
redirect_to_url);
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
initial_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(redirect_to_url, req->url());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
initial_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_FALSE(req->was_cached());
EXPECT_EQ(0, d.received_redirect_count());
EXPECT_EQ(initial_url, req->url());
}
}
TEST_F(URLRequestTestHTTP, PreserveFragmentOnRedirectUrl) {
ASSERT_TRUE(http_test_server()->Start());
GURL original_url(http_test_server()->GetURL("/original#fragment1"));
GURL preserve_fragement_url(http_test_server()->GetURL("/echo"));
default_network_delegate().set_redirect_on_headers_received_url(
preserve_fragement_url);
default_network_delegate().set_preserve_fragment_on_redirect_url(
preserve_fragement_url);
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(original_url, r->original_url());
EXPECT_EQ(preserve_fragement_url, r->url());
}
}
TEST_F(URLRequestTestHTTP, PreserveFragmentOnRedirectUrlMismatch) {
ASSERT_TRUE(http_test_server()->Start());
GURL original_url(http_test_server()->GetURL("/original#fragment1"));
GURL preserve_fragement_url(http_test_server()->GetURL("/echo#fragment2"));
GURL redirect_url(http_test_server()->GetURL("/echo"));
GURL expected_url(http_test_server()->GetURL("/echo#fragment1"));
default_network_delegate().set_redirect_on_headers_received_url(redirect_url);
default_network_delegate().set_preserve_fragment_on_redirect_url(
preserve_fragement_url);
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(original_url, r->original_url());
EXPECT_EQ(expected_url, r->url());
}
}
TEST_F(URLRequestTestHTTP, RedirectJobWithReferenceFragment) {
ASSERT_TRUE(http_test_server()->Start());
GURL original_url(
http_test_server()->GetURL("/original#should-not-be-appended"));
GURL redirect_url(http_test_server()->GetURL("/echo"));
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
std::unique_ptr<URLRequestRedirectJob> job =
std::make_unique<URLRequestRedirectJob>(
r.get(), redirect_url, RedirectUtil::ResponseCode::REDIRECT_302_FOUND,
"Very Good Reason");
TestScopedURLInterceptor interceptor(r->url(), std::move(job));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(original_url, r->original_url());
EXPECT_EQ(redirect_url, r->url());
}
TEST_F(URLRequestTestHTTP, UnsupportedReferrerScheme) {
ASSERT_TRUE(http_test_server()->Start());
const std::string referrer("foobar://totally.legit.referrer");
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer(referrer);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string("None"), d.data_received());
}
TEST_F(URLRequestTestHTTP, NoUserPassInReferrer) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://user:pass@foo.com/");
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string("http://foo.com/"), d.data_received());
}
TEST_F(URLRequestTestHTTP, NoFragmentInReferrer) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://foo.com/test#fragment");
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string("http://foo.com/test"), d.data_received());
}
TEST_F(URLRequestTestHTTP, EmptyReferrerAfterValidReferrer) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer("http://foo.com/test#fragment");
req->SetReferrer("");
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string("None"), d.data_received());
}
TEST_F(URLRequestTestHTTP, CapRefererHeaderLength) {
ASSERT_TRUE(http_test_server()->Start());
{
std::string original_header = "http://example.com/";
original_header.resize(4097, 'a');
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer(original_header);
req->Start();
d.RunUntilComplete();
EXPECT_EQ("None", d.data_received());
}
{
std::string original_header = "http://example.com/";
original_header.resize(4096, 'a');
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer(original_header);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(original_header, d.data_received());
}
{
std::string original_header = "http://example.com/";
original_header.resize(4095, 'a');
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetReferrer(original_header);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(original_header, d.data_received());
}
}
TEST_F(URLRequestTestHTTP, CancelRedirect) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
d.set_cancel_in_received_redirect(true);
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/redirect-test.html"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(0, d.bytes_received());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(ERR_ABORTED, d.request_status());
}
}
TEST_F(URLRequestTestHTTP, DeferredRedirect) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
GURL test_url(http_test_server()->GetURL("/redirect-test.html"));
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilRedirect();
EXPECT_EQ(1, d.received_redirect_count());
req->FollowDeferredRedirect(std::nullopt ,
std::nullopt );
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(OK, d.request_status());
base::FilePath path;
base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &path);
path = path.Append(kTestFilePath);
path = path.Append(FILE_PATH_LITERAL("with-headers.html"));
std::string contents;
EXPECT_TRUE(base::ReadFileToString(path, &contents));
EXPECT_EQ(contents, d.data_received());
}
}
TEST_F(URLRequestTestHTTP, DeferredRedirect_ModifiedHeaders) {
test_server::HttpRequest http_request;
int num_observed_requests = 0;
http_test_server()->RegisterRequestMonitor(
base::BindLambdaForTesting([&](const test_server::HttpRequest& request) {
http_request = request;
++num_observed_requests;
}));
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
GURL test_url(http_test_server()->GetURL("/redirect-test.html"));
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetExtraRequestHeaderByName("Header1", "Value1", true );
req->SetExtraRequestHeaderByName("Header2", "Value2", true );
req->Start();
d.RunUntilRedirect();
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(1, num_observed_requests);
EXPECT_EQ("Value1", http_request.headers["Header1"]);
EXPECT_EQ("Value2", http_request.headers["Header2"]);
EXPECT_EQ(0u, http_request.headers.count("Header3"));
net::HttpRequestHeaders modified_headers;
modified_headers.SetHeader("Header2", "");
modified_headers.SetHeader("Header3", "Value3");
req->FollowDeferredRedirect(std::nullopt ,
modified_headers);
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(2, num_observed_requests);
EXPECT_EQ("Value1", http_request.headers["Header1"]);
EXPECT_EQ(1u, http_request.headers.count("Header2"));
EXPECT_EQ("", http_request.headers["Header2"]);
EXPECT_EQ("Value3", http_request.headers["Header3"]);
}
}
TEST_F(URLRequestTestHTTP, DeferredRedirect_RemovedHeaders) {
test_server::HttpRequest http_request;
int num_observed_requests = 0;
http_test_server()->RegisterRequestMonitor(
base::BindLambdaForTesting([&](const test_server::HttpRequest& request) {
http_request = request;
++num_observed_requests;
}));
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
GURL test_url(http_test_server()->GetURL("/redirect-test.html"));
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetExtraRequestHeaderByName("Header1", "Value1", true );
req->SetExtraRequestHeaderByName("Header2", "Value2", true );
req->Start();
d.RunUntilRedirect();
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(1, num_observed_requests);
EXPECT_EQ("Value1", http_request.headers["Header1"]);
EXPECT_EQ("Value2", http_request.headers["Header2"]);
std::vector<std::string> removed_headers({"Header2"});
req->FollowDeferredRedirect(removed_headers,
std::nullopt );
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(2, num_observed_requests);
EXPECT_EQ("Value1", http_request.headers["Header1"]);
EXPECT_EQ(0u, http_request.headers.count("Header2"));
}
}
TEST_F(URLRequestTestHTTP, CancelDeferredRedirect) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/redirect-test.html"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilRedirect();
EXPECT_EQ(1, d.received_redirect_count());
req->Cancel();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(0, d.bytes_received());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(ERR_ABORTED, d.request_status());
}
}
TEST_F(URLRequestTestHTTP, VaryHeader) {
ASSERT_TRUE(http_test_server()->Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
headers.SetHeader("foo", "1");
req->SetExtraRequestHeaders(headers);
req->set_isolation_info(isolation_info1_);
req->Start();
d.RunUntilComplete();
LoadTimingInfo load_timing_info;
req->GetLoadTimingInfo(&load_timing_info);
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
headers.SetHeader("foo", "1");
req->SetExtraRequestHeaders(headers);
req->set_isolation_info(isolation_info1_);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(req->was_cached());
LoadTimingInfo load_timing_info;
req->GetLoadTimingInfo(&load_timing_info);
TestLoadTimingCacheHitNoNetwork(load_timing_info);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
headers.SetHeader("foo", "2");
req->SetExtraRequestHeaders(headers);
req->set_isolation_info(isolation_info1_);
req->Start();
d.RunUntilComplete();
EXPECT_FALSE(req->was_cached());
LoadTimingInfo load_timing_info;
req->GetLoadTimingInfo(&load_timing_info);
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
}
}
TEST_F(URLRequestTestHTTP, BasicAuth) {
ASSERT_TRUE(http_test_server()->Start());
{
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info(isolation_info1_);
r->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
}
{
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetLoadFlags(LOAD_VALIDATE_CACHE);
r->set_isolation_info(isolation_info1_);
r->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
EXPECT_TRUE(r->was_cached());
}
}
TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) {
ASSERT_TRUE(http_test_server()->Start());
GURL url_requiring_auth =
http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> r =
CreateFirstPartyRequest(default_context(), url_requiring_auth, &d);
r->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
EXPECT_TRUE(d.data_received().find("Cookie: got_challenged=true") !=
std::string::npos);
}
TEST_F(URLRequestTestHTTP, BasicAuthWithCredentialsWithCookies) {
ASSERT_TRUE(http_test_server()->Start());
GURL url_requiring_auth =
http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
GURL::Replacements replacements;
replacements.SetUsernameStr("user2");
replacements.SetPasswordStr("secret");
GURL url_with_identity = url_requiring_auth.ReplaceComponents(replacements);
TestDelegate d;
std::unique_ptr<URLRequest> r =
CreateFirstPartyRequest(default_context(), url_with_identity, &d);
r->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("user2/secret") != std::string::npos);
EXPECT_TRUE(d.data_received().find("Cookie: got_challenged=true") !=
std::string::npos);
}
TEST_F(URLRequestTestHTTP, BasicAuthWithCookiesCancelAuth) {
ASSERT_TRUE(http_test_server()->Start());
GURL url_requiring_auth =
http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
TestDelegate d;
EXPECT_TRUE(GetAllCookies(&default_context()).empty());
std::unique_ptr<URLRequest> r =
CreateFirstPartyRequest(default_context(), url_requiring_auth, &d);
r->Start();
d.RunUntilAuthRequired();
EXPECT_EQ(1, default_network_delegate().set_cookie_count());
CookieList cookies = GetAllCookies(&default_context());
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ("got_challenged", cookies[0].Name());
EXPECT_EQ("true", cookies[0].Value());
default_context().cookie_store()->DeleteAllAsync(
CookieStore::DeleteCallback());
r->CancelAuth();
d.RunUntilComplete();
ASSERT_TRUE(r->response_headers());
EXPECT_EQ(401, r->response_headers()->response_code());
EXPECT_TRUE(GetAllCookies(&default_context()).empty());
EXPECT_EQ(1, default_network_delegate().set_cookie_count());
}
TEST_F(URLRequestTestHTTP, IsolationInfoUpdatedOnRedirect) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
net::features::kSplitCacheByNetworkIsolationKey);
ASSERT_TRUE(http_test_server()->Start());
GURL redirect_url =
http_test_server()->GetURL("redirected.test", "/cachetime");
GURL original_url = http_test_server()->GetURL(
"original.test", "/server-redirect?" + redirect_url.spec());
url::Origin original_origin = url::Origin::Create(original_url);
url::Origin redirect_origin = url::Origin::Create(redirect_url);
IsolationInfo transient_isolation_info =
IsolationInfo::CreateTransient(std::nullopt);
const struct {
IsolationInfo info_before_redirect;
IsolationInfo expected_info_after_redirect;
} kTestCases[] = {
{IsolationInfo(), IsolationInfo()},
{IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame,
original_origin, original_origin,
SiteForCookies()),
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame,
redirect_origin, redirect_origin,
SiteForCookies::FromOrigin(redirect_origin))},
{IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame,
original_origin, original_origin,
SiteForCookies::FromOrigin(original_origin)),
IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame,
original_origin, redirect_origin,
SiteForCookies::FromOrigin(original_origin))},
{IsolationInfo::Create(IsolationInfo::RequestType::kOther,
original_origin, original_origin,
SiteForCookies()),
IsolationInfo::Create(IsolationInfo::RequestType::kOther,
original_origin, original_origin,
SiteForCookies())},
{transient_isolation_info, transient_isolation_info},
};
for (const auto& test_case : kTestCases) {
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info(test_case.expected_info_after_redirect);
r->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
}
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info(test_case.info_before_redirect);
r->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(redirect_url, r->url());
EXPECT_EQ(!test_case.expected_info_after_redirect.network_isolation_key()
.IsTransient(),
r->was_cached());
EXPECT_EQ(test_case.expected_info_after_redirect.request_type(),
r->isolation_info().request_type());
EXPECT_EQ(test_case.expected_info_after_redirect.top_frame_origin(),
r->isolation_info().top_frame_origin());
EXPECT_EQ(test_case.expected_info_after_redirect.frame_origin(),
r->isolation_info().frame_origin());
EXPECT_EQ(test_case.expected_info_after_redirect.network_isolation_key(),
r->isolation_info().network_isolation_key());
EXPECT_TRUE(test_case.expected_info_after_redirect.site_for_cookies()
.IsEquivalent(r->isolation_info().site_for_cookies()));
}
}
}
TEST_F(URLRequestTestHTTP, AuthWithNetworkAnonymizationKey) {
ASSERT_TRUE(http_test_server()->Start());
for (bool key_auth_cache_by_network_anonymization_key : {false, true}) {
auto context_builder = CreateTestURLRequestContextBuilder();
HttpNetworkSessionParams network_session_params;
network_session_params
.key_auth_cache_server_entries_by_network_anonymization_key =
key_auth_cache_by_network_anonymization_key;
context_builder->set_http_network_session_params(network_session_params);
auto context = context_builder->Build();
{
TestDelegate d;
GURL url(base::StringPrintf(
"http://%s:%s@%s/auth-basic", base::UTF16ToASCII(kUser).c_str(),
base::UTF16ToASCII(kSecret).c_str(),
http_test_server()->host_port_pair().ToString().c_str()));
std::unique_ptr<URLRequest> r(context->CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetLoadFlags(LOAD_BYPASS_CACHE);
r->set_isolation_info(isolation_info1_);
r->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
ASSERT_TRUE(r->response_headers());
EXPECT_EQ(200, r->response_headers()->response_code());
EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context->CreateRequest(
http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetLoadFlags(LOAD_BYPASS_CACHE);
r->set_isolation_info(isolation_info2_);
r->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
ASSERT_TRUE(r->response_headers());
if (key_auth_cache_by_network_anonymization_key) {
EXPECT_EQ(401, r->response_headers()->response_code());
} else {
EXPECT_EQ(200, r->response_headers()->response_code());
}
EXPECT_EQ(!key_auth_cache_by_network_anonymization_key,
d.data_received().find("user/secret") != std::string::npos);
}
}
}
TEST_F(URLRequestTestHTTP, EmbeddedAuthCredentialsRedacted) {
ASSERT_TRUE(http_test_server()->Start());
const std::string_view kUsername = "jiminy";
const std::string_view kPassword = "secret";
RecordingNetLogObserver redacted_net_log_observer(
NetLogCaptureMode::kDefault);
GURL url_without_credentials = http_test_server()->GetURL("/auth-basic");
GURL::Replacements replacements;
replacements.SetUsernameStr(kUsername);
replacements.SetPasswordStr(kPassword);
GURL url = url_without_credentials.ReplaceComponents(replacements);
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
ASSERT_TRUE(req->response_headers());
EXPECT_EQ(200, req->response_headers()->response_code());
EXPECT_GT(redacted_net_log_observer.GetSize(), 0u);
EXPECT_GT(net_log_observer_.GetSize(), 0u);
std::string url_with_redacted_credentials =
url_without_credentials.spec() + " (credentials redacted)";
std::string observed_redacted_json = redacted_net_log_observer.GetJson();
EXPECT_THAT(observed_redacted_json, Not(HasSubstr(url.spec())));
EXPECT_THAT(observed_redacted_json, HasSubstr(url_with_redacted_credentials));
EXPECT_THAT(observed_redacted_json, Not(HasSubstr(kUsername)));
EXPECT_THAT(observed_redacted_json, Not(HasSubstr(kPassword)));
std::string observed_json = net_log_observer_.GetJson();
EXPECT_NE(observed_json.find(url.spec()), std::string::npos);
EXPECT_EQ(observed_json.find(url_with_redacted_credentials),
std::string::npos);
}
TEST_F(URLRequestTest, ReportCookieActivity) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
RecordingNetLogObserver net_log_observer;
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<FilteringTestNetworkDelegate>());
network_delegate.SetCookieFilter("not_stored_cookie");
network_delegate.set_block_annotate_cookies();
context_builder->set_net_log(net::NetLog::Get());
auto context = context_builder->Build();
GURL set_cookie_test_url = test_server.GetURL(
"/set-cookie?not_stored_cookie=true"
"&stored_cookie=tasty"
"&path_cookie=narrow;path=/set-cookie"
"&partitioned_cookie=partitioned;path=/;partitioned;secure"
"&expired_cookie=N;expires=Mon,18-Apr-1977,22:50:13,GMT");
{
TestDelegate d;
std::unique_ptr<URLRequest> req =
CreateFirstPartyRequest(*context, set_cookie_test_url, &d);
req->Start();
d.RunUntilComplete();
ASSERT_EQ(5u, req->maybe_stored_cookies().size());
EXPECT_EQ("not_stored_cookie",
req->maybe_stored_cookies()[0].cookie->Name());
EXPECT_TRUE(req->maybe_stored_cookies()[0]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
EXPECT_EQ("stored_cookie", req->maybe_stored_cookies()[1].cookie->Name());
EXPECT_TRUE(
req->maybe_stored_cookies()[1].access_result.status.IsInclude());
EXPECT_EQ("stored_cookie", req->maybe_stored_cookies()[1].cookie->Name());
EXPECT_TRUE(
req->maybe_stored_cookies()[2].access_result.status.IsInclude());
EXPECT_EQ("path_cookie", req->maybe_stored_cookies()[2].cookie->Name());
EXPECT_TRUE(
req->maybe_stored_cookies()[3].access_result.status.IsInclude());
EXPECT_EQ("partitioned_cookie",
req->maybe_stored_cookies()[3].cookie->Name());
EXPECT_EQ("expired_cookie",
req->maybe_stored_cookies()[4].cookie->Name());
EXPECT_TRUE(
req->maybe_stored_cookies()[4].access_result.status.IsInclude());
auto entries = net_log_observer.GetEntriesWithType(
NetLogEventType::COOKIE_INCLUSION_STATUS);
EXPECT_EQ(5u, entries.size());
EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"not_stored_cookie","operation":"store",)x"
R"x("partition_key":"(none)","path":"/",)x"
R"x("status":"EXCLUDE_USER_PREFERENCES, )x"
R"x(DO_NOT_WARN, NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[0].params));
EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"stored_cookie","operation":"store",)x"
R"x("partition_key":"(none)","path":"/",)x"
R"x("status":"INCLUDE, DO_NOT_WARN, NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[1].params));
EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"path_cookie","operation":"store",)x"
R"x("partition_key":"(none)",)x"
R"x("path":"/set-cookie","status":"INCLUDE, DO_NOT_WARN, )x"
R"x(NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[2].params));
EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"partitioned_cookie","operation":"store",)x"
R"x("partition_key":")x" +
set_cookie_test_url.GetScheme() + "://" +
set_cookie_test_url.GetHost() +
", same-site"
R"x(","path":"/","status":"INCLUDE, DO_NOT_WARN, )x"
R"x(NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[3].params));
EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"expired_cookie","operation":"expire",)x"
R"x("partition_key":"(none)",)x"
R"x("path":"/","status":"INCLUDE, DO_NOT_WARN, )x"
R"x(NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[4].params));
net_log_observer.Clear();
}
{
TestDelegate d;
GURL test_url = test_server.GetURL("/echoheader?Cookie");
std::unique_ptr<URLRequest> req =
CreateFirstPartyRequest(*context, test_url, &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("stored_cookie=tasty") ==
std::string::npos);
ASSERT_EQ(3u, req->maybe_sent_cookies().size());
EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name());
EXPECT_TRUE(req->maybe_sent_cookies()[0]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_NOT_ON_PATH,
net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name());
EXPECT_TRUE(req->maybe_sent_cookies()[1]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
EXPECT_TRUE(req->maybe_sent_cookies()[2]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
auto entries = net_log_observer.GetEntriesWithType(
NetLogEventType::COOKIE_INCLUSION_STATUS);
EXPECT_EQ(3u, entries.size());
EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"path_cookie","operation":"send",)x"
R"x("partition_key":"(none)","path":)x"
R"x("/set-cookie","status":"EXCLUDE_NOT_ON_PATH, )x"
R"x(EXCLUDE_USER_PREFERENCES, DO_NOT_WARN, NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[0].params));
EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"stored_cookie","operation":"send",)x"
R"x("partition_key":"(none)","path":"/)x"
R"x(","status":"EXCLUDE_USER_PREFERENCES, DO_NOT_WARN, )x"
R"x(NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[1].params));
EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"partitioned_cookie","operation":"send",)x"
R"x("partition_key":")x" +
set_cookie_test_url.GetScheme() + "://" +
set_cookie_test_url.GetHost() +
", same-site"
R"x(","path":"/)x"
R"x(","status":"EXCLUDE_USER_PREFERENCES, DO_NOT_WARN, )x"
R"x(NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[2].params));
net_log_observer.Clear();
}
{
TestDelegate d;
net_log_observer.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
GURL test_url = test_server.GetURL("/echoheader?Cookie");
std::unique_ptr<URLRequest> req =
CreateFirstPartyRequest(*context, test_url, &d);
req->Start();
d.RunUntilComplete();
auto entries = net_log_observer.GetEntriesWithType(
NetLogEventType::COOKIE_INCLUSION_STATUS);
EXPECT_EQ(3u, entries.size());
EXPECT_EQ(R"x({"operation":"send","partition_key":"(none)",)x"
R"x("status":"EXCLUDE_NOT_ON_PATH, )x"
R"x(EXCLUDE_USER_PREFERENCES, DO_NOT_WARN, NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[0].params));
EXPECT_EQ(R"x({"operation":"send","partition_key":"(none)",)x"
R"x("status":"EXCLUDE_USER_PREFERENCES, )x"
R"x(DO_NOT_WARN, NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[1].params));
EXPECT_EQ(R"x({"operation":"send","partition_key":")x" +
set_cookie_test_url.GetScheme() + "://" +
set_cookie_test_url.GetHost() +
", same-site"
R"x(","status":"EXCLUDE_USER_PREFERENCES, )x"
R"x(DO_NOT_WARN, NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[2].params));
net_log_observer.Clear();
net_log_observer.SetObserverCaptureMode(
NetLogCaptureMode::kIncludeSensitive);
}
network_delegate.unset_block_annotate_cookies();
{
TestDelegate d;
GURL test_url = test_server.GetURL("/echoheader?Cookie");
std::unique_ptr<URLRequest> req =
CreateFirstPartyRequest(*context, test_url, &d);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("stored_cookie=tasty") !=
std::string::npos);
ASSERT_EQ(3u, req->maybe_sent_cookies().size());
EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name());
EXPECT_TRUE(req->maybe_sent_cookies()[0]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_NOT_ON_PATH}));
EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name());
EXPECT_TRUE(req->maybe_sent_cookies()[1].access_result.status.IsInclude());
auto entries = net_log_observer.GetEntriesWithType(
NetLogEventType::COOKIE_INCLUSION_STATUS);
EXPECT_EQ(3u, entries.size());
EXPECT_EQ(
"{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"path_cookie","operation":"send",)x"
R"x("partition_key":"(none)","path":"/)x"
R"x(set-cookie","status":"EXCLUDE_NOT_ON_PATH, DO_NOT_WARN, )x"
R"x(NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[0].params));
EXPECT_EQ(
"{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"stored_cookie","operation":"send",)x"
R"x("partition_key":"(none)",)x"
R"x("path":"/","status":"INCLUDE, DO_NOT_WARN, NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[1].params));
EXPECT_EQ(
"{\"domain\":\"" + set_cookie_test_url.GetHost() +
R"x(","name":"partitioned_cookie","operation":"send",)x"
R"x("partition_key":")x" +
set_cookie_test_url.GetScheme() + "://" +
set_cookie_test_url.GetHost() +
", same-site"
R"x(","path":"/","status":"INCLUDE, DO_NOT_WARN, NO_EXEMPTION"})x",
SerializeNetLogValueToJson(entries[2].params));
net_log_observer.Clear();
}
}
TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<FilteringTestNetworkDelegate>());
network_delegate.SetCookieFilter("blockeduserpreference");
context_builder->SetCookieStore(
std::make_unique<CookieMonster>(nullptr, nullptr));
auto context = context_builder->Build();
auto& cm = *static_cast<CookieMonster*>(context->cookie_store());
{
TestDelegate d;
GURL test_url = test_server.GetURL("this.example",
"/set-cookie?blockeduserpreference=true&"
"unspecifiedsamesite=1&"
"invalidsecure=1;Secure");
GURL cross_site_url = test_server.GetURL("other.example", "/");
std::unique_ptr<URLRequest> req(context->CreateRequest(
test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_site_for_cookies(
net::SiteForCookies::FromUrl(cross_site_url));
req->Start();
d.RunUntilComplete();
ASSERT_EQ(3u, req->maybe_stored_cookies().size());
EXPECT_EQ("blockeduserpreference",
req->maybe_stored_cookies()[0].cookie->Name());
EXPECT_TRUE(req->maybe_stored_cookies()[0]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
EXPECT_FALSE(
req->maybe_stored_cookies()[0].access_result.status.ShouldWarn());
EXPECT_EQ("unspecifiedsamesite",
req->maybe_stored_cookies()[1].cookie->Name());
EXPECT_TRUE(req->maybe_stored_cookies()[1]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
EXPECT_TRUE(req->maybe_stored_cookies()[1]
.access_result.status.HasExactlyWarningReasonsForTesting(
{CookieInclusionStatus::WarningReason::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
EXPECT_EQ("invalidsecure", req->maybe_stored_cookies()[2].cookie->Name());
EXPECT_TRUE(
req->maybe_stored_cookies()[2]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::EXCLUDE_SECURE_ONLY,
CookieInclusionStatus::ExclusionReason::
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
EXPECT_TRUE(req->maybe_stored_cookies()[2]
.access_result.status.HasExactlyWarningReasonsForTesting(
{CookieInclusionStatus::WarningReason::
WARN_TENTATIVELY_ALLOWING_SECURE_SOURCE_SCHEME}));
}
network_delegate.set_block_annotate_cookies();
{
GURL url = test_server.GetURL("/");
auto cookie1 = CanonicalCookie::CreateForTesting(url, "cookienosamesite=1",
base::Time::Now());
base::RunLoop run_loop;
CookieAccessResult access_result;
cm.SetCanonicalCookieAsync(
std::move(cookie1), url, CookieOptions::MakeAllInclusive(),
base::BindLambdaForTesting([&](CookieAccessResult result) {
access_result = result;
run_loop.Quit();
}));
run_loop.Run();
EXPECT_TRUE(access_result.status.IsInclude());
TestDelegate d;
GURL test_url = test_server.GetURL("/echoheader?Cookie");
std::unique_ptr<URLRequest> req(context->CreateRequest(
test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
GURL cross_site_url = test_server.GetURL("other.example", "/");
req->set_site_for_cookies(
net::SiteForCookies::FromUrl(cross_site_url));
req->Start();
d.RunUntilComplete();
EXPECT_EQ("None", d.data_received());
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]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES,
CookieInclusionStatus::ExclusionReason::
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
EXPECT_FALSE(
req->maybe_sent_cookies()[0].access_result.status.ShouldWarn());
}
network_delegate.unset_block_annotate_cookies();
{
GURL url = test_server.GetURL("/");
auto cookie2 = CanonicalCookie::CreateForTesting(
url, "cookiewithpath=1;path=/foo", base::Time::Now());
base::RunLoop run_loop;
CookieAccessResult access_result;
cm.SetCanonicalCookieAsync(
std::move(cookie2), url, CookieOptions::MakeAllInclusive(),
base::BindLambdaForTesting([&](CookieAccessResult result) {
access_result = result;
run_loop.Quit();
}));
run_loop.Run();
EXPECT_TRUE(access_result.status.IsInclude());
TestDelegate d;
GURL test_url = test_server.GetURL("/echoheader?Cookie");
std::unique_ptr<URLRequest> req(context->CreateRequest(
test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
GURL cross_site_url = test_server.GetURL("other.example", "/");
req->set_site_for_cookies(
net::SiteForCookies::FromUrl(cross_site_url));
req->Start();
d.RunUntilComplete();
EXPECT_EQ("None", d.data_received());
ASSERT_EQ(2u, req->maybe_sent_cookies().size());
EXPECT_EQ("cookiewithpath", req->maybe_sent_cookies()[0].cookie.Name());
EXPECT_TRUE(
req->maybe_sent_cookies()[0]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::EXCLUDE_NOT_ON_PATH,
CookieInclusionStatus::ExclusionReason::
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
EXPECT_FALSE(
req->maybe_sent_cookies()[0].access_result.status.ShouldWarn());
EXPECT_EQ("cookienosamesite", req->maybe_sent_cookies()[1].cookie.Name());
EXPECT_TRUE(req->maybe_sent_cookies()[1]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::ExclusionReason::
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
EXPECT_TRUE(req->maybe_sent_cookies()[1]
.access_result.status.HasExactlyWarningReasonsForTesting(
{CookieInclusionStatus::WarningReason::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
}
}
TEST_F(URLRequestTestHTTP, AuthChallengeCancelCookieCollect) {
ASSERT_TRUE(http_test_server()->Start());
GURL url_requiring_auth =
http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
auto context_builder = CreateTestURLRequestContextBuilder();
auto filtering_network_delegate =
std::make_unique<FilteringTestNetworkDelegate>();
filtering_network_delegate->SetCookieFilter("got_challenged");
context_builder->set_network_delegate(std::move(filtering_network_delegate));
auto context = context_builder->Build();
TestDelegate delegate;
std::unique_ptr<URLRequest> request =
CreateFirstPartyRequest(*context, url_requiring_auth, &delegate);
request->Start();
delegate.RunUntilAuthRequired();
ASSERT_EQ(1u, request->maybe_stored_cookies().size());
EXPECT_TRUE(request->maybe_stored_cookies()[0]
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
EXPECT_EQ("got_challenged=true",
request->maybe_stored_cookies()[0].cookie_string);
request->CancelAuth();
delegate.RunUntilComplete();
}
TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) {
ASSERT_TRUE(http_test_server()->Start());
GURL url_requiring_auth =
http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
GURL url_requiring_auth_wo_cookies =
http_test_server()->GetURL("/auth-basic");
{
auto context_builder = CreateTestURLRequestContextBuilder();
auto& filtering_network_delegate = *context_builder->set_network_delegate(
std::make_unique<FilteringTestNetworkDelegate>());
filtering_network_delegate.SetCookieFilter("got_challenged");
auto context = context_builder->Build();
TestDelegate delegate;
std::unique_ptr<URLRequest> request =
CreateFirstPartyRequest(*context, url_requiring_auth, &delegate);
request->Start();
delegate.RunUntilAuthRequired();
EXPECT_EQ(1, filtering_network_delegate.blocked_set_cookie_count());
ASSERT_EQ(1u, request->maybe_stored_cookies().size());
EXPECT_TRUE(request->maybe_stored_cookies()
.front()
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
request->SetAuth(AuthCredentials(kUser, kSecret));
delegate.RunUntilComplete();
EXPECT_THAT(delegate.request_status(), IsOk());
EXPECT_EQ(std::string::npos,
delegate.data_received().find("Cookie: got_challenged=true"));
ASSERT_EQ(0u, request->maybe_stored_cookies().size());
}
{
auto context_builder = CreateTestURLRequestContextBuilder();
auto& filtering_network_delegate = *context_builder->set_network_delegate(
std::make_unique<FilteringTestNetworkDelegate>());
filtering_network_delegate.set_block_annotate_cookies();
context_builder->SetCookieStore(
std::make_unique<CookieMonster>(nullptr, nullptr));
auto context = context_builder->Build();
auto* cm = static_cast<CookieMonster*>(context->cookie_store());
auto another_cookie = CanonicalCookie::CreateForTesting(
url_requiring_auth_wo_cookies, "another_cookie=true",
base::Time::Now());
cm->SetCanonicalCookieAsync(std::move(another_cookie),
url_requiring_auth_wo_cookies,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
TestDelegate delegate;
std::unique_ptr<URLRequest> request = CreateFirstPartyRequest(
*context, url_requiring_auth_wo_cookies, &delegate);
request->Start();
delegate.RunUntilAuthRequired();
ASSERT_EQ(1u, request->maybe_sent_cookies().size());
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()
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
request->set_maybe_sent_cookies({});
cm->DeleteAllAsync(CookieStore::DeleteCallback());
auto one_more_cookie = CanonicalCookie::CreateForTesting(
url_requiring_auth_wo_cookies, "one_more_cookie=true",
base::Time::Now());
cm->SetCanonicalCookieAsync(std::move(one_more_cookie),
url_requiring_auth_wo_cookies,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
request->SetAuth(AuthCredentials(kUser, kSecret));
delegate.RunUntilComplete();
EXPECT_THAT(delegate.request_status(), IsOk());
EXPECT_EQ(std::string::npos,
delegate.data_received().find("Cookie: one_more_cookie=true"));
EXPECT_EQ(2, filtering_network_delegate.blocked_annotate_cookies_count());
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()
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
}
}
TEST_F(URLRequestTestHTTP, BasicAuthLoadTiming) {
ASSERT_TRUE(http_test_server()->Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info(isolation_info1_);
r->Start();
d.RunUntilAuthRequired();
LoadTimingInfo load_timing_info_before_auth;
r->GetLoadTimingInfo(&load_timing_info_before_auth);
TestLoadTimingNotReused(load_timing_info_before_auth,
CONNECT_TIMING_HAS_DNS_TIMES);
r->SetAuth(AuthCredentials(kUser, kSecret));
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
LoadTimingInfo load_timing_info;
r->GetLoadTimingInfo(&load_timing_info);
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
EXPECT_NE(load_timing_info_before_auth.socket_log_id,
load_timing_info.socket_log_id);
EXPECT_LE(load_timing_info_before_auth.receive_headers_end,
load_timing_info.connect_timing.connect_start);
}
{
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetLoadFlags(LOAD_VALIDATE_CACHE);
r->set_isolation_info(isolation_info1_);
r->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
EXPECT_TRUE(r->was_cached());
LoadTimingInfo load_timing_info;
r->GetLoadTimingInfo(&load_timing_info);
TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
}
}
TEST_F(URLRequestTestHTTP, Post302RedirectGet) {
ASSERT_TRUE(http_test_server()->Start());
const char kData[] = "hello world";
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/redirect-to-echoall"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_method("POST");
req->set_upload(CreateSimpleUploadData(base::byte_span_from_cstring(kData)));
HttpRequestHeaders headers;
headers.SetHeader("Content-Type",
"multipart/form-data;"
"boundary=----WebKitFormBoundaryAADeAA+NAAWMAAwZ");
headers.SetHeader("Accept",
"text/xml,application/xml,application/xhtml+xml,"
"text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
headers.SetHeader("Accept-Language", "en-US,en");
headers.SetHeader("Accept-Charset", "ISO-8859-1,*,utf-8");
headers.SetHeader("Content-Length", "11");
headers.SetHeader("Origin", "http://localhost:1337/");
req->SetExtraRequestHeaders(headers);
req->Start();
d.RunUntilComplete();
std::string mime_type;
req->GetMimeType(&mime_type);
EXPECT_EQ("text/html", mime_type);
const std::string& data = d.data_received();
EXPECT_FALSE(ContainsString(data, "Content-Length:"));
EXPECT_FALSE(ContainsString(data, "Content-Type:"));
EXPECT_FALSE(ContainsString(data, "Origin:"));
EXPECT_TRUE(ContainsString(data, "Accept:"));
EXPECT_TRUE(ContainsString(data, "Accept-Language:"));
EXPECT_TRUE(ContainsString(data, "Accept-Charset:"));
}
TEST_F(URLRequestTestHTTP, Redirect301Tests) {
ASSERT_TRUE(http_test_server()->Start());
const GURL url = http_test_server()->GetURL("/redirect301-to-echo");
const GURL https_redirect_url =
http_test_server()->GetURL("/redirect301-to-https");
HTTPRedirectMethodTest(url, "POST", "GET", true);
HTTPRedirectMethodTest(url, "PUT", "PUT", true);
HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
HTTPRedirectOriginHeaderTest(url, "GET", "GET",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string());
HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET",
std::string());
HTTPRedirectOriginHeaderTest(url, "PUT", "PUT",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "PUT", "null");
}
TEST_F(URLRequestTestHTTP, Redirect302Tests) {
ASSERT_TRUE(http_test_server()->Start());
const GURL url = http_test_server()->GetURL("/redirect302-to-echo");
const GURL https_redirect_url =
http_test_server()->GetURL("/redirect302-to-https");
HTTPRedirectMethodTest(url, "POST", "GET", true);
HTTPRedirectMethodTest(url, "PUT", "PUT", true);
HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
HTTPRedirectOriginHeaderTest(url, "GET", "GET",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string());
HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET",
std::string());
HTTPRedirectOriginHeaderTest(url, "PUT", "PUT",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "PUT", "null");
}
TEST_F(URLRequestTestHTTP, Redirect303Tests) {
ASSERT_TRUE(http_test_server()->Start());
const GURL url = http_test_server()->GetURL("/redirect303-to-echo");
const GURL https_redirect_url =
http_test_server()->GetURL("/redirect303-to-https");
HTTPRedirectMethodTest(url, "POST", "GET", true);
HTTPRedirectMethodTest(url, "PUT", "GET", true);
HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
HTTPRedirectOriginHeaderTest(url, "DELETE", "GET", std::string());
HTTPRedirectOriginHeaderTest(https_redirect_url, "DELETE", "GET",
std::string());
HTTPRedirectOriginHeaderTest(url, "GET", "GET",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
HTTPRedirectOriginHeaderTest(url, "HEAD", "HEAD",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "HEAD", "HEAD", "null");
HTTPRedirectOriginHeaderTest(url, "OPTIONS", "GET", std::string());
HTTPRedirectOriginHeaderTest(https_redirect_url, "OPTIONS", "GET",
std::string());
HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string());
HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET",
std::string());
HTTPRedirectOriginHeaderTest(url, "PUT", "GET", std::string());
HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "GET", std::string());
}
TEST_F(URLRequestTestHTTP, Redirect307Tests) {
ASSERT_TRUE(http_test_server()->Start());
const GURL url = http_test_server()->GetURL("/redirect307-to-echo");
const GURL https_redirect_url =
http_test_server()->GetURL("/redirect307-to-https");
HTTPRedirectMethodTest(url, "POST", "POST", true);
HTTPRedirectMethodTest(url, "PUT", "PUT", true);
HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
HTTPRedirectOriginHeaderTest(url, "GET", "GET",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
HTTPRedirectOriginHeaderTest(url, "POST", "POST",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "POST", "null");
HTTPRedirectOriginHeaderTest(url, "PUT", "PUT",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "PUT", "null");
}
TEST_F(URLRequestTestHTTP, Redirect308Tests) {
ASSERT_TRUE(http_test_server()->Start());
const GURL url = http_test_server()->GetURL("/redirect308-to-echo");
const GURL https_redirect_url =
http_test_server()->GetURL("/redirect308-to-https");
HTTPRedirectMethodTest(url, "POST", "POST", true);
HTTPRedirectMethodTest(url, "PUT", "PUT", true);
HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
HTTPRedirectOriginHeaderTest(url, "GET", "GET",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
HTTPRedirectOriginHeaderTest(url, "POST", "POST",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "POST", "null");
HTTPRedirectOriginHeaderTest(url, "PUT", "PUT",
url.DeprecatedGetOriginAsURL().spec());
HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "PUT", "null");
}
TEST_F(URLRequestTestHTTP, NoRedirectOn308WithoutLocationHeader) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
const GURL url = http_test_server()->GetURL("/308-without-location-header");
std::unique_ptr<URLRequest> request(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(0, d.received_redirect_count());
EXPECT_EQ(308, request->response_headers()->response_code());
EXPECT_EQ("This is not a redirect.", d.data_received());
}
TEST_F(URLRequestTestHTTP, Redirect302PreserveReferenceFragment) {
ASSERT_TRUE(http_test_server()->Start());
GURL original_url(
http_test_server()->GetURL("/redirect302-to-echo#fragment"));
GURL expected_url(http_test_server()->GetURL("/echo#fragment"));
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(original_url, r->original_url());
EXPECT_EQ(expected_url, r->url());
}
TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) {
ASSERT_TRUE(http_test_server()->Start());
GURL redirect_to(
http_test_server()->GetURL("/set-cookie?server-redirect=other"));
GURL original_url(http_test_server()->GetURL("/server-redirect-with-cookie?" +
redirect_to.spec()));
GURL original_url_wo_cookie(
http_test_server()->GetURL("/server-redirect?" + redirect_to.spec()));
{
auto context_builder = CreateTestURLRequestContextBuilder();
auto& filtering_network_delegate = *context_builder->set_network_delegate(
std::make_unique<FilteringTestNetworkDelegate>());
filtering_network_delegate.SetCookieFilter(
"server-redirect");
auto context = context_builder->Build();
TestDelegate delegate;
std::unique_ptr<URLRequest> request =
CreateFirstPartyRequest(*context, original_url, &delegate);
request->Start();
delegate.RunUntilRedirect();
EXPECT_EQ(1, filtering_network_delegate.blocked_set_cookie_count());
ASSERT_EQ(1u, request->maybe_stored_cookies().size());
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()
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
request->FollowDeferredRedirect(std::nullopt, std::nullopt);
delegate.RunUntilComplete();
EXPECT_THAT(delegate.request_status(), IsOk());
EXPECT_EQ(2, filtering_network_delegate.blocked_set_cookie_count());
ASSERT_EQ(1u, request->maybe_stored_cookies().size());
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()
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
}
{
auto context_builder = CreateTestURLRequestContextBuilder();
auto& filtering_network_delegate = *context_builder->set_network_delegate(
std::make_unique<FilteringTestNetworkDelegate>());
filtering_network_delegate.set_block_annotate_cookies();
context_builder->SetCookieStore(
std::make_unique<CookieMonster>(nullptr, nullptr));
auto context = context_builder->Build();
auto* cm = static_cast<CookieMonster*>(context->cookie_store());
auto another_cookie = CanonicalCookie::CreateForTesting(
original_url, "another_cookie=true", base::Time::Now());
cm->SetCanonicalCookieAsync(std::move(another_cookie), original_url,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
TestDelegate delegate;
std::unique_ptr<URLRequest> request =
CreateFirstPartyRequest(*context, original_url_wo_cookie, &delegate);
request->Start();
delegate.RunUntilRedirect();
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()
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
request->set_maybe_sent_cookies({});
cm->DeleteAllAsync(CookieStore::DeleteCallback());
auto one_more_cookie = CanonicalCookie::CreateForTesting(
original_url_wo_cookie, "one_more_cookie=true", base::Time::Now());
cm->SetCanonicalCookieAsync(std::move(one_more_cookie),
original_url_wo_cookie,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
request->FollowDeferredRedirect(std::nullopt, std::nullopt);
delegate.RunUntilComplete();
EXPECT_THAT(delegate.request_status(), IsOk());
EXPECT_EQ(2, filtering_network_delegate.blocked_annotate_cookies_count());
ASSERT_EQ(1u, request->maybe_sent_cookies().size());
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()
.access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::ExclusionReason::
EXCLUDE_USER_PREFERENCES}));
}
}
TEST_F(URLRequestTestHTTP, RedirectPreserveFirstPartyURL) {
ASSERT_TRUE(http_test_server()->Start());
GURL url(http_test_server()->GetURL("/redirect302-to-echo"));
GURL first_party_url("http://example.com");
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_site_for_cookies(SiteForCookies::FromUrl(first_party_url));
r->Start();
d.RunUntilComplete();
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(OK, d.request_status());
EXPECT_TRUE(SiteForCookies::FromUrl(first_party_url)
.IsEquivalent(r->site_for_cookies()));
}
TEST_F(URLRequestTestHTTP, RedirectUpdateFirstPartyURL) {
ASSERT_TRUE(http_test_server()->Start());
GURL url(http_test_server()->GetURL("/redirect302-to-echo"));
GURL original_first_party_url("http://example.com");
GURL expected_first_party_url(http_test_server()->GetURL("/echo"));
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_site_for_cookies(SiteForCookies::FromUrl(original_first_party_url));
r->set_first_party_url_policy(
RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
r->Start();
d.RunUntilComplete();
EXPECT_EQ(2U, r->url_chain().size());
EXPECT_EQ(OK, d.request_status());
EXPECT_TRUE(SiteForCookies::FromUrl(expected_first_party_url)
.IsEquivalent(r->site_for_cookies()));
}
TEST_F(URLRequestTestHTTP, InterceptPost302RedirectGet) {
ASSERT_TRUE(http_test_server()->Start());
const char kData[] = "hello world";
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_method("POST");
req->set_upload(CreateSimpleUploadData(base::byte_span_from_cstring(kData)));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kContentLength,
base::NumberToString(std::size(kData) - 1));
req->SetExtraRequestHeaders(headers);
std::unique_ptr<URLRequestRedirectJob> job =
std::make_unique<URLRequestRedirectJob>(
req.get(), http_test_server()->GetURL("/echo"),
RedirectUtil::ResponseCode::REDIRECT_302_FOUND, "Very Good Reason");
TestScopedURLInterceptor interceptor(req->url(), std::move(job));
req->Start();
d.RunUntilComplete();
EXPECT_EQ("GET", req->method());
}
TEST_F(URLRequestTestHTTP, InterceptPost307RedirectPost) {
ASSERT_TRUE(http_test_server()->Start());
const char kData[] = "hello world";
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_method("POST");
req->set_upload(CreateSimpleUploadData(base::byte_span_from_cstring(kData)));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kContentLength,
base::NumberToString(std::size(kData) - 1));
req->SetExtraRequestHeaders(headers);
std::unique_ptr<URLRequestRedirectJob> job =
std::make_unique<URLRequestRedirectJob>(
req.get(), http_test_server()->GetURL("/echo"),
RedirectUtil::ResponseCode::REDIRECT_307_TEMPORARY_REDIRECT,
"Very Good Reason");
TestScopedURLInterceptor interceptor(req->url(), std::move(job));
req->Start();
d.RunUntilComplete();
EXPECT_EQ("POST", req->method());
EXPECT_EQ(kData, d.data_received());
}
TEST_F(URLRequestTestHTTP, DefaultAcceptLanguage) {
ASSERT_TRUE(http_test_server()->Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_http_user_agent_settings(
std::make_unique<StaticHttpUserAgentSettings>("en", "test-ua"));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server()->GetURL("/echoheader?Accept-Language"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ("en", d.data_received());
}
TEST_F(URLRequestTestHTTP, EmptyAcceptLanguage) {
ASSERT_TRUE(http_test_server()->Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_http_user_agent_settings(
std::make_unique<StaticHttpUserAgentSettings>(std::string(), "test-ua"));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server()->GetURL("/echoheader?Accept-Language"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ("None", d.data_received());
}
TEST_F(URLRequestTestHTTP, OverrideAcceptLanguage) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Accept-Language"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kAcceptLanguage, "ru");
req->SetExtraRequestHeaders(headers);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string("ru"), d.data_received());
}
TEST_F(URLRequestTestHTTP, DefaultAcceptEncoding) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Accept-Encoding"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
req->SetExtraRequestHeaders(headers);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(ContainsString(d.data_received(), "gzip"));
}
TEST_F(URLRequestTestHTTP, DefaultAcceptEncodingOverridden) {
ASSERT_TRUE(http_test_server()->Start());
struct {
base::flat_set<SourceStreamType> accepted_types;
const char* expected_accept_encoding;
} tests[] = {
{{SourceStreamType::kDeflate}, "deflate"},
{{}, "None"},
{{SourceStreamType::kGzip}, "gzip"},
{{SourceStreamType::kGzip, SourceStreamType::kDeflate}, "gzip, deflate"}};
for (auto test : tests) {
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Accept-Encoding"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_accepted_stream_types(test.accepted_types);
req->Start();
d.RunUntilComplete();
EXPECT_STRCASEEQ(d.data_received().c_str(), test.expected_accept_encoding);
}
}
TEST_F(URLRequestTestHTTP, OverrideAcceptEncoding) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Accept-Encoding"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kAcceptEncoding, "identity");
req->SetExtraRequestHeaders(headers);
req->Start();
d.RunUntilComplete();
EXPECT_FALSE(ContainsString(d.data_received(), "gzip"));
EXPECT_TRUE(ContainsString(d.data_received(), "identity"));
}
TEST_F(URLRequestTestHTTP, SetAcceptCharset) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?Accept-Charset"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kAcceptCharset, "koi-8r");
req->SetExtraRequestHeaders(headers);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string("koi-8r"), d.data_received());
}
TEST_F(URLRequestTestHTTP, DefaultUserAgent) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(default_context().http_user_agent_settings()->GetUserAgent(),
d.data_received());
}
TEST_F(URLRequestTestHTTP, OverrideUserAgent) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY,
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kUserAgent, "Lynx (textmode)");
req->SetExtraRequestHeaders(headers);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(std::string("Lynx (textmode)"), d.data_received());
}
TEST_F(URLRequestTestHTTP, EmptyHttpUserAgentSettings) {
ASSERT_TRUE(http_test_server()->Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_http_user_agent_settings(nullptr);
auto context = context_builder->Build();
struct {
const char* request;
const char* expected_response;
} tests[] = {{"/echoheader?Accept-Language", "None"},
{"/echoheader?Accept-Charset", "None"},
{"/echoheader?User-Agent", ""}};
for (const auto& test : tests) {
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server()->GetURL(test.request), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(test.expected_response, d.data_received())
<< " Request = \"" << test.request << "\"";
}
}
TEST_F(URLRequestTestHTTP, SetSubsequentJobPriority) {
GURL initial_url("http://foo.test/");
GURL redirect_url("http://bar.test/");
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
initial_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_EQ(DEFAULT_PRIORITY, req->priority());
std::unique_ptr<URLRequestRedirectJob> redirect_job =
std::make_unique<URLRequestRedirectJob>(
req.get(), redirect_url,
RedirectUtil::ResponseCode::REDIRECT_302_FOUND, "Very Good Reason");
auto interceptor = std::make_unique<TestScopedURLInterceptor>(
initial_url, std::move(redirect_job));
req->SetPriority(LOW);
req->Start();
EXPECT_TRUE(req->is_pending());
d.RunUntilRedirect();
interceptor.reset();
RequestPriority job_priority;
std::unique_ptr<URLRequestJob> job =
std::make_unique<PriorityMonitoringURLRequestJob>(req.get(),
&job_priority);
interceptor =
std::make_unique<TestScopedURLInterceptor>(redirect_url, std::move(job));
req->FollowDeferredRedirect(std::nullopt ,
std::nullopt );
d.RunUntilComplete();
EXPECT_EQ(LOW, job_priority);
}
TEST_F(URLRequestTestHTTP, NetworkSuspendTest) {
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetWrapHttpNetworkLayerCallback(
base::BindOnce([](std::unique_ptr<HttpNetworkLayer> network_layer) {
network_layer->GetSession()->OnSuspend();
std::unique_ptr<HttpTransactionFactory> factory =
std::make_unique<HttpCache>(std::move(network_layer),
HttpCache::DefaultBackend::InMemory(0),
nullptr);
return factory;
}));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(GURL("http://127.0.0.1/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(d.request_failed());
EXPECT_EQ(ERR_NETWORK_IO_SUSPENDED, d.request_status());
}
TEST_F(URLRequestTestHTTP, NetworkAccessedSetOnNetworkRequest) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
GURL test_url(http_test_server()->GetURL("/"));
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(req->response_info().network_accessed);
}
TEST_F(URLRequestTestHTTP, NetworkAccessedClearOnCachedResponse) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(isolation_info1_);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_TRUE(req->response_info().network_accessed);
EXPECT_FALSE(req->response_info().was_cached);
req = default_context().CreateRequest(
http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS);
req->set_isolation_info(isolation_info1_);
req->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_FALSE(req->response_info().network_accessed);
EXPECT_TRUE(req->response_info().was_cached);
}
TEST_F(URLRequestTestHTTP, NetworkAccessedClearOnLoadOnlyFromCache) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
GURL test_url(http_test_server()->GetURL("/"));
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->SetLoadFlags(LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION);
req->Start();
d.RunUntilComplete();
EXPECT_FALSE(req->response_info().network_accessed);
}
TEST_F(URLRequestTestHTTP, ThrottledPriority) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
GURL test_url(http_test_server()->GetURL("/"));
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
test_url, THROTTLED, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
}
TEST_F(URLRequestTestHTTP, RawBodyBytesNoContentEncoding) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/simple.html"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(5, req->GetRawBodyBytes());
}
TEST_F(URLRequestTestHTTP, RawBodyBytesGzipEncoding) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/gzip-encoded"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(30, req->GetRawBodyBytes());
}
TEST_F(URLRequestTestHTTP, TesBeforeStartTransactionFails) {
ASSERT_TRUE(http_test_server()->Start());
default_network_delegate().set_before_start_transaction_fails();
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
DCHECK(!d.response_completed());
d.RunUntilComplete();
DCHECK(d.response_completed());
EXPECT_EQ(ERR_FAILED, d.request_status());
}
class URLRequestTestReferrerPolicy : public URLRequestTest {
public:
URLRequestTestReferrerPolicy() = default;
void InstantiateSameOriginServers(net::EmbeddedTestServer::Type type) {
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_ = std::make_unique<EmbeddedTestServer>(origin_type);
RegisterDefaultHandlers(origin_server_.get());
ASSERT_TRUE(origin_server_->Start());
destination_server_ = std::make_unique<EmbeddedTestServer>(dest_type);
RegisterDefaultHandlers(destination_server_.get());
ASSERT_TRUE(destination_server_->Start());
}
void VerifyReferrerAfterRedirect(ReferrerPolicy policy,
const GURL& referrer,
const GURL& expected) {
GURL destination_url =
destination_server_ ? destination_server_->GetURL("/echoheader?Referer")
: origin_server_->GetURL("/echoheader?Referer");
GURL origin_url =
origin_server_->GetURL("/server-redirect?" + destination_url.spec());
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
origin_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_referrer_policy(policy);
req->SetReferrer(referrer.spec());
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(1, d.received_redirect_count());
EXPECT_EQ(destination_url, req->url());
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(200, req->response_headers()->response_code());
EXPECT_EQ(expected.spec(), req->referrer());
if (expected.is_empty())
EXPECT_EQ("None", d.data_received());
else
EXPECT_EQ(expected.spec(), d.data_received());
}
EmbeddedTestServer* origin_server() const { return origin_server_.get(); }
private:
std::unique_ptr<EmbeddedTestServer> origin_server_;
std::unique_ptr<EmbeddedTestServer> destination_server_;
};
TEST_F(URLRequestTestReferrerPolicy, HTTPToSameOriginHTTP) {
InstantiateSameOriginServers(net::EmbeddedTestServer::TYPE_HTTP);
GURL referrer = origin_server()->GetURL("/path/to/file.html");
VerifyReferrerAfterRedirect(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
referrer);
VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
referrer.DeprecatedGetOriginAsURL(),
referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
referrer, referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
}
TEST_F(URLRequestTestReferrerPolicy, HTTPToCrossOriginHTTP) {
InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTP,
net::EmbeddedTestServer::TYPE_HTTP);
GURL referrer = origin_server()->GetURL("/path/to/file.html");
VerifyReferrerAfterRedirect(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
referrer.DeprecatedGetOriginAsURL(),
referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
referrer, GURL());
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
}
TEST_F(URLRequestTestReferrerPolicy, HTTPSToSameOriginHTTPS) {
InstantiateSameOriginServers(net::EmbeddedTestServer::TYPE_HTTPS);
GURL referrer = origin_server()->GetURL("/path/to/file.html");
VerifyReferrerAfterRedirect(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
referrer);
VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
referrer.DeprecatedGetOriginAsURL(),
referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
referrer, referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
}
TEST_F(URLRequestTestReferrerPolicy, HTTPSToCrossOriginHTTPS) {
InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTPS,
net::EmbeddedTestServer::TYPE_HTTPS);
GURL referrer = origin_server()->GetURL("/path/to/file.html");
VerifyReferrerAfterRedirect(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
origin_server()->GetURL("/"));
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
origin_server()->GetURL("/"));
VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
referrer.DeprecatedGetOriginAsURL(),
referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
referrer, GURL());
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
}
TEST_F(URLRequestTestReferrerPolicy, HTTPToHTTPS) {
InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTP,
net::EmbeddedTestServer::TYPE_HTTPS);
GURL referrer = origin_server()->GetURL("/path/to/file.html");
VerifyReferrerAfterRedirect(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
referrer);
VerifyReferrerAfterRedirect(
ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
origin_server()->GetURL("/"));
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
origin_server()->GetURL("/"));
VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
referrer.DeprecatedGetOriginAsURL(),
referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
referrer, GURL());
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
}
TEST_F(URLRequestTestReferrerPolicy, HTTPSToHTTP) {
InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTPS,
net::EmbeddedTestServer::TYPE_HTTP);
GURL referrer = origin_server()->GetURL("/path/to/file.html");
VerifyReferrerAfterRedirect(
ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
GURL());
VerifyReferrerAfterRedirect(
ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
GURL());
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
origin_server()->GetURL("/"));
VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
referrer.DeprecatedGetOriginAsURL(),
referrer.DeprecatedGetOriginAsURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
referrer, GURL());
VerifyReferrerAfterRedirect(
ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
referrer.DeprecatedGetOriginAsURL(), GURL());
VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
}
class HTTPSRequestTest : public TestWithTaskEnvironment {
public:
HTTPSRequestTest() {
auto context_builder = CreateTestURLRequestContextBuilder();
default_context_ = context_builder->Build();
}
~HTTPSRequestTest() override {
SetTransportSecurityStateSourceForTesting(nullptr);
}
URLRequestContext& default_context() { return *default_context_; }
private:
std::unique_ptr<URLRequestContext> default_context_;
};
TEST_F(HTTPSRequestTest, HTTPSGetTest) {
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
TestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
CheckSSLInfo(r->ssl_info());
EXPECT_EQ(test_server.host_port_pair().host(),
r->GetResponseRemoteEndpoint().ToStringWithoutPort());
EXPECT_EQ(test_server.host_port_pair().port(),
r->GetResponseRemoteEndpoint().port());
}
}
TEST_F(HTTPSRequestTest, HTTPSMismatchedTest) {
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
bool err_allowed = true;
for (int i = 0; i < 2; i++, err_allowed = !err_allowed) {
TestDelegate d;
{
d.set_allow_certificate_errors(err_allowed);
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_TRUE(d.have_certificate_errors());
if (err_allowed) {
EXPECT_NE(0, d.bytes_received());
CheckSSLInfo(r->ssl_info());
} else {
EXPECT_EQ(0, d.bytes_received());
}
}
}
}
TEST_F(HTTPSRequestTest, HTTPSExpiredTest) {
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
bool err_allowed = false;
for (int i = 0; i < 2; i++, err_allowed = !err_allowed) {
TestDelegate d;
{
d.set_allow_certificate_errors(err_allowed);
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_TRUE(d.have_certificate_errors());
if (err_allowed) {
EXPECT_NE(0, d.bytes_received());
CheckSSLInfo(r->ssl_info());
} else {
EXPECT_EQ(0, d.bytes_received());
}
}
}
}
class SSLNetErrorTestDelegate : public TestDelegate {
public:
void OnSSLCertificateError(URLRequest* request,
int net_error,
const SSLInfo& ssl_info,
bool fatal) override {
net_error_ = net_error;
on_ssl_certificate_error_called_ = true;
TestDelegate::OnSSLCertificateError(request, net_error, ssl_info, fatal);
}
bool on_ssl_certificate_error_called() {
return on_ssl_certificate_error_called_;
}
int net_error() { return net_error_; }
private:
bool on_ssl_certificate_error_called_ = false;
int net_error_ = net::OK;
};
TEST_F(HTTPSRequestTest, SSLNetErrorReportedToDelegate) {
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
SSLNetErrorTestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_TRUE(d.on_ssl_certificate_error_called());
EXPECT_EQ(net::ERR_CERT_DATE_INVALID, d.net_error());
}
#if !BUILDFLAG(IS_IOS)
TEST_F(HTTPSRequestTest, HTTPSPreloadedHSTSTest) {
SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
test_server.ServeFilesFromSourceDirectory("net/data/ssl");
ASSERT_TRUE(test_server.Start());
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddRule("hsts-hpkp-preloaded.test",
test_server.GetIPLiteralString());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::move(host_resolver));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> r(context->CreateRequest(
GURL(base::StringPrintf("https://hsts-hpkp-preloaded.test:%d",
test_server.host_port_pair().port())),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_TRUE(d.have_certificate_errors());
EXPECT_TRUE(d.certificate_errors_are_fatal());
}
TEST_F(HTTPSRequestTest, HTTPSErrorsNoClobberTSSTest) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(
net::features::kStaticKeyPinningEnforcement);
SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
test_server.ServeFilesFromSourceDirectory("net/data/ssl");
ASSERT_TRUE(test_server.Start());
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddRule("hsts-hpkp-preloaded.test",
test_server.GetIPLiteralString());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::move(host_resolver));
auto context = context_builder->Build();
ASSERT_TRUE(context->transport_security_state());
TransportSecurityState& transport_security_state =
*context->transport_security_state();
transport_security_state.EnableStaticPinsForTesting();
transport_security_state.SetPinningListAlwaysTimelyForTesting(true);
TransportSecurityState::STSState static_sts_state;
TransportSecurityState::PKPState static_pkp_state;
EXPECT_TRUE(transport_security_state.GetStaticSTSState(
"hsts-hpkp-preloaded.test", &static_sts_state));
EXPECT_TRUE(transport_security_state.GetStaticPKPState(
"hsts-hpkp-preloaded.test", &static_pkp_state));
TransportSecurityState::STSState dynamic_sts_state;
TransportSecurityState::PKPState dynamic_pkp_state;
EXPECT_FALSE(transport_security_state.GetDynamicSTSState(
"hsts-hpkp-preloaded.test", &dynamic_sts_state));
EXPECT_FALSE(transport_security_state.GetDynamicPKPState(
"hsts-hpkp-preloaded.test", &dynamic_pkp_state));
TestDelegate d;
std::unique_ptr<URLRequest> r(context->CreateRequest(
GURL(base::StringPrintf("https://hsts-hpkp-preloaded.test:%d",
test_server.host_port_pair().port())),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_TRUE(d.have_certificate_errors());
EXPECT_TRUE(d.certificate_errors_are_fatal());
TransportSecurityState::STSState new_static_sts_state;
TransportSecurityState::PKPState new_static_pkp_state;
EXPECT_TRUE(transport_security_state.GetStaticSTSState(
"hsts-hpkp-preloaded.test", &new_static_sts_state));
EXPECT_TRUE(transport_security_state.GetStaticPKPState(
"hsts-hpkp-preloaded.test", &new_static_pkp_state));
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));
EXPECT_FALSE(transport_security_state.GetDynamicPKPState(
"hsts-hpkp-preloaded.test", &new_dynamic_pkp_state));
EXPECT_EQ(new_static_sts_state.upgrade_mode, static_sts_state.upgrade_mode);
EXPECT_EQ(new_static_sts_state.include_subdomains,
static_sts_state.include_subdomains);
EXPECT_EQ(new_static_pkp_state.include_subdomains,
static_pkp_state.include_subdomains);
EXPECT_EQ(new_static_pkp_state.spki_hashes, static_pkp_state.spki_hashes);
EXPECT_EQ(new_static_pkp_state.bad_spki_hashes,
static_pkp_state.bad_spki_hashes);
}
TEST_F(HTTPSRequestTest, HSTSPreservesPosts) {
static const char kData[] = "hello world";
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddRule("www.somewhere.com",
test_server.GetIPLiteralString());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::move(host_resolver));
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<TestNetworkDelegate>());
auto context = context_builder->Build();
ASSERT_TRUE(context->transport_security_state());
TransportSecurityState& transport_security_state =
*context->transport_security_state();
base::Time expiry = base::Time::Now() + base::Days(1000);
bool include_subdomains = false;
transport_security_state.AddHSTS("www.somewhere.com", expiry,
include_subdomains);
TestDelegate d;
d.set_allow_certificate_errors(true);
GURL url = GURL(base::StringPrintf("http://www.somewhere.com:%d/echo",
test_server.host_port_pair().port()));
url::Origin origin = url::Origin::Create(url);
std::unique_ptr<URLRequest> req(context->CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_method("POST");
req->set_upload(CreateSimpleUploadData(base::byte_span_from_cstring(kData)));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, origin,
origin, SiteForCookies::FromOrigin(origin)));
req->Start();
d.RunUntilComplete();
EXPECT_EQ("https", req->url().GetScheme());
EXPECT_EQ("POST", req->method());
EXPECT_EQ(kData, d.data_received());
LoadTimingInfo load_timing_info;
network_delegate.GetLoadTimingInfoBeforeRedirect(&load_timing_info);
TestLoadTimingCacheHitNoNetwork(load_timing_info);
}
TEST_F(HTTPSRequestTest, HSTSCrossOriginAddHeaders) {
static const char kOriginHeaderValue[] = "http://www.example.com";
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.ServeFilesFromSourceDirectory("net/data/ssl");
ASSERT_TRUE(test_server.Start());
auto cert_verifier = std::make_unique<MockCertVerifier>();
cert_verifier->set_default_result(OK);
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCertVerifier(std::move(cert_verifier));
auto context = context_builder->Build();
ASSERT_TRUE(context->transport_security_state());
TransportSecurityState& transport_security_state =
*context->transport_security_state();
base::Time expiry = base::Time::Now() + base::Days(1);
bool include_subdomains = false;
transport_security_state.AddHSTS("example.net", expiry, include_subdomains);
GURL hsts_http_url(base::StringPrintf("http://example.net:%d/somehstssite",
test_server.host_port_pair().port()));
GURL::Replacements replacements;
replacements.SetSchemeStr("https");
GURL hsts_https_url = hsts_http_url.ReplaceComponents(replacements);
url::Origin hsts_https_origin = url::Origin::Create(hsts_https_url);
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
hsts_http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
HttpRequestHeaders request_headers;
request_headers.SetHeader("Origin", kOriginHeaderValue);
req->SetExtraRequestHeaders(request_headers);
req->set_isolation_info(IsolationInfo::Create(
IsolationInfo::RequestType::kMainFrame, hsts_https_origin,
hsts_https_origin, SiteForCookies::FromOrigin(hsts_https_origin)));
req->Start();
d.RunUntilRedirect();
EXPECT_EQ(1, d.received_redirect_count());
const HttpResponseHeaders* headers = req->response_headers();
std::string redirect_location;
EXPECT_TRUE(
headers->EnumerateHeader(nullptr, "Location", &redirect_location));
EXPECT_EQ(hsts_https_url.spec(), redirect_location);
std::string received_cors_header;
EXPECT_TRUE(headers->EnumerateHeader(nullptr, "Access-Control-Allow-Origin",
&received_cors_header));
EXPECT_EQ(kOriginHeaderValue, received_cors_header);
std::string received_corp_header;
EXPECT_TRUE(headers->EnumerateHeader(nullptr, "Cross-Origin-Resource-Policy",
&received_corp_header));
EXPECT_EQ("Cross-Origin", received_corp_header);
}
namespace {
class SSLClientAuthTestDelegate : public TestDelegate {
public:
SSLClientAuthTestDelegate() { set_on_complete(base::DoNothing()); }
void OnCertificateRequested(URLRequest* request,
SSLCertRequestInfo* cert_request_info) override {
on_certificate_requested_count_++;
std::move(on_certificate_requested_).Run();
}
void RunUntilCertificateRequested() {
base::RunLoop run_loop;
on_certificate_requested_ = run_loop.QuitClosure();
run_loop.Run();
}
int on_certificate_requested_count() {
return on_certificate_requested_count_;
}
private:
int on_certificate_requested_count_ = 0;
base::OnceClosure on_certificate_requested_;
};
class TestSSLPrivateKey : public SSLPrivateKey {
public:
explicit TestSSLPrivateKey(scoped_refptr<SSLPrivateKey> key)
: key_(std::move(key)) {}
void set_fail_signing(bool fail_signing) { fail_signing_ = fail_signing; }
int sign_count() const { return sign_count_; }
std::string GetProviderName() override { return key_->GetProviderName(); }
std::vector<uint16_t> GetAlgorithmPreferences() override {
return key_->GetAlgorithmPreferences();
}
void Sign(uint16_t algorithm,
base::span<const uint8_t> input,
SignCallback callback) override {
sign_count_++;
if (fail_signing_) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED,
std::vector<uint8_t>()));
} else {
key_->Sign(algorithm, input, std::move(callback));
}
}
private:
~TestSSLPrivateKey() override = default;
scoped_refptr<SSLPrivateKey> key_;
bool fail_signing_ = false;
int sign_count_ = 0;
};
}
TEST_F(HTTPSRequestTest, ClientAuthNoCertificate) {
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::SSLServerConfig ssl_config;
ssl_config.client_cert_type =
SSLServerConfig::ClientCertType::OPTIONAL_CLIENT_CERT;
test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
SSLClientAuthTestDelegate d;
{
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilCertificateRequested();
EXPECT_TRUE(r->is_pending());
EXPECT_EQ(1, d.on_certificate_requested_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
r->ContinueWithCertificate(nullptr, nullptr);
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
}
}
TEST_F(HTTPSRequestTest, ClientAuth) {
std::unique_ptr<FakeClientCertIdentity> identity =
FakeClientCertIdentity::CreateFromCertAndKeyFiles(
GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
ASSERT_TRUE(identity);
scoped_refptr<TestSSLPrivateKey> private_key =
base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::SSLServerConfig ssl_config;
ssl_config.client_cert_type =
SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
{
SSLClientAuthTestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilCertificateRequested();
EXPECT_TRUE(r->is_pending());
EXPECT_EQ(1, d.on_certificate_requested_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
r->ContinueWithCertificate(identity->certificate(), private_key);
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
EXPECT_EQ(1, private_key->sign_count());
}
default_context()
.http_transaction_factory()
->GetSession()
->CloseAllConnections(ERR_FAILED, "Very good reason");
default_context()
.http_transaction_factory()
->GetSession()
->ClearSSLSessionCache();
{
SSLClientAuthTestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(0, d.on_certificate_requested_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
EXPECT_EQ(2, private_key->sign_count());
}
}
TEST_F(HTTPSRequestTest, ClientAuthFailSigning) {
std::unique_ptr<FakeClientCertIdentity> identity =
FakeClientCertIdentity::CreateFromCertAndKeyFiles(
GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
ASSERT_TRUE(identity);
scoped_refptr<TestSSLPrivateKey> private_key =
base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
private_key->set_fail_signing(true);
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::SSLServerConfig ssl_config;
ssl_config.client_cert_type =
SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
{
SSLClientAuthTestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilCertificateRequested();
EXPECT_TRUE(r->is_pending());
EXPECT_EQ(1, d.on_certificate_requested_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
r->ContinueWithCertificate(identity->certificate(), private_key);
d.RunUntilComplete();
EXPECT_EQ(ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED, d.request_status());
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
EXPECT_EQ(1, private_key->sign_count());
}
default_context()
.http_transaction_factory()
->GetSession()
->CloseAllConnections(ERR_FAILED, "Very good reason");
default_context()
.http_transaction_factory()
->GetSession()
->ClearSSLSessionCache();
{
SSLClientAuthTestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilCertificateRequested();
EXPECT_TRUE(r->is_pending());
EXPECT_EQ(1, d.on_certificate_requested_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
EXPECT_EQ(1, private_key->sign_count());
}
}
TEST_F(HTTPSRequestTest, ClientAuthFailSigningRetry) {
std::unique_ptr<FakeClientCertIdentity> identity =
FakeClientCertIdentity::CreateFromCertAndKeyFiles(
GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
ASSERT_TRUE(identity);
scoped_refptr<TestSSLPrivateKey> private_key =
base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::SSLServerConfig ssl_config;
ssl_config.client_cert_type =
SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
{
SSLClientAuthTestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilCertificateRequested();
EXPECT_TRUE(r->is_pending());
EXPECT_EQ(1, d.on_certificate_requested_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
r->ContinueWithCertificate(identity->certificate(), private_key);
d.RunUntilComplete();
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
EXPECT_EQ(1, private_key->sign_count());
}
default_context()
.http_transaction_factory()
->GetSession()
->CloseAllConnections(ERR_FAILED, "Very good reason");
default_context()
.http_transaction_factory()
->GetSession()
->ClearSSLSessionCache();
private_key->set_fail_signing(true);
{
SSLClientAuthTestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilCertificateRequested();
EXPECT_TRUE(r->is_pending());
EXPECT_EQ(2, private_key->sign_count());
EXPECT_EQ(1, d.on_certificate_requested_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(0, d.bytes_received());
}
}
TEST_F(HTTPSRequestTest, ResumeTest) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
const auto url = test_server.GetURL("/");
default_context()
.http_transaction_factory()
->GetSession()
->ClearSSLSessionCache();
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
}
reinterpret_cast<HttpCache*>(default_context().http_transaction_factory())
->CloseAllConnections(ERR_FAILED, "Very good reason");
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, r->ssl_info().handshake_type);
}
}
TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
const auto url = test_server.GetURL("/");
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
}
default_context()
.http_transaction_factory()
->GetSession()
->CloseAllConnections(ERR_FAILED, "");
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, r->ssl_info().handshake_type);
}
auto context_builder = CreateTestURLRequestContextBuilder();
auto other_context = context_builder->Build();
{
TestDelegate d;
std::unique_ptr<URLRequest> r(other_context->CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
}
}
TEST_F(HTTPSRequestTest, NoSessionResumptionBetweenPrivacyModes) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
const auto url = test_server.GetURL("/");
auto ConnectAndCheckHandshake = [this, url](bool allow_credentials,
auto expected_handshake) {
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
if (!allow_credentials) {
r->set_disallow_credentials();
}
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(expected_handshake, r->ssl_info().handshake_type);
};
const bool kAllowCredentialsValues[] = {false, true};
for (const auto allow_creds_1 : kAllowCredentialsValues) {
for (const auto allow_creds_2 : kAllowCredentialsValues) {
SCOPED_TRACE(base::StringPrintf("allow_creds_1=%d, allow_creds_2=%d",
allow_creds_1, allow_creds_2));
ConnectAndCheckHandshake(allow_creds_1, SSLInfo::HANDSHAKE_FULL);
ConnectAndCheckHandshake(allow_creds_2, allow_creds_1 == allow_creds_2
? SSLInfo::HANDSHAKE_RESUME
: SSLInfo::HANDSHAKE_FULL);
auto* network_session =
default_context().http_transaction_factory()->GetSession();
network_session->ClearSSLSessionCache();
}
}
}
class HTTPSFallbackTest : public TestWithTaskEnvironment {
public:
HTTPSFallbackTest() {
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_ssl_config_service(
std::make_unique<TestSSLConfigService>(SSLContextConfig()));
context_ = context_builder->Build();
}
~HTTPSFallbackTest() override = default;
protected:
void DoFallbackTest(const SSLServerConfig& ssl_config) {
DCHECK(!request_);
delegate_.set_allow_certificate_errors(true);
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
ASSERT_TRUE(test_server.Start());
request_ =
context_->CreateRequest(test_server.GetURL("/"), DEFAULT_PRIORITY,
&delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
request_->Start();
delegate_.RunUntilComplete();
}
void ExpectConnection(int version) {
EXPECT_EQ(1, delegate_.response_started_count());
EXPECT_NE(0, delegate_.bytes_received());
EXPECT_EQ(version, SSLConnectionStatusToVersion(
request_->ssl_info().connection_status));
}
void ExpectFailure(int error) {
EXPECT_EQ(1, delegate_.response_started_count());
EXPECT_EQ(error, delegate_.request_status());
}
private:
TestDelegate delegate_;
std::unique_ptr<URLRequestContext> context_;
std::unique_ptr<URLRequest> request_;
};
TEST_F(HTTPSFallbackTest, TLSv1NoFallback) {
net::SSLServerConfig ssl_config;
ssl_config.client_hello_callback_for_testing =
base::BindRepeating([](const SSL_CLIENT_HELLO* client_hello) {
return client_hello->version <= TLS1_VERSION;
});
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_config));
ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
}
TEST_F(HTTPSFallbackTest, TLSv1_1NoFallback) {
net::SSLServerConfig ssl_config;
ssl_config.client_hello_callback_for_testing =
base::BindRepeating([](const SSL_CLIENT_HELLO* client_hello) {
return client_hello->version <= TLS1_1_VERSION;
});
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_config));
ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
}
TEST_F(HTTPSFallbackTest, TLSv1_2NoFallback) {
net::SSLServerConfig ssl_config;
ssl_config.client_hello_callback_for_testing =
base::BindRepeating([](const SSL_CLIENT_HELLO* client_hello) {
const uint8_t* data;
size_t len;
return !SSL_early_callback_ctx_extension_get(
client_hello, TLSEXT_TYPE_supported_versions, &data, &len);
});
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_config));
ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
}
class HTTPSSessionTest : public TestWithTaskEnvironment {
public:
HTTPSSessionTest() {
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCertVerifier(std::make_unique<MockCertVerifier>());
default_context_ = context_builder->Build();
default_cert_verifier().set_default_result(OK);
}
~HTTPSSessionTest() override = default;
URLRequestContext& default_context() { return *default_context_; }
MockCertVerifier& default_cert_verifier() {
return *static_cast<MockCertVerifier*>(default_context_->cert_verifier());
}
private:
std::unique_ptr<URLRequestContext> default_context_;
};
TEST_F(HTTPSSessionTest, DontResumeSessionsForInvalidCertificates) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
const auto url = test_server.GetURL("/");
default_context()
.http_transaction_factory()
->GetSession()
->ClearSSLSessionCache();
default_cert_verifier().set_default_result(ERR_CERT_DATE_INVALID);
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
}
reinterpret_cast<HttpCache*>(default_context().http_transaction_factory())
->CloseAllConnections(ERR_FAILED, "Very good reason");
default_cert_verifier().set_default_result(OK);
{
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
}
}
#endif
class SecureDnsInterceptor : public net::URLRequestInterceptor {
public:
SecureDnsInterceptor() = default;
~SecureDnsInterceptor() override = default;
private:
std::unique_ptr<net::URLRequestJob> MaybeInterceptRequest(
net::URLRequest* request) const override {
EXPECT_EQ(SecureDnsPolicy::kDisable, request->secure_dns_policy());
return nullptr;
}
};
class HTTPSCertNetFetchingTest : public HTTPSRequestTest {
public:
HTTPSCertNetFetchingTest() = default;
void SetUp() override {
cert_net_fetcher_ = base::MakeRefCounted<CertNetFetcherURLRequest>();
auto cert_verifier =
CertVerifier::CreateDefaultWithoutCaching(cert_net_fetcher_);
updatable_cert_verifier_ = cert_verifier.get();
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCertVerifier(std::make_unique<CachingCertVerifier>(
std::make_unique<CoalescingCertVerifier>(std::move(cert_verifier))));
context_ = context_builder->Build();
net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
"http", "127.0.0.1", std::make_unique<SecureDnsInterceptor>());
cert_net_fetcher_->SetURLRequestContext(context_.get());
context_->cert_verifier()->SetConfig(GetCertVerifierConfig());
}
void TearDown() override {
cert_net_fetcher_->Shutdown();
net::URLRequestFilter::GetInstance()->ClearHandlers();
}
void DoConnectionWithDelegate(
std::string_view hostname,
const EmbeddedTestServer::ServerCertificateConfig& cert_config,
TestDelegate* delegate,
SSLInfo* out_ssl_info) {
*out_ssl_info = SSLInfo();
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(cert_config);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
delegate->set_allow_certificate_errors(true);
std::unique_ptr<URLRequest> r(context_->CreateRequest(
test_server.GetURL(hostname, "/"), DEFAULT_PRIORITY, delegate,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
delegate->RunUntilComplete();
EXPECT_EQ(1, delegate->response_started_count());
*out_ssl_info = r->ssl_info();
}
void DoConnectionWithDelegate(
const EmbeddedTestServer::ServerCertificateConfig& cert_config,
TestDelegate* delegate,
SSLInfo* out_ssl_info) {
DoConnectionWithDelegate("127.0.0.1", cert_config, delegate, out_ssl_info);
}
void DoConnection(
std::string_view hostname,
const EmbeddedTestServer::ServerCertificateConfig& cert_config,
CertStatus* out_cert_status) {
*out_cert_status = 0;
TestDelegate d;
SSLInfo ssl_info;
ASSERT_NO_FATAL_FAILURE(
DoConnectionWithDelegate(hostname, cert_config, &d, &ssl_info));
*out_cert_status = ssl_info.cert_status;
}
void DoConnection(
const EmbeddedTestServer::ServerCertificateConfig& cert_config,
CertStatus* out_cert_status) {
DoConnection("127.0.0.1", cert_config, out_cert_status);
}
protected:
virtual CertVerifier::Config GetCertVerifierConfig() {
CertVerifier::Config config;
return config;
}
void UpdateCertVerifier(scoped_refptr<CRLSet> crl_set) {
net::CertVerifyProc::ImplParams params;
params.crl_set = std::move(crl_set);
updatable_cert_verifier_->UpdateVerifyProcData(cert_net_fetcher_, params,
{});
}
scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher_;
std::unique_ptr<URLRequestContext> context_;
raw_ptr<CertVerifierWithUpdatableProc> updatable_cert_verifier_;
};
#if !BUILDFLAG(IS_IOS)
static const char kEVTestCertPolicy[] = "1.3.6.1.4.1.11129.2.4.1";
class HTTPSEVTest : public HTTPSCertNetFetchingTest {
public:
void SetUp() override {
HTTPSCertNetFetchingTest::SetUp();
scoped_refptr<X509Certificate> root_cert =
ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem");
ASSERT_TRUE(root_cert);
ev_test_policy_ = std::make_unique<ScopedTestEVPolicy>(
EVRootCAMetadata::GetInstance(),
X509Certificate::CalculateFingerprint256(root_cert->cert_buffer()),
kEVTestCertPolicy);
}
void TearDown() override { HTTPSCertNetFetchingTest::TearDown(); }
private:
std::unique_ptr<ScopedTestEVPolicy> ev_test_policy_;
};
class HTTPSOCSPTest : public HTTPSCertNetFetchingTest {
public:
CertVerifier::Config GetCertVerifierConfig() override {
CertVerifier::Config config;
config.enable_rev_checking = true;
return config;
}
};
static bool UsingBuiltinCertVerifier() {
#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
return true;
#else
return false;
#endif
}
static bool SystemSupportsHardFailRevocationChecking() {
return UsingBuiltinCertVerifier();
}
static bool SystemUsesChromiumEVMetadata() {
#if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
return true;
#else
return false;
#endif
}
static bool SystemSupportsOCSP() {
#if BUILDFLAG(IS_ANDROID)
return false;
#else
return true;
#endif
}
static bool SystemSupportsOCSPStapling() {
if (UsingBuiltinCertVerifier())
return true;
#if BUILDFLAG(IS_ANDROID)
return false;
#else
return true;
#endif
}
static bool SystemSupportsCRLSets() {
if (UsingBuiltinCertVerifier())
return true;
#if BUILDFLAG(IS_ANDROID)
return false;
#else
return true;
#endif
}
TEST_F(HTTPSEVTest, EVCheckNoOCSP) {
if (!SystemUsesChromiumEVMetadata()) {
LOG(WARNING) << "Skipping test because system doesn't support EV";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.policy_oids = {kEVTestCertPolicy};
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_EQ(SystemUsesChromiumEVMetadata(),
static_cast<bool>(cert_status & CERT_STATUS_IS_EV));
EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, Valid) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, Revoked) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, Invalid) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponse);
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, IntermediateValid) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, IntermediateResponseOldButStillValid) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, IntermediateResponseTooOldKnownRoot) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
scoped_refptr<X509Certificate> root_cert =
ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem");
ASSERT_TRUE(root_cert);
ScopedTestKnownRoot scoped_known_root(root_cert.get());
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLonger}});
cert_config.dns_names = {"example.com"};
CertStatus cert_status;
DoConnection("example.com", cert_config, &cert_status);
if (UsingBuiltinCertVerifier()) {
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
} else {
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
}
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, IntermediateResponseTooOld) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLonger}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, IntermediateRevoked) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, ValidStapled) {
if (!SystemSupportsOCSPStapling()) {
LOG(WARNING)
<< "Skipping test because system doesn't support OCSP stapling";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, RevokedStapled) {
if (!SystemSupportsOCSPStapling()) {
LOG(WARNING)
<< "Skipping test because system doesn't support OCSP stapling";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, OldStapledAndInvalidAIA) {
if (!SystemSupportsOCSPStapling()) {
LOG(WARNING)
<< "Skipping test because system doesn't support OCSP stapling";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}});
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSOCSPTest, OldStapledButValidAIA) {
if (!SystemSupportsOCSPStapling()) {
LOG(WARNING)
<< "Skipping test because system doesn't support OCSP stapling";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}});
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
static const struct OCSPVerifyTestData {
EmbeddedTestServer::OCSPConfig ocsp_config;
bssl::OCSPVerifyResult::ResponseStatus expected_response_status;
bssl::OCSPRevocationStatus expected_cert_status;
} kOCSPVerifyData[] = {
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::GOOD},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater),
bssl::OCSPVerifyResult::ERROR_RESPONSE,
bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponse),
bssl::OCSPVerifyResult::PARSE_RESPONSE_ERROR,
bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponseData),
bssl::OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR,
bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::UNKNOWN,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::UNKNOWN,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::UNKNOWN,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kBeforeCert),
bssl::OCSPVerifyResult::BAD_PRODUCED_AT,
bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kAfterCert),
bssl::OCSPVerifyResult::BAD_PRODUCED_AT,
bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld},
{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::GOOD},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly},
{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::GOOD},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong},
{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::GOOD},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly},
{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld},
{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::UNKNOWN,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid},
{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid},
{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::REVOKED},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::UNKNOWN,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid},
{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::UNKNOWN,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid},
{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong},
{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid,
EmbeddedTestServer::OCSPConfig::SingleResponse::Serial::kMismatch}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::NO_MATCHING_RESPONSE,
bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly,
EmbeddedTestServer::OCSPConfig::SingleResponse::Serial::kMismatch}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::NO_MATCHING_RESPONSE,
bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::PROVIDED, bssl::OCSPRevocationStatus::REVOKED},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
{EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}},
EmbeddedTestServer::OCSPConfig::Produced::kValid),
bssl::OCSPVerifyResult::INVALID_DATE, bssl::OCSPRevocationStatus::UNKNOWN},
};
class HTTPSOCSPVerifyTest
: public HTTPSOCSPTest,
public testing::WithParamInterface<OCSPVerifyTestData> {};
TEST_P(HTTPSOCSPVerifyTest, VerifyResult) {
#if BUILDFLAG(CRONET_BUILD)
if (base::android::android_info::sdk_int() >= 36) {
GTEST_SKIP();
}
#endif
OCSPVerifyTestData test = GetParam();
scoped_refptr<X509Certificate> root_cert =
ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem");
ASSERT_TRUE(root_cert);
ScopedTestKnownRoot scoped_known_root(root_cert.get());
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.stapled_ocsp_config = test.ocsp_config;
cert_config.dns_names = {"example.com"};
SSLInfo ssl_info;
OCSPErrorTestDelegate delegate;
ASSERT_NO_FATAL_FAILURE(DoConnectionWithDelegate("example.com", cert_config,
&delegate, &ssl_info));
if (delegate.have_certificate_errors()) {
ASSERT_TRUE(delegate.on_ssl_certificate_error_called());
ssl_info = delegate.ssl_info();
}
EXPECT_EQ(test.expected_response_status,
ssl_info.ocsp_result.response_status);
if (test.expected_response_status == bssl::OCSPVerifyResult::PROVIDED) {
EXPECT_EQ(test.expected_cert_status,
ssl_info.ocsp_result.revocation_status);
}
}
INSTANTIATE_TEST_SUITE_P(OCSPVerify,
HTTPSOCSPVerifyTest,
testing::ValuesIn(kOCSPVerifyData));
#endif
class HTTPSAIATest : public HTTPSCertNetFetchingTest {};
TEST_F(HTTPSAIATest, AIAFetching) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = EmbeddedTestServer::IntermediateType::kByAIA;
test_server.SetSSLConfig(cert_config);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
TestDelegate d;
d.set_allow_certificate_errors(true);
std::unique_ptr<URLRequest> r(context_->CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
CertStatus cert_status = r->ssl_info().cert_status;
EXPECT_EQ(OK, d.request_status());
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
ASSERT_TRUE(r->ssl_info().cert);
EXPECT_EQ(2u, r->ssl_info().cert->intermediate_buffers().size());
ASSERT_TRUE(r->ssl_info().unverified_cert);
EXPECT_EQ(0u, r->ssl_info().unverified_cert->intermediate_buffers().size());
}
#if !BUILDFLAG(IS_IOS)
class HTTPSHardFailTest : public HTTPSOCSPTest {
protected:
CertVerifier::Config GetCertVerifierConfig() override {
CertVerifier::Config config;
config.require_rev_checking_local_anchors = true;
return config;
}
};
TEST_F(HTTPSHardFailTest, Valid) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSHardFailTest, Revoked) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSHardFailTest, FailsOnOCSPInvalid) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponse);
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_UNABLE_TO_CHECK_REVOCATION,
cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSHardFailTest, IntermediateResponseOldButStillValid) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSHardFailTest, IntermediateResponseTooOld) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLonger}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSHardFailTest, ValidStapled) {
if (!SystemSupportsOCSPStapling()) {
LOG(WARNING)
<< "Skipping test because system doesn't support OCSP stapling";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSHardFailTest, RevokedStapled) {
if (!SystemSupportsOCSPStapling()) {
LOG(WARNING)
<< "Skipping test because system doesn't support OCSP stapling";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSHardFailTest, OldStapledAndInvalidAIA) {
if (!SystemSupportsOCSPStapling()) {
LOG(WARNING)
<< "Skipping test because system doesn't support OCSP stapling";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}});
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(CERT_STATUS_UNABLE_TO_CHECK_REVOCATION,
cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSHardFailTest, OldStapledButValidAIA) {
if (!SystemSupportsOCSPStapling()) {
LOG(WARNING)
<< "Skipping test because system doesn't support OCSP stapling";
return;
}
if (!SystemSupportsHardFailRevocationChecking()) {
LOG(WARNING) << "Skipping test because system doesn't support hard fail "
<< "revocation checking";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}});
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
class HTTPSCRLSetTest : public HTTPSCertNetFetchingTest {};
TEST_F(HTTPSCRLSetTest, ExpiredCRLSet) {
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponse);
UpdateCertVerifier(CRLSet::ExpiredCRLSetForTesting());
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSCRLSetTest, ExpiredCRLSetAndRevoked) {
if (!SystemSupportsOCSP()) {
LOG(WARNING) << "Skipping test because system doesn't support OCSP";
return;
}
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::REVOKED,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
UpdateCertVerifier(CRLSet::ExpiredCRLSetForTesting());
CertStatus cert_status;
DoConnection(cert_config, &cert_status);
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSCRLSetTest, CRLSetRevoked) {
if (!SystemSupportsCRLSets()) {
LOG(WARNING) << "Skipping test because system doesn't support CRLSets";
return;
}
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
test_server.SetSSLConfig(cert_config);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
CertVerifier::Config cert_verifier_config = GetCertVerifierConfig();
auto root_cert_spki_hash = GetTestRootCertSPKIHash();
auto crl_set =
CRLSet::ForTesting(false, &root_cert_spki_hash,
test_server.GetCertificate()->serial_number(), "", {});
ASSERT_TRUE(crl_set);
UpdateCertVerifier(crl_set);
TestDelegate d;
d.set_allow_certificate_errors(true);
std::unique_ptr<URLRequest> r(context_->CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
CertStatus cert_status = r->ssl_info().cert_status;
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
TEST_F(HTTPSCRLSetTest, CRLSetRevokedBySubject) {
if (!SystemSupportsCRLSets()) {
LOG(WARNING) << "Skipping test because system doesn't support CRLSets";
return;
}
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
{{bssl::OCSPRevocationStatus::GOOD,
EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
test_server.SetSSLConfig(cert_config);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
std::string common_name = test_server.GetCertificate()->subject().common_name;
{
auto crl_set = CRLSet::ForTesting(
false, nullptr, {},
common_name,
{});
ASSERT_TRUE(crl_set);
UpdateCertVerifier(crl_set);
TestDelegate d;
d.set_allow_certificate_errors(true);
std::unique_ptr<URLRequest> r(context_->CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
CertStatus cert_status = r->ssl_info().cert_status;
EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
}
SHA256HashValue spki_hash_value;
ASSERT_TRUE(x509_util::CalculateSha256SpkiHash(
test_server.GetCertificate()->cert_buffer(), &spki_hash_value));
std::string spki_hash(base::as_string_view(spki_hash_value));
{
auto crl_set = CRLSet::ForTesting(
false, nullptr, {},
common_name, {spki_hash});
ASSERT_TRUE(crl_set);
UpdateCertVerifier(crl_set);
TestDelegate d;
d.set_allow_certificate_errors(true);
std::unique_ptr<URLRequest> r(context_->CreateRequest(
test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
CertStatus cert_status = r->ssl_info().cert_status;
EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
}
}
using HTTPSLocalCRLSetTest = TestWithTaskEnvironment;
TEST_F(HTTPSLocalCRLSetTest, KnownInterceptionBlocked) {
auto cert_verifier = CertVerifier::CreateDefaultWithoutCaching(
nullptr);
CertVerifierWithUpdatableProc* updatable_cert_verifier_ = cert_verifier.get();
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCertVerifier(std::make_unique<CachingCertVerifier>(
std::make_unique<CoalescingCertVerifier>(std::move(cert_verifier))));
auto context = context_builder->Build();
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&https_server);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_OK_BY_INTERMEDIATE);
ASSERT_TRUE(https_server.Start());
{
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(https_server.GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.request_failed());
EXPECT_FALSE(d.have_certificate_errors());
EXPECT_FALSE(req->ssl_info().cert_status &
CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
}
std::string crl_set_bytes;
net::CertVerifyProc::ImplParams params;
ASSERT_TRUE(
base::ReadFileToString(GetTestCertsDirectory().AppendASCII(
"crlset_blocked_interception_by_root.raw"),
&crl_set_bytes));
ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, ¶ms.crl_set));
updatable_cert_verifier_->UpdateVerifyProcData(
nullptr, params, {});
{
TestDelegate d;
d.set_allow_certificate_errors(true);
std::unique_ptr<URLRequest> req(
context->CreateRequest(https_server.GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.request_failed());
if (SystemSupportsCRLSets()) {
EXPECT_TRUE(d.have_certificate_errors());
EXPECT_FALSE(d.certificate_errors_are_fatal());
EXPECT_EQ(ERR_CERT_KNOWN_INTERCEPTION_BLOCKED, d.certificate_net_error());
EXPECT_TRUE(req->ssl_info().cert_status &
CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
} else {
EXPECT_FALSE(d.have_certificate_errors());
EXPECT_TRUE(req->ssl_info().cert_status &
CERT_STATUS_KNOWN_INTERCEPTION_DETECTED);
}
}
}
TEST_F(HTTPSLocalCRLSetTest, InterceptionBlockedAllowOverrideOnHSTS) {
constexpr char kHSTSHost[] = "include-subdomains-hsts-preloaded.test";
constexpr char kHSTSSubdomainWithKnownInterception[] =
"www.include-subdomains-hsts-preloaded.test";
EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK_BY_INTERMEDIATE);
https_server.ServeFilesFromSourceDirectory(base::FilePath(kTestFilePath));
ASSERT_TRUE(https_server.Start());
auto cert_verifier = std::make_unique<MockCertVerifier>();
scoped_refptr<X509Certificate> cert = https_server.GetCertificate();
ASSERT_TRUE(cert);
SHA256HashValue filler_hash;
filler_hash.fill(3);
CertVerifyResult fake_result;
fake_result.verified_cert = cert;
fake_result.is_issued_by_known_root = false;
CertVerifyResult test_result = fake_result;
test_result.public_key_hashes.push_back(filler_hash);
test_result.cert_status |= CERT_STATUS_AUTHORITY_INVALID;
cert_verifier->AddResultForCertAndHost(
cert.get(), https_server.host_port_pair().host(), test_result,
ERR_CERT_AUTHORITY_INVALID);
CertVerifyResult sts_base_result = fake_result;
sts_base_result.public_key_hashes.push_back(filler_hash);
sts_base_result.cert_status |= CERT_STATUS_AUTHORITY_INVALID;
cert_verifier->AddResultForCertAndHost(cert.get(), kHSTSHost, sts_base_result,
ERR_CERT_AUTHORITY_INVALID);
CertVerifyResult sts_sub_result = fake_result;
sts_sub_result.public_key_hashes.push_back(GetTestRootCertSPKIHash());
sts_sub_result.cert_status |=
CERT_STATUS_REVOKED | CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED;
cert_verifier->AddResultForCertAndHost(
cert.get(), kHSTSSubdomainWithKnownInterception, sts_sub_result,
ERR_CERT_KNOWN_INTERCEPTION_BLOCKED);
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCertVerifier(std::move(cert_verifier));
auto context = context_builder->Build();
ASSERT_TRUE(context->transport_security_state());
TransportSecurityState& security_state = *context->transport_security_state();
security_state.EnableStaticPinsForTesting();
security_state.SetPinningListAlwaysTimelyForTesting(true);
SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
{
TestDelegate d;
std::unique_ptr<URLRequest> req(
context->CreateRequest(https_server.GetURL("/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_TRUE(d.request_failed());
EXPECT_TRUE(d.have_certificate_errors());
EXPECT_FALSE(d.certificate_errors_are_fatal());
EXPECT_FALSE(req->ssl_info().cert_status &
CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
https_server.GetURL(kHSTSHost, "/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_TRUE(d.request_failed());
EXPECT_TRUE(d.have_certificate_errors());
EXPECT_TRUE(d.certificate_errors_are_fatal());
EXPECT_FALSE(req->ssl_info().cert_status &
CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
}
{
TestDelegate d;
d.set_allow_certificate_errors(true);
std::unique_ptr<URLRequest> req(context->CreateRequest(
https_server.GetURL(kHSTSSubdomainWithKnownInterception, "/"),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.request_failed());
EXPECT_TRUE(d.have_certificate_errors());
EXPECT_FALSE(d.certificate_errors_are_fatal());
EXPECT_EQ(ERR_CERT_KNOWN_INTERCEPTION_BLOCKED, d.certificate_net_error());
EXPECT_TRUE(req->ssl_info().cert_status &
CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
}
}
#endif
TEST_F(URLRequestTest, NetworkAccessedSetOnHostResolutionFailure) {
auto context_builder = CreateTestURLRequestContextBuilder();
auto host_resolver = std::make_unique<MockHostResolver>();
host_resolver->rules()->AddSimulatedTimeoutFailure("*");
context_builder->set_host_resolver(std::move(host_resolver));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_FALSE(req->response_info().network_accessed);
req->Start();
d.RunUntilComplete();
EXPECT_TRUE(req->response_info().network_accessed);
EXPECT_THAT(req->response_info().resolve_error_info.error,
IsError(ERR_DNS_TIMED_OUT));
}
TEST_F(URLRequestTest, URLRequestRedirectJobCancelRequest) {
TestDelegate d;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
GURL("http://not-a-real-domain/"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
std::unique_ptr<URLRequestRedirectJob> job =
std::make_unique<URLRequestRedirectJob>(
req.get(), GURL("http://this-should-never-be-navigated-to/"),
RedirectUtil::ResponseCode::REDIRECT_307_TEMPORARY_REDIRECT,
"Jumbo shrimp");
TestScopedURLInterceptor interceptor(req->url(), std::move(job));
req->Start();
req->Cancel();
d.RunUntilComplete();
EXPECT_EQ(ERR_ABORTED, d.request_status());
EXPECT_EQ(0, d.received_redirect_count());
}
TEST_F(URLRequestTestHTTP, HeadersCallbacks) {
ASSERT_TRUE(http_test_server()->Start());
GURL url(http_test_server()->GetURL("/cachetime"));
HttpRequestHeaders extra_headers;
extra_headers.SetHeader("X-Foo", "bar");
{
HttpRawRequestHeaders raw_req_headers;
scoped_refptr<const HttpResponseHeaders> raw_resp_headers;
TestDelegate delegate;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetExtraRequestHeaders(extra_headers);
r->SetRequestHeadersCallback(base::BindLambdaForTesting(
[&delegate, &raw_req_headers](HttpRawRequestHeaders request_headers) {
EXPECT_EQ(delegate.response_started_count(), 0);
raw_req_headers = std::move(request_headers);
}));
r->SetResponseHeadersCallback(base::BindLambdaForTesting(
[&delegate, &raw_resp_headers](
scoped_refptr<const HttpResponseHeaders> response_headers) {
EXPECT_EQ(delegate.response_started_count(), 0);
raw_resp_headers = response_headers;
}));
r->set_isolation_info(isolation_info1_);
r->Start();
delegate.RunUntilComplete();
EXPECT_FALSE(raw_req_headers.headers().empty());
std::string value;
EXPECT_TRUE(raw_req_headers.FindHeaderForTest("X-Foo", &value));
EXPECT_EQ("bar", value);
EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Accept-Encoding", &value));
EXPECT_EQ("gzip, deflate", value);
EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Connection", &value));
EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Host", &value));
EXPECT_EQ("GET /cachetime HTTP/1.1\r\n", raw_req_headers.request_line());
EXPECT_EQ(raw_resp_headers.get(), r->response_headers());
}
{
TestDelegate delegate;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetExtraRequestHeaders(extra_headers);
r->SetRequestHeadersCallback(base::BindRepeating([](HttpRawRequestHeaders) {
FAIL() << "Callback should not be called unless request is sent";
}));
r->SetResponseHeadersCallback(
base::BindRepeating([](scoped_refptr<const HttpResponseHeaders>) {
FAIL() << "Callback should not be called unless request is sent";
}));
r->set_isolation_info(isolation_info1_);
r->Start();
delegate.RunUntilComplete();
EXPECT_TRUE(r->was_cached());
}
}
TEST_F(URLRequestTestHTTP, HeadersCallbacksWithRedirect) {
ASSERT_TRUE(http_test_server()->Start());
HttpRawRequestHeaders raw_req_headers;
scoped_refptr<const HttpResponseHeaders> raw_resp_headers;
TestDelegate delegate;
HttpRequestHeaders extra_headers;
extra_headers.SetHeader("X-Foo", "bar");
GURL url(http_test_server()->GetURL("/redirect-test.html"));
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetExtraRequestHeaders(extra_headers);
r->SetRequestHeadersCallback(base::BindRepeating(
&HttpRawRequestHeaders::Assign, base::Unretained(&raw_req_headers)));
r->SetResponseHeadersCallback(base::BindRepeating(
[](scoped_refptr<const HttpResponseHeaders>* left,
scoped_refptr<const HttpResponseHeaders> right) { *left = right; },
base::Unretained(&raw_resp_headers)));
r->Start();
delegate.RunUntilRedirect();
ASSERT_EQ(1, delegate.received_redirect_count());
std::string value;
EXPECT_TRUE(raw_req_headers.FindHeaderForTest("X-Foo", &value));
EXPECT_EQ("bar", value);
EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Accept-Encoding", &value));
EXPECT_EQ("gzip, deflate", value);
EXPECT_EQ(1, delegate.received_redirect_count());
EXPECT_EQ("GET /redirect-test.html HTTP/1.1\r\n",
raw_req_headers.request_line());
EXPECT_TRUE(raw_resp_headers->HasHeader("Location"));
EXPECT_EQ(302, raw_resp_headers->response_code());
EXPECT_EQ("Redirect", raw_resp_headers->GetStatusText());
raw_req_headers = HttpRawRequestHeaders();
raw_resp_headers = nullptr;
r->FollowDeferredRedirect(std::nullopt ,
std::nullopt );
delegate.RunUntilComplete();
EXPECT_TRUE(raw_req_headers.FindHeaderForTest("X-Foo", &value));
EXPECT_EQ("bar", value);
EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Accept-Encoding", &value));
EXPECT_EQ("gzip, deflate", value);
EXPECT_EQ("GET /with-headers.html HTTP/1.1\r\n",
raw_req_headers.request_line());
EXPECT_EQ(r->response_headers(), raw_resp_headers.get());
}
TEST_F(URLRequestTest, HeadersCallbacksConnectFailed) {
TestDelegate request_delegate;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
GURL("http://127.0.0.1:9/"), DEFAULT_PRIORITY, &request_delegate,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetRequestHeadersCallback(
base::BindRepeating([](net::HttpRawRequestHeaders) {
FAIL() << "Callback should not be called unless request is sent";
}));
r->SetResponseHeadersCallback(
base::BindRepeating([](scoped_refptr<const net::HttpResponseHeaders>) {
FAIL() << "Callback should not be called unless request is sent";
}));
r->Start();
request_delegate.RunUntilComplete();
EXPECT_FALSE(r->is_pending());
}
TEST_F(URLRequestTestHTTP, HeadersCallbacksAuthRetry) {
ASSERT_TRUE(http_test_server()->Start());
GURL url(http_test_server()->GetURL("/auth-basic"));
TestDelegate delegate;
delegate.set_credentials(AuthCredentials(kUser, kSecret));
HttpRequestHeaders extra_headers;
extra_headers.SetHeader("X-Foo", "bar");
using ReqHeadersVector = std::vector<std::unique_ptr<HttpRawRequestHeaders>>;
ReqHeadersVector raw_req_headers;
using RespHeadersVector =
std::vector<scoped_refptr<const HttpResponseHeaders>>;
RespHeadersVector raw_resp_headers;
auto req_headers_callback = base::BindRepeating(
[](ReqHeadersVector* vec, HttpRawRequestHeaders headers) {
vec->emplace_back(
std::make_unique<HttpRawRequestHeaders>(std::move(headers)));
},
&raw_req_headers);
auto resp_headers_callback = base::BindRepeating(
[](RespHeadersVector* vec,
scoped_refptr<const HttpResponseHeaders> headers) {
vec->push_back(headers);
},
&raw_resp_headers);
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetExtraRequestHeaders(extra_headers);
r->SetRequestHeadersCallback(req_headers_callback);
r->SetResponseHeadersCallback(resp_headers_callback);
r->set_isolation_info(isolation_info1_);
r->Start();
delegate.RunUntilComplete();
EXPECT_FALSE(r->is_pending());
ASSERT_EQ(raw_req_headers.size(), 2u);
ASSERT_EQ(raw_resp_headers.size(), 2u);
std::string value;
EXPECT_FALSE(raw_req_headers[0]->FindHeaderForTest("Authorization", &value));
EXPECT_TRUE(raw_req_headers[0]->FindHeaderForTest("X-Foo", &value));
EXPECT_EQ("bar", value);
EXPECT_TRUE(raw_req_headers[1]->FindHeaderForTest("Authorization", &value));
EXPECT_TRUE(raw_req_headers[1]->FindHeaderForTest("X-Foo", &value));
EXPECT_EQ("bar", value);
EXPECT_EQ(raw_resp_headers[1], r->response_headers());
EXPECT_NE(raw_resp_headers[0], raw_resp_headers[1]);
EXPECT_EQ(401, raw_resp_headers[0]->response_code());
EXPECT_EQ("Unauthorized", raw_resp_headers[0]->GetStatusText());
std::unique_ptr<URLRequest> r2(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
r2->SetExtraRequestHeaders(extra_headers);
r2->SetRequestHeadersCallback(req_headers_callback);
r2->SetResponseHeadersCallback(resp_headers_callback);
r2->SetLoadFlags(LOAD_VALIDATE_CACHE);
r2->set_isolation_info(isolation_info1_);
r2->Start();
delegate.RunUntilComplete();
EXPECT_FALSE(r2->is_pending());
ASSERT_EQ(raw_req_headers.size(), 3u);
ASSERT_EQ(raw_resp_headers.size(), 3u);
EXPECT_TRUE(raw_req_headers[2]->FindHeaderForTest("If-None-Match", &value));
EXPECT_NE(raw_resp_headers[2].get(), r2->response_headers());
EXPECT_EQ(304, raw_resp_headers[2]->response_code());
EXPECT_EQ("Not Modified", raw_resp_headers[2]->GetStatusText());
}
TEST_F(URLRequestTest, UpgradeIfInsecureFlagSet) {
TestDelegate d;
const GURL kOriginalUrl("https://original.test");
const GURL kRedirectUrl("http://redirect.test");
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS));
network_delegate.set_redirect_url(kRedirectUrl);
auto context = context_builder->Build();
std::unique_ptr<URLRequest> r(context->CreateRequest(
kOriginalUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_upgrade_if_insecure(true);
r->Start();
d.RunUntilRedirect();
GURL::Replacements replacements;
replacements.SetSchemeStr("https");
EXPECT_EQ(kRedirectUrl.ReplaceComponents(replacements),
d.redirect_info().new_url);
EXPECT_TRUE(d.redirect_info().insecure_scheme_was_upgraded);
}
TEST_F(URLRequestTest, UpgradeIfInsecureFlagSetExplicitPort80) {
TestDelegate d;
const GURL kOriginalUrl("https://original.test");
const GURL kRedirectUrl("http://redirect.test:80");
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS));
network_delegate.set_redirect_url(kRedirectUrl);
auto context = context_builder->Build();
std::unique_ptr<URLRequest> r(context->CreateRequest(
kOriginalUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_upgrade_if_insecure(true);
r->Start();
d.RunUntilRedirect();
GURL::Replacements replacements;
EXPECT_EQ(d.redirect_info().new_url.GetHost(), kRedirectUrl.GetHost());
EXPECT_TRUE(d.redirect_info().new_url.SchemeIs("https"));
EXPECT_EQ(d.redirect_info().new_url.EffectiveIntPort(), 443);
EXPECT_TRUE(d.redirect_info().insecure_scheme_was_upgraded);
}
TEST_F(URLRequestTest, UpgradeIfInsecureFlagSetNonStandardPort) {
TestDelegate d;
const GURL kOriginalUrl("https://original.test");
const GURL kRedirectUrl("http://redirect.test:1234");
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS));
network_delegate.set_redirect_url(kRedirectUrl);
auto context = context_builder->Build();
std::unique_ptr<URLRequest> r(context->CreateRequest(
kOriginalUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_upgrade_if_insecure(true);
r->Start();
d.RunUntilRedirect();
GURL::Replacements replacements;
replacements.SetSchemeStr("https");
EXPECT_EQ(kRedirectUrl.ReplaceComponents(replacements),
d.redirect_info().new_url);
EXPECT_TRUE(d.redirect_info().insecure_scheme_was_upgraded);
}
TEST_F(URLRequestTest, UpgradeIfInsecureFlagNotSet) {
TestDelegate d;
const GURL kOriginalUrl("https://original.test");
const GURL kRedirectUrl("http://redirect.test");
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<BlockingNetworkDelegate>(
BlockingNetworkDelegate::SYNCHRONOUS));
network_delegate.set_redirect_url(kRedirectUrl);
auto context = context_builder->Build();
std::unique_ptr<URLRequest> r(context->CreateRequest(
kOriginalUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_upgrade_if_insecure(false);
r->Start();
d.RunUntilRedirect();
EXPECT_EQ(kRedirectUrl, d.redirect_info().new_url);
EXPECT_FALSE(d.redirect_info().insecure_scheme_was_upgraded);
}
#if BUILDFLAG(IS_ANDROID)
TEST_F(URLRequestTestHTTP, TestTagging) {
if (!CanGetTaggedBytes()) {
DVLOG(0) << "Skipping test - GetTaggedBytes unsupported.";
return;
}
ASSERT_TRUE(http_test_server()->Start());
static const int32_t UNTAGGED_TAG = 0;
uint64_t old_traffic = GetTaggedBytes(UNTAGGED_TAG);
TestDelegate delegate;
std::unique_ptr<URLRequest> req(default_context().CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &delegate,
TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_EQ(SocketTag(), req->socket_tag());
req->Start();
delegate.RunUntilComplete();
EXPECT_GT(GetTaggedBytes(UNTAGGED_TAG), old_traffic);
int32_t tag_val1 = 0x12345678;
SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
old_traffic = GetTaggedBytes(tag_val1);
req = default_context().CreateRequest(http_test_server()->GetURL("/"),
DEFAULT_PRIORITY, &delegate,
TRAFFIC_ANNOTATION_FOR_TESTS);
req->set_socket_tag(tag1);
EXPECT_EQ(tag1, req->socket_tag());
req->Start();
delegate.RunUntilComplete();
EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
}
#endif
namespace {
class ReadBufferingListener
: public test_server::EmbeddedTestServerConnectionListener {
public:
ReadBufferingListener() = default;
~ReadBufferingListener() override = default;
void BufferNextConnection(int buffer_size) { buffer_size_ = buffer_size; }
std::unique_ptr<StreamSocket> AcceptedSocket(
std::unique_ptr<StreamSocket> socket) override {
if (!buffer_size_) {
return socket;
}
auto wrapped =
std::make_unique<ReadBufferingStreamSocket>(std::move(socket));
wrapped->BufferNextRead(buffer_size_);
buffer_size_ = 0;
return wrapped;
}
void ReadFromSocket(const StreamSocket& socket, int rv) override {}
private:
int buffer_size_ = 0;
};
class ZeroRTTResponse : public test_server::BasicHttpResponse {
public:
ZeroRTTResponse(bool zero_rtt, bool send_too_early, bool is_websocket = false)
: zero_rtt_(zero_rtt),
send_too_early_(send_too_early),
is_websocket_(is_websocket) {}
ZeroRTTResponse(const ZeroRTTResponse&) = delete;
ZeroRTTResponse& operator=(const ZeroRTTResponse&) = delete;
~ZeroRTTResponse() override = default;
void SendResponse(
base::WeakPtr<test_server::HttpResponseDelegate> delegate) override {
AddCustomHeader("Vary", "Early-Data");
set_content_type("text/plain");
AddCustomHeader("Cache-Control", "no-cache");
if (zero_rtt_) {
if (send_too_early_)
set_code(HTTP_TOO_EARLY);
set_content("1");
} else {
set_content("0");
}
if (is_websocket_ && !(zero_rtt_ && send_too_early_)) {
set_code(HTTP_SWITCHING_PROTOCOLS);
AddCustomHeader("Connection", "Upgrade");
AddCustomHeader("Upgrade", "websocket");
AddCustomHeader("Sec-WebSocket-Accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
}
delegate->SendResponseHeaders(code(), GetHttpReasonPhrase(code()),
BuildHeaders());
delegate->SendContents(content(), base::DoNothing());
}
private:
bool zero_rtt_;
bool send_too_early_;
bool is_websocket_;
};
std::unique_ptr<test_server::HttpResponse> HandleZeroRTTRequest(
const test_server::HttpRequest& request) {
DCHECK(request.ssl_info);
if (request.GetURL().GetPath() != "/zerortt") {
return nullptr;
}
return std::make_unique<ZeroRTTResponse>(
request.ssl_info->early_data_received, false,
request.GetURL().GetQuery() == "ws=1");
}
}
class HTTPSEarlyDataTest : public TestWithTaskEnvironment {
public:
HTTPSEarlyDataTest() : test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
HttpNetworkSessionParams params;
params.enable_early_data = true;
auto cert_verifier = std::make_unique<MockCertVerifier>();
cert_verifier->set_default_result(OK);
SSLContextConfig config;
config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_http_network_session_params(params);
context_builder->SetCertVerifier(std::move(cert_verifier));
context_builder->set_ssl_config_service(
std::make_unique<TestSSLConfigService>(config));
context_ = context_builder->Build();
test_server_.SetSSLConfig(
net::EmbeddedTestServer::CERT_OK,
CreateSSLServerConfig(SSL_PROTOCOL_VERSION_TLS1_3));
RegisterDefaultHandlers(&test_server_);
test_server_.RegisterRequestHandler(
base::BindRepeating(&HandleZeroRTTRequest));
test_server_.SetConnectionListener(&listener_);
}
~HTTPSEarlyDataTest() override = default;
URLRequestContext& context() { return *context_; }
static SSLServerConfig CreateSSLServerConfig(uint16_t version) {
SSLServerConfig ssl_config;
ssl_config.version_max = version;
ssl_config.early_data_enabled = true;
return ssl_config;
}
void ResetSSLConfig(net::EmbeddedTestServer::ServerCertificate cert,
uint16_t version) {
SSLServerConfig ssl_config = CreateSSLServerConfig(version);
test_server_.ResetSSLConfig(cert, ssl_config);
}
protected:
std::unique_ptr<URLRequestContext> context_;
ReadBufferingListener listener_;
EmbeddedTestServer test_server_;
};
TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTest) {
ASSERT_TRUE(test_server_.Start());
context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
const int kParamSize = 4 * 1024;
const GURL kUrl =
test_server_.GetURL("/zerortt?" + std::string(kParamSize, 'a'));
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
context().http_transaction_factory()->GetSession()->CloseAllConnections(
ERR_FAILED, "Very good reason");
listener_.BufferNextConnection(kParamSize);
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("1", d.data_received());
}
}
TEST_F(HTTPSEarlyDataTest, TLSEarlyDataPOSTTest) {
ASSERT_TRUE(test_server_.Start());
context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
context().http_transaction_factory()->GetSession()->CloseAllConnections(
ERR_FAILED, "Very good reason");
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_method("POST");
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
}
TEST_F(HTTPSEarlyDataTest, TLSEarlyDataIdempotentPOSTTest) {
ASSERT_TRUE(test_server_.Start());
context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
const int kParamSize = 4 * 1024;
const GURL kUrl =
test_server_.GetURL("/zerortt?" + std::string(kParamSize, 'a'));
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
context().http_transaction_factory()->GetSession()->CloseAllConnections(
ERR_FAILED, "Very good reason");
listener_.BufferNextConnection(kParamSize);
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_method("POST");
r->SetIdempotency(net::IDEMPOTENT);
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("1", d.data_received());
}
}
TEST_F(HTTPSEarlyDataTest, TLSEarlyDataNonIdempotentRequestTest) {
ASSERT_TRUE(test_server_.Start());
context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
context().http_transaction_factory()->GetSession()->CloseAllConnections(
ERR_FAILED, "Very good reason");
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->SetIdempotency(net::NOT_IDEMPOTENT);
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
}
std::unique_ptr<test_server::HttpResponse> HandleTooEarly(
bool* sent_425,
const test_server::HttpRequest& request) {
DCHECK(request.ssl_info);
if (request.GetURL().GetPath() != "/tooearly") {
return nullptr;
}
if (request.ssl_info->early_data_received)
*sent_425 = true;
return std::make_unique<ZeroRTTResponse>(
request.ssl_info->early_data_received, true);
}
TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTooEarlyTest) {
bool sent_425 = false;
test_server_.RegisterRequestHandler(
base::BindRepeating(&HandleTooEarly, base::Unretained(&sent_425)));
ASSERT_TRUE(test_server_.Start());
context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
const int kParamSize = 4 * 1024;
const GURL kUrl =
test_server_.GetURL("/tooearly?" + std::string(kParamSize, 'a'));
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
EXPECT_FALSE(sent_425);
}
context().http_transaction_factory()->GetSession()->CloseAllConnections(
ERR_FAILED, "Very good reason");
listener_.BufferNextConnection(kParamSize);
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
EXPECT_TRUE(sent_425);
}
}
#if BUILDFLAG(ENABLE_WEBSOCKETS)
TEST_F(HTTPSEarlyDataTest, WebSocketEarlyDataTooEarly) {
ASSERT_TRUE(test_server_.Start());
context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
const GURL kUrl = test_server_.GetURL("/zerortt?ws=0");
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
context().http_transaction_factory()->GetSession()->CloseAllConnections(
ERR_FAILED, "Very good reason");
scoped_refptr<X509Certificate> old_cert = test_server_.GetCertificate();
ResetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED,
SSL_PROTOCOL_VERSION_TLS1_3);
GURL::Replacements replacements;
replacements.SetQueryStr("ws=1");
replacements.SetSchemeStr(url::kWssScheme);
const GURL wss_url = kUrl.ReplaceComponents(replacements);
{
TestDelegate d;
std::unique_ptr<URLRequest> req(context().CreateRequest(
wss_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS,
true));
EXPECT_TRUE(req->url().SchemeIsCryptographic());
d.set_cancel_in_response_started(true);
HttpRequestHeaders headers = WebSocketCommonTestHeaders();
req->SetExtraRequestHeaders(headers);
auto websocket_stream_create_helper =
std::make_unique<TestWebSocketHandshakeStreamCreateHelper>();
req->SetUserData(kWebSocketHandshakeUserDataKey,
std::move(websocket_stream_create_helper));
req->Start();
EXPECT_TRUE(req->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_TRUE(d.response_code().has_value());
EXPECT_EQ(HTTP_SWITCHING_PROTOCOLS, d.response_code().value());
}
}
#endif
TEST_F(HTTPSEarlyDataTest, TLSEarlyDataRejectTest) {
ASSERT_TRUE(test_server_.Start());
context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
context().http_transaction_factory()->GetSession()->CloseAllConnections(
ERR_FAILED, "Very good reason");
scoped_refptr<X509Certificate> old_cert = test_server_.GetCertificate();
ResetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED,
SSL_PROTOCOL_VERSION_TLS1_3);
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_FALSE(old_cert->EqualsIncludingChain(r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
}
TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTLS12RejectTest) {
ASSERT_TRUE(test_server_.Start());
context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
context().http_transaction_factory()->GetSession()->CloseAllConnections(
ERR_FAILED, "Very good reason");
scoped_refptr<X509Certificate> old_cert = test_server_.GetCertificate();
ResetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED,
SSL_PROTOCOL_VERSION_TLS1_2);
{
TestDelegate d;
std::unique_ptr<URLRequest> r(context().CreateRequest(
test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
EXPECT_TRUE(r->is_pending());
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_2,
SSLConnectionStatusToVersion(r->ssl_info().connection_status));
EXPECT_TRUE(r->ssl_info().unverified_cert.get());
EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
r->ssl_info().cert.get()));
EXPECT_FALSE(old_cert->EqualsIncludingChain(r->ssl_info().cert.get()));
EXPECT_EQ("0", d.data_received());
}
}
TEST_F(URLRequestTestHTTP, AuthChallengeInfo) {
ASSERT_TRUE(http_test_server()->Start());
GURL url(http_test_server()->GetURL("/auth-basic"));
TestDelegate delegate;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
r->Start();
delegate.RunUntilComplete();
ASSERT_TRUE(r->auth_challenge_info().has_value());
EXPECT_FALSE(r->auth_challenge_info()->is_proxy);
EXPECT_EQ(url::SchemeHostPort(url), r->auth_challenge_info()->challenger);
EXPECT_EQ("basic", r->auth_challenge_info()->scheme);
EXPECT_EQ("testrealm", r->auth_challenge_info()->realm);
EXPECT_EQ("Basic realm=\"testrealm\"", r->auth_challenge_info()->challenge);
EXPECT_EQ("/auth-basic", r->auth_challenge_info()->path);
}
TEST_F(URLRequestTestHTTP, ConnectNoSupported) {
ASSERT_TRUE(http_test_server()->Start());
TestDelegate delegate;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &delegate,
TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_method("CONNECT");
r->Start();
delegate.RunUntilComplete();
EXPECT_EQ(ERR_METHOD_NOT_SUPPORTED, delegate.request_status());
}
class URLRequestDnsAliasTest : public TestWithTaskEnvironment {
protected:
URLRequestDnsAliasTest() {
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_host_resolver(std::make_unique<MockHostResolver>());
context_ = context_builder->Build();
}
URLRequestContext& context() { return *context_; }
MockHostResolver& host_resolver() {
return *static_cast<MockHostResolver*>(context_->host_resolver());
}
void SetUp() override { ASSERT_TRUE(test_server_.Start()); }
std::unique_ptr<URLRequestContext> context_;
TestDelegate test_delegate_;
EmbeddedTestServer test_server_;
};
TEST_F(URLRequestDnsAliasTest, WithDnsAliases) {
GURL url(test_server_.GetURL("www.example.test", "/echo"));
std::vector<std::string> aliases({"alias1", "alias2", "host"});
host_resolver().rules()->AddIPLiteralRuleWithDnsAliases(
"www.example.test", "127.0.0.1", std::move(aliases));
std::unique_ptr<URLRequest> request(context().CreateRequest(
url, DEFAULT_PRIORITY, &test_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
test_delegate_.RunUntilComplete();
EXPECT_THAT(test_delegate_.request_status(), IsOk());
EXPECT_THAT(request->response_info().dns_aliases,
testing::ElementsAre("alias1", "alias2", "host"));
}
TEST_F(URLRequestDnsAliasTest, NoAdditionalDnsAliases) {
GURL url(test_server_.GetURL("www.example.test", "/echo"));
host_resolver().rules()->AddIPLiteralRuleWithDnsAliases(
"www.example.test", "127.0.0.1", std::set<std::string>());
std::unique_ptr<URLRequest> request(context().CreateRequest(
url, DEFAULT_PRIORITY, &test_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
test_delegate_.RunUntilComplete();
EXPECT_THAT(test_delegate_.request_status(), IsOk());
EXPECT_THAT(request->response_info().dns_aliases,
testing::ElementsAre("www.example.test"));
}
TEST_F(URLRequestTest, SetURLChain) {
TestDelegate d;
{
GURL original_url("http://localhost");
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_EQ(r->url_chain().size(), 1u);
EXPECT_EQ(r->url_chain()[0], original_url);
const std::vector<GURL> url_chain = {
GURL("http://foo.test"),
GURL("http://bar.test"),
GURL("http://baz.test"),
};
r->SetURLChain(url_chain);
EXPECT_EQ(r->url_chain().size(), 3u);
EXPECT_EQ(r->url_chain()[0], url_chain[0]);
EXPECT_EQ(r->url_chain()[1], url_chain[1]);
EXPECT_EQ(r->url_chain()[2], original_url);
}
}
TEST_F(URLRequestTest, SetIsolationInfoFromNak) {
TestDelegate d;
SchemefulSite site_a = SchemefulSite(GURL("https://a.com/"));
SchemefulSite site_b = SchemefulSite(GURL("https://b.com/"));
base::UnguessableToken nak_nonce = base::UnguessableToken::Create();
auto populated_cross_site_nak = NetworkAnonymizationKey::CreateFromParts(
site_a, true, nak_nonce);
IsolationInfo expected_isolation_info_populated_cross_site_nak =
IsolationInfo::Create(IsolationInfo::RequestType::kOther,
url::Origin::Create(GURL("https://a.com/")),
url::Origin(), SiteForCookies(), nak_nonce);
auto populated_same_site_nak = NetworkAnonymizationKey::CreateFromParts(
site_a, false, nak_nonce);
IsolationInfo expected_isolation_info_populated_same_site_nak =
IsolationInfo::Create(IsolationInfo::RequestType::kOther,
url::Origin::Create(GURL("https://a.com/")),
url::Origin::Create(GURL("https://a.com/")),
SiteForCookies(), nak_nonce);
NetworkAnonymizationKey empty_nak;
GURL original_url("http://localhost");
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info_from_network_anonymization_key(
populated_cross_site_nak);
r->SetLoadFlags(LOAD_DISABLE_CACHE);
r->set_disallow_credentials();
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_EQ(r->isolation_info().network_anonymization_key(),
populated_cross_site_nak);
EXPECT_EQ(
r->isolation_info().top_frame_origin(),
expected_isolation_info_populated_cross_site_nak.top_frame_origin());
EXPECT_FALSE(r->isolation_info().IsEqualForTesting(
expected_isolation_info_populated_cross_site_nak));
r->set_isolation_info_from_network_anonymization_key(populated_same_site_nak);
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_EQ(r->isolation_info().network_anonymization_key(),
populated_same_site_nak);
EXPECT_TRUE(r->isolation_info().IsEqualForTesting(
expected_isolation_info_populated_same_site_nak));
r->set_isolation_info_from_network_anonymization_key(empty_nak);
EXPECT_TRUE(r->is_created_from_network_anonymization_key());
EXPECT_EQ(r->isolation_info().network_anonymization_key(), empty_nak);
EXPECT_TRUE(r->isolation_info().IsEqualForTesting(net::IsolationInfo()));
r->Start();
d.RunUntilComplete();
}
TEST_F(URLRequestTest, CookiePartitionKey) {
const url::Origin kOrigin = url::Origin::Create(GURL("http://foo.test/"));
const url::Origin kCrossSiteOrigin =
url::Origin::Create(GURL("http://b.test/"));
struct {
const GURL request_url;
IsolationInfo::RequestType request_type;
const url::Origin frame_origin;
const SiteForCookies site_for_cookies;
const url::Origin initiator;
bool expected_third_party;
std::optional<GURL> change_initator = std::nullopt;
} cases[]{
{GURL("ws://foo.test/"), IsolationInfo::RequestType::kMainFrame, kOrigin,
SiteForCookies::FromOrigin(kOrigin), kOrigin, false},
{GURL("ws://foo.test/"), IsolationInfo::RequestType::kMainFrame, kOrigin,
SiteForCookies::FromOrigin(kOrigin), kOrigin, false,
GURL("ws://b.test/")},
{GURL("ws://foo.test/"), IsolationInfo::RequestType::kSubFrame, kOrigin,
SiteForCookies(), kCrossSiteOrigin, true},
{GURL("ws://b.test/"), IsolationInfo::RequestType::kSubFrame,
kCrossSiteOrigin, SiteForCookies(), kCrossSiteOrigin, true},
{GURL("ws://b.test/"), IsolationInfo::RequestType::kSubFrame,
kCrossSiteOrigin, SiteForCookies(), kCrossSiteOrigin, true,
GURL("ws://foo.test/")},
{GURL("ws://b.test/"), IsolationInfo::RequestType::kSubFrame,
kCrossSiteOrigin, SiteForCookies::FromOrigin(kOrigin), kCrossSiteOrigin,
true},
{GURL("ws://foo.test/"), IsolationInfo::RequestType::kSubFrame, kOrigin,
SiteForCookies(), kOrigin, true},
};
for (const auto& tc : cases) {
TestDelegate d;
std::unique_ptr<URLRequest> r(default_context().CreateRequest(
tc.request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r->set_isolation_info(IsolationInfo::Create(
tc.request_type, kOrigin, tc.frame_origin, tc.site_for_cookies));
if (tc.change_initator.has_value()) {
r->set_initiator(url::Origin::Create(tc.change_initator.value()));
}
EXPECT_TRUE(r->cookie_partition_key().has_value());
EXPECT_EQ(r->cookie_partition_key()->site(), SchemefulSite(kOrigin));
EXPECT_EQ(r->cookie_partition_key()->IsThirdParty(),
tc.expected_third_party);
}
}
class URLRequestMaybeAsyncFirstPartySetsTest
: public URLRequestTest,
public testing::WithParamInterface<bool> {
public:
URLRequestMaybeAsyncFirstPartySetsTest() { CHECK(test_server_.Start()); }
std::unique_ptr<CookieStore> CreateCookieStore() {
auto cookie_monster = std::make_unique<CookieMonster>(nullptr,
nullptr);
auto cookie_access_delegate = std::make_unique<TestCookieAccessDelegate>();
cookie_access_delegate->set_invoke_callbacks_asynchronously(
invoke_callbacks_asynchronously());
cookie_monster->SetCookieAccessDelegate(std::move(cookie_access_delegate));
return cookie_monster;
}
bool invoke_callbacks_asynchronously() { return GetParam(); }
HttpTestServer& test_server() { return test_server_; }
private:
HttpTestServer test_server_;
};
TEST_P(URLRequestMaybeAsyncFirstPartySetsTest, SimpleRequest) {
const std::string kHost = "example.test";
const url::Origin kOrigin =
url::Origin::Create(test_server().GetURL(kHost, "/"));
const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCookieStore(CreateCookieStore());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
test_server().GetURL(kHost, "/echo"), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, kSiteForCookies));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(d.data_received(), "Echo");
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(req->GetResponseCode(), 200);
}
TEST_P(URLRequestMaybeAsyncFirstPartySetsTest, SingleRedirect) {
const std::string kHost = "example.test";
const url::Origin kOrigin =
url::Origin::Create(test_server().GetURL(kHost, "/"));
const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->SetCookieStore(CreateCookieStore());
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
test_server().GetURL(kHost,
base::StrCat({
"/server-redirect?",
test_server().GetURL(kHost, "/echo").spec(),
})),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_isolation_info(
IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
kOrigin, kSiteForCookies));
req->Start();
d.RunUntilComplete();
EXPECT_EQ(d.data_received(), "Echo");
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(req->GetResponseCode(), 200);
}
INSTANTIATE_TEST_SUITE_P(,
URLRequestMaybeAsyncFirstPartySetsTest,
testing::Bool());
class PartitionConnectionsByNetworkAnonymizationKey : public URLRequestTest {
public:
PartitionConnectionsByNetworkAnonymizationKey() {
scoped_feature_list_.InitAndEnableFeature(
net::features::kPartitionConnectionsByNetworkIsolationKey);
}
const SchemefulSite kTestSiteA = SchemefulSite(GURL("http://a.test/"));
const SchemefulSite kTestSiteB = SchemefulSite(GURL("http://b.test/"));
const SchemefulSite kTestSiteC = SchemefulSite(GURL("http://c.test/"));
const base::UnguessableToken kNonceA = base::UnguessableToken::Create();
const base::UnguessableToken kNonceB = base::UnguessableToken::Create();
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(PartitionConnectionsByNetworkAnonymizationKey,
DifferentTopFrameSitesNeverShareConnections) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
const auto original_url = test_server.GetURL("/echo");
const auto network_anonymization_key1 =
NetworkAnonymizationKey::CreateSameSite(kTestSiteA);
const auto network_anonymization_key2 =
NetworkAnonymizationKey::CreateSameSite(kTestSiteB);
{
TestDelegate d;
std::unique_ptr<URLRequest> r1(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r1->set_isolation_info_from_network_anonymization_key(
network_anonymization_key1);
r1->SetLoadFlags(LOAD_DISABLE_CACHE);
r1->set_disallow_credentials();
EXPECT_TRUE(r1->is_created_from_network_anonymization_key());
EXPECT_EQ(r1->isolation_info().network_anonymization_key(),
network_anonymization_key1);
r1->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r1->ssl_info().handshake_type);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> r2(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r2->set_isolation_info_from_network_anonymization_key(
network_anonymization_key2);
r2->SetLoadFlags(LOAD_DISABLE_CACHE);
r2->set_disallow_credentials();
EXPECT_TRUE(r2->is_created_from_network_anonymization_key());
EXPECT_EQ(r2->isolation_info().network_anonymization_key(),
network_anonymization_key2);
r2->Start();
d.RunUntilComplete();
EXPECT_EQ(1, d.response_started_count());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r2->ssl_info().handshake_type);
}
}
TEST_F(PartitionConnectionsByNetworkAnonymizationKey,
FirstPartyIsSeparatedFromCrossSiteFrames) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
const auto original_url = test_server.GetURL("/echo");
const auto network_anonymization_key1 =
NetworkAnonymizationKey::CreateSameSite(kTestSiteA);
const auto network_anonymization_key2 =
NetworkAnonymizationKey::CreateCrossSite(kTestSiteA);
{
TestDelegate d;
std::unique_ptr<URLRequest> r1(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r1->set_isolation_info_from_network_anonymization_key(
network_anonymization_key1);
r1->SetLoadFlags(LOAD_DISABLE_CACHE);
r1->set_disallow_credentials();
EXPECT_TRUE(r1->is_created_from_network_anonymization_key());
EXPECT_EQ(r1->isolation_info().network_anonymization_key(),
network_anonymization_key1);
r1->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r1->ssl_info().handshake_type);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> r2(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r2->set_isolation_info_from_network_anonymization_key(
network_anonymization_key2);
r2->SetLoadFlags(LOAD_DISABLE_CACHE);
r2->set_disallow_credentials();
EXPECT_TRUE(r2->is_created_from_network_anonymization_key());
EXPECT_EQ(r2->isolation_info().network_anonymization_key(),
network_anonymization_key2);
r2->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r2->ssl_info().handshake_type);
}
}
TEST_F(
PartitionConnectionsByNetworkAnonymizationKey,
DifferentCrossSiteFramesAreSeparatedOnlyWhenNetworkAnonymizationKeyIsTripleKeyed) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
const auto original_url = test_server.GetURL("/echo");
const auto network_anonymization_key1 =
NetworkAnonymizationKey::CreateCrossSite(kTestSiteA);
const auto network_anonymization_key2 =
NetworkAnonymizationKey::CreateCrossSite(kTestSiteA);
{
TestDelegate d;
std::unique_ptr<URLRequest> r1(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r1->set_isolation_info_from_network_anonymization_key(
network_anonymization_key1);
r1->SetLoadFlags(LOAD_DISABLE_CACHE);
r1->set_disallow_credentials();
EXPECT_TRUE(r1->is_created_from_network_anonymization_key());
EXPECT_EQ(r1->isolation_info().network_anonymization_key(),
network_anonymization_key1);
r1->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r1->ssl_info().handshake_type);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> r2(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r2->set_isolation_info_from_network_anonymization_key(
network_anonymization_key2);
r2->SetLoadFlags(LOAD_DISABLE_CACHE);
r2->set_disallow_credentials();
EXPECT_TRUE(r2->is_created_from_network_anonymization_key());
EXPECT_EQ(r2->isolation_info().network_anonymization_key(),
network_anonymization_key2);
r2->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, r2->ssl_info().handshake_type);
}
}
TEST_F(PartitionConnectionsByNetworkAnonymizationKey,
DifferentNoncesAreAlwaysSeparated) {
EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
const auto original_url = test_server.GetURL("/echo");
const auto network_anonymization_key1 =
NetworkAnonymizationKey::CreateFromParts(
kTestSiteA, false, kNonceA);
const auto network_anonymization_key2 =
NetworkAnonymizationKey::CreateFromParts(
kTestSiteA, false, kNonceB);
{
TestDelegate d;
std::unique_ptr<URLRequest> r1(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r1->set_isolation_info_from_network_anonymization_key(
network_anonymization_key1);
r1->SetLoadFlags(LOAD_DISABLE_CACHE);
r1->set_disallow_credentials();
EXPECT_TRUE(r1->is_created_from_network_anonymization_key());
EXPECT_EQ(r1->isolation_info().network_anonymization_key(),
network_anonymization_key1);
r1->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r1->ssl_info().handshake_type);
}
{
TestDelegate d;
std::unique_ptr<URLRequest> r2(default_context().CreateRequest(
original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
r2->set_isolation_info_from_network_anonymization_key(
network_anonymization_key2);
r2->SetLoadFlags(LOAD_DISABLE_CACHE);
r2->set_disallow_credentials();
EXPECT_TRUE(r2->is_created_from_network_anonymization_key());
EXPECT_EQ(r2->isolation_info().network_anonymization_key(),
network_anonymization_key2);
r2->Start();
d.RunUntilComplete();
EXPECT_THAT(d.request_status(), IsOk());
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r2->ssl_info().handshake_type);
}
}
class PatternedExpectBypassCacheNetworkDelegate : public TestNetworkDelegate {
public:
explicit PatternedExpectBypassCacheNetworkDelegate(
std::vector<bool> expectations)
: expectations_(std::move(expectations)) {}
~PatternedExpectBypassCacheNetworkDelegate() override {
EXPECT_TRUE(expectations_.empty());
}
int OnBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url) override {
CHECK(!expectations_.empty());
EXPECT_EQ(!!(request->load_flags() & LOAD_BYPASS_CACHE),
expectations_.front());
expectations_.erase(expectations_.begin());
return TestNetworkDelegate::OnBeforeURLRequest(request, std::move(callback),
new_url);
}
private:
std::vector<bool> expectations_;
};
TEST_F(URLRequestTest, RedirectClearsPerHopLoadFlags) {
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_delegate(
std::make_unique<PatternedExpectBypassCacheNetworkDelegate>(
std::vector({true, false})));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
https_server.GetURL(
"a.test",
base::StrCat({"/server-redirect?",
https_server.GetURL("a.test", "/echo").spec()})),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_per_hop_load_flags(LOAD_BYPASS_CACHE);
EXPECT_TRUE(req->load_flags() & LOAD_BYPASS_CACHE);
req->Start();
d.RunUntilRedirect();
EXPECT_FALSE(req->load_flags() & LOAD_BYPASS_CACHE);
req->FollowDeferredRedirect({}, {});
d.RunUntilComplete();
EXPECT_EQ(req->url().GetPath(), "/echo");
}
TEST_F(URLRequestTest, DelegateCanSetPerHopLoadFlagsDuringRedirect) {
EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
auto context_builder = CreateTestURLRequestContextBuilder();
context_builder->set_network_delegate(
std::make_unique<PatternedExpectBypassCacheNetworkDelegate>(
std::vector({false, true})));
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
https_server.GetURL(
"a.test",
base::StrCat({"/server-redirect?",
https_server.GetURL("a.test", "/echo").spec()})),
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_FALSE(req->load_flags() & LOAD_BYPASS_CACHE);
req->Start();
d.RunUntilRedirect();
EXPECT_FALSE(req->load_flags() & LOAD_BYPASS_CACHE);
req->set_per_hop_load_flags(LOAD_BYPASS_CACHE);
EXPECT_TRUE(req->load_flags() & LOAD_BYPASS_CACHE);
req->FollowDeferredRedirect({}, {});
d.RunUntilComplete();
EXPECT_EQ(req->url().GetPath(), "/echo");
}
class StorageAccessHeaderURLRequestTest : public URLRequestTestHTTP {
public:
StorageAccessHeaderURLRequestTest() = default;
~StorageAccessHeaderURLRequestTest() override {
EXPECT_TRUE(http_test_server()->ShutdownAndWaitUntilComplete());
{
base::AutoLock auto_lock(lock_);
EXPECT_TRUE(response_sequence_.empty());
}
}
void SetUp() override {
URLRequestTestHTTP::SetUp();
http_test_server()->RegisterRequestHandler(base::BindRepeating(
&StorageAccessHeaderURLRequestTest::HandleRetryRequest,
base::Unretained(this)));
ASSERT_TRUE(http_test_server()->Start());
}
enum class ResponseKind {
kOk,
kRedirect,
kAuthChallenge,
kExpectAuthCredentials,
kAuthWithoutChallenge,
};
void set_response_sequence(const std::initializer_list<ResponseKind>& kinds) {
base::AutoLock auto_lock(lock_);
response_sequence_ = kinds;
}
void set_activate_storage_access_value(std::string_view value) {
base::AutoLock auto_lock(lock_);
activate_storage_access_value_ = value;
}
protected:
static constexpr char kStorageAccessRetryPath[] =
"/retry-with-storage-access";
private:
std::unique_ptr<test_server::HttpResponse> HandleRetryRequest(
const test_server::HttpRequest& request) {
if (!base::StartsWith(request.GetURL().GetPath(),
kStorageAccessRetryPath)) {
return nullptr;
}
auto http_response = std::make_unique<test_server::BasicHttpResponse>();
http_response->set_content_type("text/plain");
ResponseKind response_kind;
{
base::AutoLock auto_lock(lock_);
http_response->AddCustomHeader("Activate-Storage-Access",
activate_storage_access_value_);
CHECK(!response_sequence_.empty());
response_kind = response_sequence_.front();
response_sequence_.erase(response_sequence_.begin());
}
switch (response_kind) {
case ResponseKind::kOk:
http_response->set_code(HTTP_OK);
return http_response;
case ResponseKind::kRedirect:
http_response->set_code(HTTP_TEMPORARY_REDIRECT);
http_response->AddCustomHeader(
"Location", http_test_server()->GetURL("/echo").spec());
return http_response;
case ResponseKind::kAuthChallenge:
return HandleAuthChallenge(request, std::move(http_response));
case ResponseKind::kExpectAuthCredentials:
return HandleExpectAuthCredentials(request, std::move(http_response));
case ResponseKind::kAuthWithoutChallenge:
http_response->set_code(HTTP_UNAUTHORIZED);
return http_response;
}
}
static std::unique_ptr<test_server::HttpResponse> HandleAuthChallenge(
const test_server::HttpRequest& request,
std::unique_ptr<test_server::BasicHttpResponse> http_response) {
EXPECT_FALSE(base::Contains(request.headers, "Authorization"));
http_response->set_code(HTTP_UNAUTHORIZED);
http_response->AddCustomHeader("WWW-Authenticate", "Basic realm=\"REALM\"");
return http_response;
}
static std::unique_ptr<test_server::HttpResponse> HandleExpectAuthCredentials(
const test_server::HttpRequest& request,
std::unique_ptr<test_server::BasicHttpResponse> http_response) {
EXPECT_TRUE(base::Contains(request.headers, "Authorization"));
std::string auth = request.headers.at("Authorization");
EXPECT_TRUE(base::Contains(auth, "Basic"));
std::string b64str = auth.substr(std::string("Basic ").size());
std::string userpass;
base::Base64Decode(b64str, &userpass);
size_t delimiter = userpass.find(":");
EXPECT_NE(delimiter, std::string::npos);
EXPECT_EQ(userpass.substr(0, delimiter), base::UTF16ToASCII(kUser));
EXPECT_EQ(userpass.substr(delimiter + 1), base::UTF16ToASCII(kSecret));
http_response->set_code(HTTP_OK);
return http_response;
}
base::Lock lock_;
std::vector<ResponseKind> response_sequence_ GUARDED_BY(lock_);
std::string activate_storage_access_value_ GUARDED_BY(lock_) =
"retry; allowed-origin=*";
};
struct StorageAccessHeaderRetryData {
std::optional<url::Origin> origin_header;
std::string activate_storage_access_value;
bool expect_retry;
};
class StorageAccessHeaderRetryURLRequestTest
: public StorageAccessHeaderURLRequestTest,
public testing::WithParamInterface<StorageAccessHeaderRetryData> {};
TEST_P(StorageAccessHeaderRetryURLRequestTest, Retry) {
const StorageAccessHeaderRetryData test = GetParam();
set_activate_storage_access_value(test.activate_storage_access_value);
std::vector<bool> pattern;
if (test.expect_retry) {
set_response_sequence({ResponseKind::kOk, ResponseKind::kOk});
pattern = {false, true};
} else {
set_response_sequence({ResponseKind::kOk});
pattern = {false};
}
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<PatternedExpectBypassCacheNetworkDelegate>(pattern));
if (test.expect_retry) {
network_delegate.set_storage_access_status(
cookie_util::StorageAccessStatus::kActive);
}
auto context = context_builder->Build();
TestDelegate d;
base::HistogramTester histogram_tester;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server()->GetURL(kStorageAccessRetryPath), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
if (test.origin_header) {
req->SetExtraRequestHeaderByName(HttpRequestHeaders::kOrigin,
test.origin_header->Serialize(),
true);
}
req->set_storage_access_status(
StorageAccessStatusCache(cookie_util::StorageAccessStatus::kInactive));
req->Start();
d.RunUntilComplete();
if (test.expect_retry) {
EXPECT_THAT(
network_delegate.cookie_setting_overrides_records(),
ElementsAre(
CookieSettingOverrides(), CookieSettingOverrides(),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader}),
CookieSettingOverrides(
{CookieSettingOverride::
kStorageAccessGrantEligibleViaHeader})));
histogram_tester.ExpectBucketCount(
"API.StorageAccessHeader.ActivateStorageAccessRetryOutcome",
net::cookie_util::ActivateStorageAccessRetryOutcome::kSuccess,
1);
histogram_tester.ExpectBucketCount(
"API.StorageAccessHeader.ActivateStorageAccessRetryOutcome",
net::cookie_util::ActivateStorageAccessRetryOutcome::
kFailureIneffectiveRetry,
1);
} else {
EXPECT_THAT(
network_delegate.cookie_setting_overrides_records(),
ElementsAre(CookieSettingOverrides(), CookieSettingOverrides()));
}
}
const StorageAccessHeaderRetryData storage_access_header_retry_tests[] = {
{std::nullopt, "", false},
{std::nullopt, "retry; allowed-origin=\"\"", false},
{std::nullopt, "retry; allowed-origin=\"null\"", false},
{std::nullopt, "retry; allowed-origin=*", true},
{std::nullopt, "retry; allowed-origin=\"https://example.test\"", false},
{url::Origin(), "retry; allowed-origin=\"null\"", true},
{url::Origin::Create(GURL("https://example.test")), "", false},
{url::Origin::Create(GURL("https://example.test")),
"retry; allowed-origin=*", true},
{url::Origin::Create(GURL("https://example.test")),
"retry; allowed-origin=\"*\"", false},
{url::Origin::Create(GURL("https://example.test")),
"retry; allowed-origin=\"https://example.test\"", true},
{url::Origin::Create(GURL("https://example.test:123")),
"retry; allowed-origin=\"https://example.test\"", false},
{url::Origin::Create(GURL("https://example.test")),
"retry; allowed-origin=\"https://example.test\", foo, bar", false},
{url::Origin::Create(GURL("https://example.test")),
"foo, retry; allowed-origin=\"https://example.test\", bar", false},
{url::Origin::Create(GURL("https://example.test")),
"foo, bar, retry; allowed-origin=\"https://example.test\"", false},
{url::Origin::Create(GURL("https://example.test")),
"retry; allowed-origin=\"https://example.test\"; foo; bar", true},
{url::Origin::Create(GURL("https://example.test")),
"retry; foo; allowed-origin=\"https://example.test\"; bar", true},
{url::Origin::Create(GURL("https://example.test")),
"retry; foo; bar; allowed-origin=\"https://example.test\"", true},
{url::Origin::Create(GURL("https://example.test")),
"retry; allowed-origin=\"https://example.test\"; "
"allowed-origin=\"https://foo.test\"",
false},
{url::Origin::Create(GURL("https://example.test")),
"retry; allowed-origin=\"https://foo.test\"; "
"allowed-origin=\"https://example.test\"",
true},
{url::Origin::Create(GURL("https://example.test")),
"bogus; allowed-origin=\"https://example.test\"", false},
{url::Origin::Create(GURL("https://example.test")),
"retry; allowed=\"https://example.test\"", false},
{url::Origin::Create(GURL("https://example.test")),
"retry; %=\"https://example.test\"", false},
{url::Origin::Create(GURL("https://example.test")),
"\"retry\"; allowed-origin=\"https://example.test\"", false},
};
INSTANTIATE_TEST_SUITE_P(,
StorageAccessHeaderRetryURLRequestTest,
testing::ValuesIn(storage_access_header_retry_tests));
TEST_F(StorageAccessHeaderURLRequestTest, RedirectPrioritizesRetryHeader) {
set_response_sequence({ResponseKind::kRedirect, ResponseKind::kRedirect});
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<PatternedExpectBypassCacheNetworkDelegate>(
std::vector({false, true, false})));
network_delegate.set_storage_access_status(
cookie_util::StorageAccessStatus::kActive);
auto context = context_builder->Build();
TestDelegate d;
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server()->GetURL(kStorageAccessRetryPath), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_storage_access_status(
StorageAccessStatusCache(cookie_util::StorageAccessStatus::kInactive));
req->Start();
d.RunUntilRedirect();
EXPECT_EQ(req->url().GetPath(), kStorageAccessRetryPath);
req->set_storage_access_status(
StorageAccessStatusCache(cookie_util::StorageAccessStatus::kActive));
req->FollowDeferredRedirect({}, {});
d.RunUntilComplete();
EXPECT_THAT(
network_delegate.cookie_setting_overrides_records(),
ElementsAre(
CookieSettingOverrides(), CookieSettingOverrides(),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader}),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader}),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader}),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader})));
EXPECT_EQ(req->url().GetPath(), "/echo");
}
TEST_F(StorageAccessHeaderURLRequestTest, AuthChallengeIgnoresRetryHeader) {
set_response_sequence({ResponseKind::kAuthChallenge,
ResponseKind::kExpectAuthCredentials,
ResponseKind::kOk});
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<PatternedExpectBypassCacheNetworkDelegate>(
std::vector({false, true})));
network_delegate.set_storage_access_status(
cookie_util::StorageAccessStatus::kActive);
auto context = context_builder->Build();
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server()->GetURL(kStorageAccessRetryPath), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_storage_access_status(
StorageAccessStatusCache(cookie_util::StorageAccessStatus::kInactive));
req->Start();
d.RunUntilComplete();
EXPECT_THAT(
network_delegate.cookie_setting_overrides_records(),
ElementsAre(
CookieSettingOverrides(), CookieSettingOverrides(),
CookieSettingOverrides(),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader}),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader})));
EXPECT_TRUE(d.auth_required_called());
}
TEST_F(StorageAccessHeaderURLRequestTest,
AuthWithoutChallengeHonorsRetryHeader) {
set_response_sequence(
{ResponseKind::kAuthWithoutChallenge, ResponseKind::kOk});
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<PatternedExpectBypassCacheNetworkDelegate>(
std::vector({false, true})));
network_delegate.set_storage_access_status(
cookie_util::StorageAccessStatus::kActive);
auto context = context_builder->Build();
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server()->GetURL(kStorageAccessRetryPath), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_storage_access_status(
StorageAccessStatusCache(cookie_util::StorageAccessStatus::kInactive));
req->Start();
d.RunUntilComplete();
EXPECT_THAT(
network_delegate.cookie_setting_overrides_records(),
ElementsAre(
CookieSettingOverrides(), CookieSettingOverrides(),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader}),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader})));
EXPECT_FALSE(d.auth_required_called());
}
TEST_F(StorageAccessHeaderURLRequestTest, SurvivesPostAuthRetries) {
set_response_sequence({ResponseKind::kOk, ResponseKind::kAuthChallenge,
ResponseKind::kExpectAuthCredentials});
auto context_builder = CreateTestURLRequestContextBuilder();
auto& network_delegate = *context_builder->set_network_delegate(
std::make_unique<PatternedExpectBypassCacheNetworkDelegate>(
std::vector({false, true})));
network_delegate.set_storage_access_status(
cookie_util::StorageAccessStatus::kActive);
auto context = context_builder->Build();
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
std::unique_ptr<URLRequest> req(context->CreateRequest(
http_test_server()->GetURL(kStorageAccessRetryPath), DEFAULT_PRIORITY, &d,
TRAFFIC_ANNOTATION_FOR_TESTS));
req->set_storage_access_status(
StorageAccessStatusCache(cookie_util::StorageAccessStatus::kInactive));
req->Start();
d.RunUntilComplete();
EXPECT_THAT(
network_delegate.cookie_setting_overrides_records(),
ElementsAre(
CookieSettingOverrides(), CookieSettingOverrides(),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader}),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader}),
CookieSettingOverrides(
{CookieSettingOverride::kStorageAccessGrantEligibleViaHeader})));
EXPECT_TRUE(d.auth_required_called());
}
#if BUILDFLAG(ARKWEB_UNITTESTS)
#include "arkweb/chromium_ext/net/url_request/url_request_for_include_unittest.cc"
#endif
}