| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/url_request/url_request_http_job.h" |
| |
| #include <cstddef> |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/compiler_specific.h" |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/run_loop.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "net/base/auth.h" |
| #include "net/base/request_priority.h" |
| #include "net/cert/ct_policy_status.h" |
| #include "net/cookies/cookie_store_test_helpers.h" |
| #include "net/http/http_transaction_factory.h" |
| #include "net/http/http_transaction_test_util.h" |
| #include "net/log/net_log_event_type.h" |
| #include "net/log/test_net_log.h" |
| #include "net/log/test_net_log_entry.h" |
| #include "net/log/test_net_log_util.h" |
| #include "net/net_buildflags.h" |
| #include "net/socket/next_proto.h" |
| #include "net/socket/socket_test_util.h" |
| #include "net/test/cert_test_util.h" |
| #include "net/test/gtest_util.h" |
| #include "net/test/test_data_directory.h" |
| #include "net/test/test_with_scoped_task_environment.h" |
| #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" |
| #include "net/url_request/url_request.h" |
| #include "net/url_request/url_request_job_factory_impl.h" |
| #include "net/url_request/url_request_status.h" |
| #include "net/url_request/url_request_test_util.h" |
| #include "net/url_request/websocket_handshake_userdata_key.h" |
| #include "net/websockets/websocket_test_util.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| #include "url/url_constants.h" |
| |
| #if defined(OS_ANDROID) |
| #include "base/android/jni_android.h" |
| #include "jni/AndroidNetworkLibraryTestUtil_jni.h" |
| #include "starboard/types.h" |
| #endif |
| |
| using net::test::IsError; |
| using net::test::IsOk; |
| |
| namespace net { |
| |
| namespace { |
| |
| using ::testing::Return; |
| |
| const char kSimpleGetMockWrite[] = |
| "GET / HTTP/1.1\r\n" |
| "Host: www.example.com\r\n" |
| "Connection: keep-alive\r\n" |
| "User-Agent: \r\n" |
| "Accept-Encoding: gzip, deflate\r\n" |
| "Accept-Language: en-us,fr\r\n\r\n"; |
| |
| const char kSimpleHeadMockWrite[] = |
| "HEAD / HTTP/1.1\r\n" |
| "Host: www.example.com\r\n" |
| "Connection: keep-alive\r\n" |
| "User-Agent: \r\n" |
| "Accept-Encoding: gzip, deflate\r\n" |
| "Accept-Language: en-us,fr\r\n\r\n"; |
| |
| const char kTrustAnchorRequestHistogram[] = |
| "Net.Certificate.TrustAnchor.Request"; |
| |
| const char kCTComplianceHistogramName[] = |
| "Net.CertificateTransparency.RequestComplianceStatus"; |
| const char kCTRequiredHistogramName[] = |
| "Net.CertificateTransparency.CTRequiredRequestComplianceStatus"; |
| |
| // Inherit from URLRequestHttpJob to expose the priority and some |
| // other hidden functions. |
| class TestURLRequestHttpJob : public URLRequestHttpJob { |
| public: |
| explicit TestURLRequestHttpJob(URLRequest* request) |
| : URLRequestHttpJob(request, |
| request->context()->network_delegate(), |
| request->context()->http_user_agent_settings()), |
| use_null_source_stream_(false) {} |
| |
| ~TestURLRequestHttpJob() override = default; |
| |
| // URLRequestJob implementation: |
| std::unique_ptr<SourceStream> SetUpSourceStream() override { |
| if (use_null_source_stream_) |
| return nullptr; |
| return URLRequestHttpJob::SetUpSourceStream(); |
| } |
| |
| void set_use_null_source_stream(bool use_null_source_stream) { |
| use_null_source_stream_ = use_null_source_stream; |
| } |
| |
| using URLRequestHttpJob::SetPriority; |
| using URLRequestHttpJob::Start; |
| using URLRequestHttpJob::Kill; |
| using URLRequestHttpJob::priority; |
| |
| private: |
| bool use_null_source_stream_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestURLRequestHttpJob); |
| }; |
| |
| class URLRequestHttpJobSetUpSourceTest : public TestWithScopedTaskEnvironment { |
| public: |
| URLRequestHttpJobSetUpSourceTest() : context_(true) { |
| test_job_interceptor_ = new TestJobInterceptor(); |
| EXPECT_TRUE(test_job_factory_.SetProtocolHandler( |
| url::kHttpScheme, base::WrapUnique(test_job_interceptor_))); |
| context_.set_job_factory(&test_job_factory_); |
| context_.set_client_socket_factory(&socket_factory_); |
| context_.Init(); |
| } |
| |
| protected: |
| MockClientSocketFactory socket_factory_; |
| // |test_job_interceptor_| is owned by |test_job_factory_|. |
| TestJobInterceptor* test_job_interceptor_; |
| URLRequestJobFactoryImpl test_job_factory_; |
| |
| TestURLRequestContext context_; |
| TestDelegate delegate_; |
| }; |
| |
| // Tests that if SetUpSourceStream() returns nullptr, the request fails. |
| TEST_F(URLRequestHttpJobSetUpSourceTest, SetUpSourceFails) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| std::unique_ptr<URLRequest> request = |
| context_.CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS); |
| auto job = std::make_unique<TestURLRequestHttpJob>(request.get()); |
| job->set_use_null_source_stream(true); |
| test_job_interceptor_->set_main_intercept_job(std::move(job)); |
| request->Start(); |
| |
| delegate_.RunUntilComplete(); |
| EXPECT_EQ(ERR_CONTENT_DECODING_INIT_FAILED, delegate_.request_status()); |
| } |
| |
| // Tests that if there is an unknown content-encoding type, the raw response |
| // body is passed through. |
| TEST_F(URLRequestHttpJobSetUpSourceTest, UnknownEncoding) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Encoding: foo, gzip\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| std::unique_ptr<URLRequest> request = |
| context_.CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS); |
| auto job = std::make_unique<TestURLRequestHttpJob>(request.get()); |
| test_job_interceptor_->set_main_intercept_job(std::move(job)); |
| request->Start(); |
| |
| delegate_.RunUntilComplete(); |
| EXPECT_EQ(OK, delegate_.request_status()); |
| EXPECT_EQ("Test Content", delegate_.data_received()); |
| } |
| |
| class URLRequestHttpJobWithProxy : public WithScopedTaskEnvironment { |
| public: |
| explicit URLRequestHttpJobWithProxy( |
| std::unique_ptr<ProxyResolutionService> proxy_resolution_service) |
| : proxy_resolution_service_(std::move(proxy_resolution_service)), |
| context_(new TestURLRequestContext(true)) { |
| context_->set_client_socket_factory(&socket_factory_); |
| context_->set_network_delegate(&network_delegate_); |
| context_->set_proxy_resolution_service(proxy_resolution_service_.get()); |
| context_->Init(); |
| } |
| |
| MockClientSocketFactory socket_factory_; |
| TestNetworkDelegate network_delegate_; |
| std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; |
| std::unique_ptr<TestURLRequestContext> context_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(URLRequestHttpJobWithProxy); |
| }; |
| |
| // Tests that when proxy is not used, the proxy server is set correctly on the |
| // URLRequest. |
| TEST(URLRequestHttpJobWithProxy, TestFailureWithoutProxy) { |
| URLRequestHttpJobWithProxy http_job_with_proxy(nullptr); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET)}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| http_job_with_proxy.socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| http_job_with_proxy.context_->CreateRequest( |
| GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_CONNECTION_RESET)); |
| EXPECT_EQ(ProxyServer::Direct(), request->proxy_server()); |
| EXPECT_FALSE(request->was_fetched_via_proxy()); |
| EXPECT_EQ(0, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| http_job_with_proxy.network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ( |
| CountReadBytes(reads), |
| http_job_with_proxy.network_delegate_.total_network_bytes_received()); |
| } |
| |
| // Tests that when one proxy is in use and the connection to the proxy server |
| // fails, the proxy server is still set correctly on the URLRequest. |
| TEST(URLRequestHttpJobWithProxy, TestSuccessfulWithOneProxy) { |
| const char kSimpleProxyGetMockWrite[] = |
| "GET http://www.example.com/ HTTP/1.1\r\n" |
| "Host: www.example.com\r\n" |
| "Proxy-Connection: keep-alive\r\n" |
| "User-Agent: \r\n" |
| "Accept-Encoding: gzip, deflate\r\n" |
| "Accept-Language: en-us,fr\r\n\r\n"; |
| |
| const ProxyServer proxy_server = |
| ProxyServer::FromURI("http://origin.net:80", ProxyServer::SCHEME_HTTP); |
| |
| std::unique_ptr<ProxyResolutionService> proxy_resolution_service = |
| ProxyResolutionService::CreateFixedFromPacResult( |
| proxy_server.ToPacString(), TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| MockWrite writes[] = {MockWrite(kSimpleProxyGetMockWrite)}; |
| MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET)}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| |
| URLRequestHttpJobWithProxy http_job_with_proxy( |
| std::move(proxy_resolution_service)); |
| http_job_with_proxy.socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| http_job_with_proxy.context_->CreateRequest( |
| GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_CONNECTION_RESET)); |
| // When request fails due to proxy connection errors, the proxy server should |
| // still be set on the |request|. |
| EXPECT_EQ(proxy_server, request->proxy_server()); |
| #ifndef HTTP_CACHE_DISABLED_FOR_STARBOARD |
| // This bool is set by HttpNetworkTransaction but not by HTTPCacheTransaction. |
| // If Cobalt use HTTPNetworkLayer instead of HTTPCache as the transaction |
| // factory, the behavior is then different in this case. |
| // HTTPNetworkTransaction sets this boolean in OnStreamReady which is called |
| // after successfully creating a stream. It's arguable wheather this boolean |
| // should be set at this moment or not. |
| // But since the request fails here, was_fetched_via_proxy is meaningless and |
| // unimportant. |
| EXPECT_FALSE(request->was_fetched_via_proxy()); |
| #endif |
| EXPECT_EQ(0, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(0, request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| http_job_with_proxy.network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ( |
| 0, http_job_with_proxy.network_delegate_.total_network_bytes_received()); |
| } |
| |
| // Tests that when two proxies are in use and the connection to the first proxy |
| // server fails, the proxy server is set correctly on the URLRequest. |
| TEST(URLRequestHttpJobWithProxy, |
| TestContentLengthSuccessfulRequestWithTwoProxies) { |
| const ProxyServer proxy_server = |
| ProxyServer::FromURI("http://origin.net:80", ProxyServer::SCHEME_HTTP); |
| |
| // Connection to |proxy_server| would fail. Request should be fetched over |
| // DIRECT. |
| std::unique_ptr<ProxyResolutionService> proxy_resolution_service = |
| ProxyResolutionService::CreateFixedFromPacResult( |
| proxy_server.ToPacString() + "; " + |
| ProxyServer::Direct().ToPacString(), |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content"), MockRead(ASYNC, OK)}; |
| |
| MockConnect mock_connect_1(SYNCHRONOUS, ERR_CONNECTION_RESET); |
| StaticSocketDataProvider connect_data_1; |
| connect_data_1.set_connect_data(mock_connect_1); |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| |
| URLRequestHttpJobWithProxy http_job_with_proxy( |
| std::move(proxy_resolution_service)); |
| http_job_with_proxy.socket_factory_.AddSocketDataProvider(&connect_data_1); |
| http_job_with_proxy.socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| http_job_with_proxy.context_->CreateRequest( |
| GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(ProxyServer::Direct(), request->proxy_server()); |
| EXPECT_FALSE(request->was_fetched_via_proxy()); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| http_job_with_proxy.network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ( |
| CountReadBytes(reads), |
| http_job_with_proxy.network_delegate_.total_network_bytes_received()); |
| } |
| |
| class URLRequestHttpJobTest : public TestWithScopedTaskEnvironment { |
| protected: |
| URLRequestHttpJobTest() : context_(true) { |
| context_.set_http_transaction_factory(&network_layer_); |
| |
| // The |test_job_factory_| takes ownership of the interceptor. |
| test_job_interceptor_ = new TestJobInterceptor(); |
| EXPECT_TRUE(test_job_factory_.SetProtocolHandler( |
| url::kHttpScheme, base::WrapUnique(test_job_interceptor_))); |
| context_.set_job_factory(&test_job_factory_); |
| context_.set_net_log(&net_log_); |
| context_.Init(); |
| |
| req_ = |
| context_.CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS); |
| } |
| |
| MockNetworkLayer network_layer_; |
| |
| // |test_job_interceptor_| is owned by |test_job_factory_|. |
| TestJobInterceptor* test_job_interceptor_; |
| URLRequestJobFactoryImpl test_job_factory_; |
| |
| TestURLRequestContext context_; |
| TestDelegate delegate_; |
| TestNetLog net_log_; |
| std::unique_ptr<URLRequest> req_; |
| }; |
| |
| class URLRequestHttpJobWithMockSocketsTest |
| : public TestWithScopedTaskEnvironment { |
| protected: |
| URLRequestHttpJobWithMockSocketsTest() |
| : context_(new TestURLRequestContext(true)) { |
| context_->set_client_socket_factory(&socket_factory_); |
| context_->set_network_delegate(&network_delegate_); |
| context_->Init(); |
| } |
| |
| MockClientSocketFactory socket_factory_; |
| TestNetworkDelegate network_delegate_; |
| std::unique_ptr<TestURLRequestContext> context_; |
| }; |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestContentLengthSuccessfulRequest) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(reads), |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| // Tests a successful HEAD request. |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, TestSuccessfulHead) { |
| MockWrite writes[] = {MockWrite(kSimpleHeadMockWrite)}; |
| MockRead reads[] = { |
| MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 0\r\n\r\n")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->set_method("HEAD"); |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(0, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(reads), |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| // Similar to above test but tests that even if response body is there in the |
| // HEAD response stream, it should not be read due to HttpStreamParser's logic. |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, TestSuccessfulHeadWithContent) { |
| MockWrite writes[] = {MockWrite(kSimpleHeadMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->set_method("HEAD"); |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(0, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads) - 12, request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(reads) - 12, |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| #if !defined(HTTP_CACHE_DISABLED_FOR_STARBOARD) |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, TestSuccessfulCachedHeadRequest) { |
| // Cache the response. |
| { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(reads), |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| // Send a HEAD request for the cached response. |
| { |
| MockWrite writes[] = {MockWrite(kSimpleHeadMockWrite)}; |
| MockRead reads[] = { |
| MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 0\r\n\r\n")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| // Use the cached version. |
| request->SetLoadFlags(LOAD_SKIP_CACHE_VALIDATION); |
| request->set_method("HEAD"); |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(0, request->received_response_content_length()); |
| EXPECT_EQ(0, request->GetTotalSentBytes()); |
| EXPECT_EQ(0, request->GetTotalReceivedBytes()); |
| } |
| } |
| #endif |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestContentLengthSuccessfulHttp09Request) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("Test Content"), |
| MockRead(net::SYNCHRONOUS, net::OK)}; |
| |
| StaticSocketDataProvider socket_data(reads, base::span<MockWrite>()); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(reads), |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, TestContentLengthFailedRequest) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 20\r\n\r\n"), |
| MockRead("Test Content"), |
| MockRead(net::SYNCHRONOUS, net::ERR_FAILED)}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_FAILED)); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(reads), |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestContentLengthCancelledRequest) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 20\r\n\r\n"), |
| MockRead("Test Content"), |
| MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| delegate.set_cancel_in_received_data(true); |
| request->Start(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_ABORTED)); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(reads), |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestRawHeaderSizeSuccessfullRequest) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| |
| const std::string& response_header = |
| "HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"; |
| const std::string& content_data = "Test Content"; |
| |
| MockRead reads[] = {MockRead(response_header.c_str()), |
| MockRead(content_data.c_str()), |
| MockRead(net::SYNCHRONOUS, net::OK)}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_EQ(net::OK, request->status().error()); |
| EXPECT_EQ(static_cast<int>(content_data.size()), |
| request->received_response_content_length()); |
| EXPECT_EQ(static_cast<int>(response_header.size()), |
| request->raw_header_size()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestRawHeaderSizeSuccessfull100ContinueRequest) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| |
| const std::string& continue_header = "HTTP/1.1 100 Continue\r\n\r\n"; |
| const std::string& response_header = |
| "HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"; |
| const std::string& content_data = "Test Content"; |
| |
| MockRead reads[] = { |
| MockRead(continue_header.c_str()), MockRead(response_header.c_str()), |
| MockRead(content_data.c_str()), MockRead(net::SYNCHRONOUS, net::OK)}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_EQ(net::OK, request->status().error()); |
| EXPECT_EQ(static_cast<int>(content_data.size()), |
| request->received_response_content_length()); |
| EXPECT_EQ(static_cast<int>(continue_header.size() + response_header.size()), |
| request->raw_header_size()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestRawHeaderSizeFailureTruncatedHeaders) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.0 200 OK\r\n" |
| "Content-Len"), |
| MockRead(net::SYNCHRONOUS, net::OK)}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| delegate.set_cancel_in_response_started(true); |
| request->Start(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_EQ(ERR_ABORTED, request->status().error()); |
| EXPECT_EQ(0, request->received_response_content_length()); |
| EXPECT_EQ(28, request->raw_header_size()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestRawHeaderSizeSuccessfullContinuiousRead) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| const std::string& header_data = |
| "HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"; |
| const std::string& content_data = "Test Content"; |
| std::string single_read_content = header_data; |
| single_read_content.append(content_data); |
| MockRead reads[] = {MockRead(single_read_content.c_str())}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_EQ(net::OK, request->status().error()); |
| EXPECT_EQ(static_cast<int>(content_data.size()), |
| request->received_response_content_length()); |
| EXPECT_EQ(static_cast<int>(header_data.size()), request->raw_header_size()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestNetworkBytesRedirectedRequest) { |
| MockWrite redirect_writes[] = { |
| MockWrite("GET / HTTP/1.1\r\n" |
| "Host: www.redirect.com\r\n" |
| "Connection: keep-alive\r\n" |
| "User-Agent: \r\n" |
| "Accept-Encoding: gzip, deflate\r\n" |
| "Accept-Language: en-us,fr\r\n\r\n")}; |
| |
| MockRead redirect_reads[] = { |
| MockRead("HTTP/1.1 302 Found\r\n" |
| "Location: http://www.example.com\r\n\r\n"), |
| }; |
| StaticSocketDataProvider redirect_socket_data(redirect_reads, |
| redirect_writes); |
| socket_factory_.AddSocketDataProvider(&redirect_socket_data); |
| |
| MockWrite final_writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead final_reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider final_socket_data(final_reads, final_writes); |
| socket_factory_.AddSocketDataProvider(&final_socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.redirect.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| ASSERT_TRUE(request->is_pending()); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| // Should not include the redirect. |
| EXPECT_EQ(CountWriteBytes(final_writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(final_reads), request->GetTotalReceivedBytes()); |
| // Should include the redirect as well as the final response. |
| EXPECT_EQ(CountWriteBytes(redirect_writes) + CountWriteBytes(final_writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(redirect_reads) + CountReadBytes(final_reads), |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestNetworkBytesCancelledAfterHeaders) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n\r\n")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| delegate.set_cancel_in_response_started(true); |
| request->Start(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_ABORTED)); |
| EXPECT_EQ(0, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| EXPECT_EQ(CountWriteBytes(writes), |
| network_delegate_.total_network_bytes_sent()); |
| EXPECT_EQ(CountReadBytes(reads), |
| network_delegate_.total_network_bytes_received()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestNetworkBytesCancelledImmediately) { |
| StaticSocketDataProvider socket_data; |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| request->Cancel(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_ABORTED)); |
| EXPECT_EQ(0, request->received_response_content_length()); |
| EXPECT_EQ(0, request->GetTotalSentBytes()); |
| EXPECT_EQ(0, request->GetTotalReceivedBytes()); |
| EXPECT_EQ(0, network_delegate_.total_network_bytes_received()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, TestHttpTimeToFirstByte) { |
| base::HistogramTester histograms; |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| histograms.ExpectTotalCount("Net.HttpTimeToFirstByte", 0); |
| |
| request->Start(); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| histograms.ExpectTotalCount("Net.HttpTimeToFirstByte", 1); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpTimeToFirstByteForCancelledTask) { |
| base::HistogramTester histograms; |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| request->Cancel(); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_ABORTED)); |
| histograms.ExpectTotalCount("Net.HttpTimeToFirstByte", 0); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpJobSuccessPriorityKeyedTotalTime) { |
| base::HistogramTester histograms; |
| |
| for (int priority = 0; priority < net::NUM_PRIORITIES; ++priority) { |
| for (int request_index = 0; request_index <= priority; ++request_index) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com/"), |
| static_cast<net::RequestPriority>(priority), |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| } |
| } |
| |
| for (int priority = 0; priority < net::NUM_PRIORITIES; ++priority) { |
| histograms.ExpectTotalCount( |
| "Net.HttpJob.TotalTimeSuccess.Priority" + base::IntToString(priority), |
| priority + 1); |
| } |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpJobRecordsTrustAnchorHistograms) { |
| SSLSocketDataProvider ssl_socket_data(net::ASYNC, net::OK); |
| ssl_socket_data.ssl_info.cert = |
| ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); |
| // Simulate a certificate chain issued by "C=US, O=Google Trust Services LLC, |
| // CN=GTS Root R4". This publicly-trusted root was chosen as it was included |
| // in 2017 and is not anticipated to be removed from all supported platforms |
| // for a few decades. |
| // Note: The actual cert in |cert| does not matter for this testing. |
| SHA256HashValue leaf_hash = {{0}}; |
| SHA256HashValue intermediate_hash = {{1}}; |
| SHA256HashValue root_hash = { |
| {0x98, 0x47, 0xe5, 0x65, 0x3e, 0x5e, 0x9e, 0x84, 0x75, 0x16, 0xe5, |
| 0xcb, 0x81, 0x86, 0x06, 0xaa, 0x75, 0x44, 0xa1, 0x9b, 0xe6, 0x7f, |
| 0xd7, 0x36, 0x6d, 0x50, 0x69, 0x88, 0xe8, 0xd8, 0x43, 0x47}}; |
| ssl_socket_data.ssl_info.public_key_hashes.push_back(HashValue(leaf_hash)); |
| ssl_socket_data.ssl_info.public_key_hashes.push_back( |
| HashValue(intermediate_hash)); |
| ssl_socket_data.ssl_info.public_key_hashes.push_back(HashValue(root_hash)); |
| |
| const base::HistogramBase::Sample kGTSRootR4HistogramID = 486; |
| |
| socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| base::HistogramTester histograms; |
| histograms.ExpectTotalCount(kTrustAnchorRequestHistogram, 0); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("https://www.example.com/"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| |
| histograms.ExpectTotalCount(kTrustAnchorRequestHistogram, 1); |
| histograms.ExpectUniqueSample(kTrustAnchorRequestHistogram, |
| kGTSRootR4HistogramID, 1); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpJobDoesNotRecordTrustAnchorHistogramsWhenNoNetworkLoad) { |
| SSLSocketDataProvider ssl_socket_data(net::ASYNC, net::OK); |
| ssl_socket_data.ssl_info.cert = |
| ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); |
| // Simulate a request loaded from a non-network source, such as a disk |
| // cache. |
| ssl_socket_data.ssl_info.public_key_hashes.clear(); |
| |
| socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| base::HistogramTester histograms; |
| histograms.ExpectTotalCount(kTrustAnchorRequestHistogram, 0); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("https://www.example.com/"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| |
| histograms.ExpectTotalCount(kTrustAnchorRequestHistogram, 0); |
| } |
| |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpJobRecordsMostSpecificTrustAnchorHistograms) { |
| SSLSocketDataProvider ssl_socket_data(net::ASYNC, net::OK); |
| ssl_socket_data.ssl_info.cert = |
| ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); |
| // Simulate a certificate chain issued by "C=US, O=Google Trust Services LLC, |
| // CN=GTS Root R4". This publicly-trusted root was chosen as it was included |
| // in 2017 and is not anticipated to be removed from all supported platforms |
| // for a few decades. |
| // Note: The actual cert in |cert| does not matter for this testing. |
| SHA256HashValue leaf_hash = {{0}}; |
| SHA256HashValue intermediate_hash = {{1}}; |
| SHA256HashValue gts_root_r3_hash = { |
| {0x41, 0x79, 0xed, 0xd9, 0x81, 0xef, 0x74, 0x74, 0x77, 0xb4, 0x96, |
| 0x26, 0x40, 0x8a, 0xf4, 0x3d, 0xaa, 0x2c, 0xa7, 0xab, 0x7f, 0x9e, |
| 0x08, 0x2c, 0x10, 0x60, 0xf8, 0x40, 0x96, 0x77, 0x43, 0x48}}; |
| SHA256HashValue gts_root_r4_hash = { |
| {0x98, 0x47, 0xe5, 0x65, 0x3e, 0x5e, 0x9e, 0x84, 0x75, 0x16, 0xe5, |
| 0xcb, 0x81, 0x86, 0x06, 0xaa, 0x75, 0x44, 0xa1, 0x9b, 0xe6, 0x7f, |
| 0xd7, 0x36, 0x6d, 0x50, 0x69, 0x88, 0xe8, 0xd8, 0x43, 0x47}}; |
| ssl_socket_data.ssl_info.public_key_hashes.push_back(HashValue(leaf_hash)); |
| ssl_socket_data.ssl_info.public_key_hashes.push_back( |
| HashValue(intermediate_hash)); |
| ssl_socket_data.ssl_info.public_key_hashes.push_back( |
| HashValue(gts_root_r3_hash)); |
| ssl_socket_data.ssl_info.public_key_hashes.push_back( |
| HashValue(gts_root_r4_hash)); |
| |
| const base::HistogramBase::Sample kGTSRootR3HistogramID = 485; |
| |
| socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| base::HistogramTester histograms; |
| histograms.ExpectTotalCount(kTrustAnchorRequestHistogram, 0); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("https://www.example.com/"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| |
| histograms.ExpectTotalCount(kTrustAnchorRequestHistogram, 1); |
| histograms.ExpectUniqueSample(kTrustAnchorRequestHistogram, |
| kGTSRootR3HistogramID, 1); |
| } |
| |
| // Tests that the CT compliance histogram is recorded, even if CT is not |
| // required. |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpJobRecordsCTComplianceHistograms) { |
| SSLSocketDataProvider ssl_socket_data(net::ASYNC, net::OK); |
| ssl_socket_data.ssl_info.cert = |
| ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); |
| ssl_socket_data.ssl_info.is_issued_by_known_root = true; |
| ssl_socket_data.ssl_info.ct_policy_compliance_required = false; |
| ssl_socket_data.ssl_info.ct_policy_compliance = |
| ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS; |
| |
| socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| base::HistogramTester histograms; |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("https://www.example.com/"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| |
| histograms.ExpectUniqueSample( |
| kCTComplianceHistogramName, |
| static_cast<int32_t>(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS), |
| 1); |
| // CTRequiredRequestComplianceStatus should *not* have been recorded because |
| // it is only recorded for requests which are required to be compliant. |
| histograms.ExpectTotalCount(kCTRequiredHistogramName, 0); |
| } |
| |
| // Tests that the CT compliance histograms are not recorded for |
| // locally-installed trust anchors. |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpJobDoesNotRecordCTComplianceHistogramsForLocalRoot) { |
| SSLSocketDataProvider ssl_socket_data(net::ASYNC, net::OK); |
| ssl_socket_data.ssl_info.cert = |
| ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); |
| ssl_socket_data.ssl_info.is_issued_by_known_root = false; |
| ssl_socket_data.ssl_info.ct_policy_compliance_required = false; |
| ssl_socket_data.ssl_info.ct_policy_compliance = |
| ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS; |
| |
| socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| base::HistogramTester histograms; |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("https://www.example.com/"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| |
| histograms.ExpectTotalCount(kCTComplianceHistogramName, 0); |
| histograms.ExpectTotalCount(kCTRequiredHistogramName, 0); |
| } |
| |
| // Tests that the CT compliance histogram is recorded when CT is required but |
| // not compliant. |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpJobRecordsCTRequiredHistogram) { |
| SSLSocketDataProvider ssl_socket_data(net::ASYNC, net::OK); |
| ssl_socket_data.ssl_info.cert = |
| ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); |
| ssl_socket_data.ssl_info.is_issued_by_known_root = true; |
| ssl_socket_data.ssl_info.ct_policy_compliance_required = true; |
| ssl_socket_data.ssl_info.ct_policy_compliance = |
| ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS; |
| |
| socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| base::HistogramTester histograms; |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("https://www.example.com/"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| |
| histograms.ExpectUniqueSample( |
| kCTComplianceHistogramName, |
| static_cast<int32_t>(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS), |
| 1); |
| histograms.ExpectUniqueSample( |
| kCTRequiredHistogramName, |
| static_cast<int32_t>(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS), |
| 1); |
| } |
| |
| // Tests that the CT compliance histograms are not recorded when there is an |
| // unrelated certificate error. |
| TEST_F(URLRequestHttpJobWithMockSocketsTest, |
| TestHttpJobDoesNotRecordCTHistogramWithCertError) { |
| SSLSocketDataProvider ssl_socket_data(net::ASYNC, net::OK); |
| ssl_socket_data.ssl_info.cert = |
| ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); |
| ssl_socket_data.ssl_info.is_issued_by_known_root = true; |
| ssl_socket_data.ssl_info.ct_policy_compliance_required = true; |
| ssl_socket_data.ssl_info.ct_policy_compliance = |
| ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS; |
| ssl_socket_data.ssl_info.cert_status = net::CERT_STATUS_DATE_INVALID; |
| |
| socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data); |
| |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| base::HistogramTester histograms; |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = context_->CreateRequest( |
| GURL("https://www.example.com/"), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| |
| histograms.ExpectTotalCount(kCTComplianceHistogramName, 0); |
| histograms.ExpectTotalCount(kCTRequiredHistogramName, 0); |
| } |
| |
| TEST_F(URLRequestHttpJobTest, TestCancelWhileReadingCookies) { |
| DelayedCookieMonster cookie_monster; |
| TestURLRequestContext context(true); |
| context.set_cookie_store(&cookie_monster); |
| context.Init(); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context.CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| |
| request->Start(); |
| request->Cancel(); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_ABORTED)); |
| } |
| |
| // Make sure that SetPriority actually sets the URLRequestHttpJob's |
| // priority, before start. Other tests handle the after start case. |
| TEST_F(URLRequestHttpJobTest, SetPriorityBasic) { |
| auto job = std::make_unique<TestURLRequestHttpJob>(req_.get()); |
| EXPECT_EQ(DEFAULT_PRIORITY, job->priority()); |
| |
| job->SetPriority(LOWEST); |
| EXPECT_EQ(LOWEST, job->priority()); |
| |
| job->SetPriority(LOW); |
| EXPECT_EQ(LOW, job->priority()); |
| } |
| |
| // Make sure that URLRequestHttpJob passes on its priority to its |
| // transaction on start. |
| TEST_F(URLRequestHttpJobTest, SetTransactionPriorityOnStart) { |
| test_job_interceptor_->set_main_intercept_job( |
| std::make_unique<TestURLRequestHttpJob>(req_.get())); |
| req_->SetPriority(LOW); |
| |
| EXPECT_FALSE(network_layer_.last_transaction()); |
| |
| req_->Start(); |
| |
| ASSERT_TRUE(network_layer_.last_transaction()); |
| EXPECT_EQ(LOW, network_layer_.last_transaction()->priority()); |
| } |
| |
| // Make sure that URLRequestHttpJob passes on its priority updates to |
| // its transaction. |
| TEST_F(URLRequestHttpJobTest, SetTransactionPriority) { |
| test_job_interceptor_->set_main_intercept_job( |
| std::make_unique<TestURLRequestHttpJob>(req_.get())); |
| req_->SetPriority(LOW); |
| req_->Start(); |
| ASSERT_TRUE(network_layer_.last_transaction()); |
| EXPECT_EQ(LOW, network_layer_.last_transaction()->priority()); |
| |
| req_->SetPriority(HIGHEST); |
| EXPECT_EQ(HIGHEST, network_layer_.last_transaction()->priority()); |
| } |
| |
| TEST_F(URLRequestHttpJobTest, HSTSInternalRedirectTest) { |
| // Setup HSTS state. |
| context_.transport_security_state()->AddHSTS( |
| "upgrade.test", base::Time::Now() + base::TimeDelta::FromSeconds(10), |
| true); |
| ASSERT_TRUE( |
| context_.transport_security_state()->ShouldUpgradeToSSL("upgrade.test")); |
| ASSERT_FALSE(context_.transport_security_state()->ShouldUpgradeToSSL( |
| "no-upgrade.test")); |
| |
| struct TestCase { |
| const char* url; |
| bool upgrade_expected; |
| const char* url_expected; |
| } cases[] = { |
| {"http://upgrade.test/", true, "https://upgrade.test/"}, |
| {"http://upgrade.test:123/", true, "https://upgrade.test:123/"}, |
| {"http://no-upgrade.test/", false, "http://no-upgrade.test/"}, |
| {"http://no-upgrade.test:123/", false, "http://no-upgrade.test:123/"}, |
| #if BUILDFLAG(ENABLE_WEBSOCKETS) |
| {"ws://upgrade.test/", true, "wss://upgrade.test/"}, |
| {"ws://upgrade.test:123/", true, "wss://upgrade.test:123/"}, |
| {"ws://no-upgrade.test/", false, "ws://no-upgrade.test/"}, |
| {"ws://no-upgrade.test:123/", false, "ws://no-upgrade.test:123/"}, |
| #endif // BUILDFLAG(ENABLE_WEBSOCKETS) |
| }; |
| |
| for (const auto& test : cases) { |
| SCOPED_TRACE(test.url); |
| TestDelegate d; |
| TestNetworkDelegate network_delegate; |
| std::unique_ptr<URLRequest> r(context_.CreateRequest( |
| GURL(test.url), DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); |
| |
| net_log_.Clear(); |
| r->Start(); |
| d.RunUntilComplete(); |
| |
| if (test.upgrade_expected) { |
| net::TestNetLogEntry::List entries; |
| net_log_.GetEntries(&entries); |
| int redirects = 0; |
| for (const auto& entry : entries) { |
| if (entry.type == net::NetLogEventType::URL_REQUEST_REDIRECT_JOB) { |
| redirects++; |
| std::string value; |
| EXPECT_TRUE(entry.GetStringValue("reason", &value)); |
| EXPECT_EQ("HSTS", value); |
| } |
| } |
| EXPECT_EQ(1, redirects); |
| EXPECT_EQ(1, d.received_redirect_count()); |
| EXPECT_EQ(2u, r->url_chain().size()); |
| } else { |
| EXPECT_EQ(0, d.received_redirect_count()); |
| EXPECT_EQ(1u, r->url_chain().size()); |
| } |
| EXPECT_EQ(GURL(test.url_expected), r->url()); |
| } |
| } |
| |
| class URLRequestHttpJobWithBrotliSupportTest |
| : public TestWithScopedTaskEnvironment { |
| protected: |
| URLRequestHttpJobWithBrotliSupportTest() |
| : context_(new TestURLRequestContext(true)) { |
| auto params = std::make_unique<HttpNetworkSession::Params>(); |
| context_->set_enable_brotli(true); |
| context_->set_http_network_session_params(std::move(params)); |
| context_->set_client_socket_factory(&socket_factory_); |
| context_->Init(); |
| } |
| |
| MockClientSocketFactory socket_factory_; |
| std::unique_ptr<TestURLRequestContext> context_; |
| }; |
| |
| TEST_F(URLRequestHttpJobWithBrotliSupportTest, NoBrotliAdvertisementOverHttp) { |
| MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("http://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| } |
| |
| TEST_F(URLRequestHttpJobWithBrotliSupportTest, BrotliAdvertisement) { |
| net::SSLSocketDataProvider ssl_socket_data_provider(net::ASYNC, net::OK); |
| ssl_socket_data_provider.next_proto = kProtoHTTP11; |
| ssl_socket_data_provider.ssl_info.cert = |
| ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); |
| ASSERT_TRUE(ssl_socket_data_provider.ssl_info.cert); |
| socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data_provider); |
| |
| MockWrite writes[] = { |
| MockWrite("GET / HTTP/1.1\r\n" |
| "Host: www.example.com\r\n" |
| "Connection: keep-alive\r\n" |
| "User-Agent: \r\n" |
| "Accept-Encoding: gzip, deflate, br\r\n" |
| "Accept-Language: en-us,fr\r\n\r\n")}; |
| MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" |
| "Content-Length: 12\r\n\r\n"), |
| MockRead("Test Content")}; |
| StaticSocketDataProvider socket_data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&socket_data); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_->CreateRequest(GURL("https://www.example.com"), DEFAULT_PRIORITY, |
| &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_THAT(delegate.request_status(), IsOk()); |
| EXPECT_EQ(12, request->received_response_content_length()); |
| EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); |
| EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); |
| } |
| |
| #if defined(OS_ANDROID) |
| TEST_F(URLRequestHttpJobTest, AndroidCleartextPermittedTest) { |
| context_.set_check_cleartext_permitted(true); |
| |
| static constexpr struct TestCase { |
| const char* url; |
| bool cleartext_permitted; |
| bool should_block; |
| int expected_per_host_call_count; |
| int expected_default_call_count; |
| } kTestCases[] = { |
| {"http://unblocked.test/", true, false, 1, 0}, |
| {"https://unblocked.test/", true, false, 0, 0}, |
| {"http://blocked.test/", false, true, 1, 0}, |
| {"https://blocked.test/", false, false, 0, 0}, |
| // If determining the per-host cleartext policy causes an |
| // IllegalArgumentException (because the hostname is invalid), |
| // the default configuration should be applied, and the |
| // exception should not cause a JNI error. |
| {"http://./", false, true, 1, 1}, |
| {"http://./", true, false, 1, 1}, |
| // Even if the host name would be considered invalid, https |
| // schemes should not trigger cleartext policy checks. |
| {"https://./", false, false, 0, 0}, |
| }; |
| |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| for (const TestCase& test : kTestCases) { |
| Java_AndroidNetworkLibraryTestUtil_setUpSecurityPolicyForTesting( |
| env, test.cleartext_permitted); |
| |
| TestDelegate delegate; |
| std::unique_ptr<URLRequest> request = |
| context_.CreateRequest(GURL(test.url), DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| |
| if (test.should_block) { |
| EXPECT_THAT(delegate.request_status(), |
| IsError(ERR_CLEARTEXT_NOT_PERMITTED)); |
| } else { |
| // Should fail since there's no test server running |
| EXPECT_THAT(delegate.request_status(), IsError(ERR_FAILED)); |
| } |
| EXPECT_EQ( |
| Java_AndroidNetworkLibraryTestUtil_getPerHostCleartextCheckCount(env), |
| test.expected_per_host_call_count); |
| EXPECT_EQ( |
| Java_AndroidNetworkLibraryTestUtil_getDefaultCleartextCheckCount(env), |
| test.expected_default_call_count); |
| } |
| } |
| #endif |
| |
| #if BUILDFLAG(ENABLE_WEBSOCKETS) |
| |
| class URLRequestHttpJobWebSocketTest : public TestWithScopedTaskEnvironment { |
| protected: |
| URLRequestHttpJobWebSocketTest() : context_(true) { |
| context_.set_network_delegate(&network_delegate_); |
| context_.set_client_socket_factory(&socket_factory_); |
| context_.Init(); |
| req_ = |
| context_.CreateRequest(GURL("ws://www.example.org"), DEFAULT_PRIORITY, |
| &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS); |
| } |
| |
| // A Network Delegate is required for the WebSocketHandshakeStreamBase |
| // object to be passed on to the HttpNetworkTransaction. |
| TestNetworkDelegate network_delegate_; |
| |
| TestURLRequestContext context_; |
| MockClientSocketFactory socket_factory_; |
| TestDelegate delegate_; |
| std::unique_ptr<URLRequest> req_; |
| }; |
| |
| TEST_F(URLRequestHttpJobWebSocketTest, RejectedWithoutCreateHelper) { |
| req_->Start(); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_THAT(delegate_.request_status(), IsError(ERR_DISALLOWED_URL_SCHEME)); |
| } |
| |
| TEST_F(URLRequestHttpJobWebSocketTest, CreateHelperPassedThrough) { |
| HttpRequestHeaders headers; |
| headers.SetHeader("Connection", "Upgrade"); |
| headers.SetHeader("Upgrade", "websocket"); |
| headers.SetHeader("Origin", "http://www.example.org"); |
| headers.SetHeader("Sec-WebSocket-Version", "13"); |
| req_->SetExtraRequestHeaders(headers); |
| |
| MockWrite writes[] = { |
| MockWrite("GET / HTTP/1.1\r\n" |
| "Host: www.example.org\r\n" |
| "Connection: Upgrade\r\n" |
| "Upgrade: websocket\r\n" |
| "Origin: http://www.example.org\r\n" |
| "Sec-WebSocket-Version: 13\r\n" |
| "User-Agent: \r\n" |
| "Accept-Encoding: gzip, deflate\r\n" |
| "Accept-Language: en-us,fr\r\n" |
| "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" |
| "Sec-WebSocket-Extensions: permessage-deflate; " |
| "client_max_window_bits\r\n\r\n")}; |
| |
| MockRead reads[] = { |
| MockRead("HTTP/1.1 101 Switching Protocols\r\n" |
| "Upgrade: websocket\r\n" |
| "Connection: Upgrade\r\n" |
| "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"), |
| MockRead(ASYNC, 0)}; |
| |
| StaticSocketDataProvider data(reads, writes); |
| socket_factory_.AddSocketDataProvider(&data); |
| |
| auto websocket_stream_create_helper = |
| std::make_unique<TestWebSocketHandshakeStreamCreateHelper>(); |
| |
| req_->SetUserData(kWebSocketHandshakeUserDataKey, |
| std::move(websocket_stream_create_helper)); |
| req_->SetLoadFlags(LOAD_DISABLE_CACHE); |
| req_->Start(); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_THAT(delegate_.request_status(), IsOk()); |
| EXPECT_TRUE(delegate_.response_completed()); |
| |
| EXPECT_TRUE(data.AllWriteDataConsumed()); |
| EXPECT_TRUE(data.AllReadDataConsumed()); |
| } |
| |
| #endif // BUILDFLAG(ENABLE_WEBSOCKETS) |
| |
| } // namespace |
| |
| } // namespace net |