blob: a7fd28ec32014ff2fe40791e7b6e3b9ad3d47fa9 [file] [log] [blame]
[email protected]23e482282013-06-14 16:08:021// Copyright 2013 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]5285d972011-10-18 18:56:348#include <stdarg.h>
sclittlebe1ccf62015-09-02 19:40:369#include <stdint.h>
danakj1fd259a02016-04-16 03:17:0910
avibf0746c2015-12-09 19:53:1411#include <limits>
rdsmith1d343be52016-10-21 20:37:5012#include <set>
[email protected]5285d972011-10-18 18:56:3413#include <string>
dchengc7eeda422015-12-26 03:56:4814#include <utility>
[email protected]95d88ffe2010-02-04 21:25:3315#include <vector>
[email protected]77848d12008-11-14 00:00:2216
Sebastien Marchand6d0558fd2019-01-25 16:49:3717#include "base/bind.h"
[email protected]68bf9152008-09-25 19:47:3018#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5219#include "base/files/file_path.h"
thestigd8df0332014-09-04 06:33:2920#include "base/files/file_util.h"
[email protected]f3da152d2012-06-02 01:00:5721#include "base/json/json_writer.h"
Adam Rice425cf122015-01-19 06:18:2422#include "base/logging.h"
danakj1fd259a02016-04-16 03:17:0923#include "base/memory/ptr_util.h"
[email protected]bf828982013-08-14 18:01:4724#include "base/memory/weak_ptr.h"
Eric Orthf4db66a2019-02-19 21:35:3325#include "base/optional.h"
[email protected]a34f61ee2014-03-18 20:59:4926#include "base/run_loop.h"
Avi Drissman4365a4782018-12-28 19:26:2427#include "base/stl_util.h"
Bence Békyd74f4382018-02-20 18:26:1928#include "base/strings/string_piece.h"
[email protected]125ef482013-06-11 18:32:4729#include "base/strings/string_util.h"
Matt Menked732ea42019-03-08 12:05:0030#include "base/strings/stringprintf.h"
[email protected]750b2f3c2013-06-07 18:41:0531#include "base/strings/utf_string_conversions.h"
Douglas Creager3cb042052018-11-06 23:08:5232#include "base/test/metrics/histogram_tester.h"
Matt Menke166443c2019-05-24 18:45:5933#include "base/test/scoped_feature_list.h"
Douglas Creager134b52e2018-11-09 18:00:1434#include "base/test/simple_test_clock.h"
35#include "base/test/simple_test_tick_clock.h"
Gabriel Charettec7108742019-08-23 03:31:4036#include "base/test/task_environment.h"
[email protected]f36a8132011-09-02 18:36:3337#include "base/test/test_file_util.h"
gabf767595f2016-05-11 18:50:3538#include "base/threading/thread_task_runner_handle.h"
Matt Menke5062be22019-05-01 17:50:2439#include "build/build_config.h"
[email protected]277d5942010-08-11 21:02:3540#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0741#include "net/base/chunked_upload_data_stream.h"
Bence Békya25e3f72018-02-13 21:13:3942#include "net/base/completion_once_callback.h"
mmenkecbc2b712014-10-09 20:29:0743#include "net/base/elements_upload_data_stream.h"
Matt Menke166443c2019-05-24 18:45:5944#include "net/base/features.h"
Eric Orthf4db66a2019-02-19 21:35:3345#include "net/base/host_port_pair.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3746#include "net/base/ip_endpoint.h"
[email protected]58e32bb2013-01-21 18:23:2547#include "net/base/load_timing_info.h"
48#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2449#include "net/base/net_errors.h"
Matt Menkebdf777802019-04-22 19:38:5950#include "net/base/privacy_mode.h"
tbansal28e68f82016-02-04 02:56:1551#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4052#include "net/base/proxy_server.h"
[email protected]ac790b42009-12-02 04:31:3153#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5254#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1555#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0656#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2157#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0858#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1159#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5360#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2461#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1262#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0063#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2964#include "net/http/http_auth_handler_ntlm.h"
aberentbba302d2015-12-03 10:20:1965#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5766#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5267#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5668#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0469#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2470#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1371#include "net/http/http_response_info.h"
Matt Menke609160742019-08-02 18:47:2672#include "net/http/http_server_properties.h"
[email protected]0877e3d2009-10-17 22:29:5773#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3874#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1975#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0776#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0077#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1978#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5179#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4680#include "net/log/test_net_log_util.h"
Lily Houghton582d4622018-01-22 22:43:4081#include "net/proxy_resolution/mock_proxy_resolver.h"
82#include "net/proxy_resolution/proxy_config_service_fixed.h"
83#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0384#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4085#include "net/proxy_resolution/proxy_resolver.h"
86#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4487#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1588#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0389#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3690#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4791#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0292#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0793#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0494#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4495#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1296#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:4497#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:5898#include "net/spdy/spdy_session.h"
99#include "net/spdy/spdy_session_pool.h"
100#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:04101#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57102#include "net/ssl/ssl_cert_request_info.h"
David Benjaminef2f2a5a2019-07-16 19:21:31103#include "net/ssl/ssl_config.h"
[email protected]e86839fd2013-08-14 18:29:03104#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57105#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54106#include "net/ssl/ssl_private_key.h"
David Benjamin151ec6b2019-08-02 19:38:52107#include "net/ssl/test_ssl_config_service.h"
[email protected]6e7845ae2013-03-29 21:48:11108#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01109#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43110#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:40111#include "net/test/test_with_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14112#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23113#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00114#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44115#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06116#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18117#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52118#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15119#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27120#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52121
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37122#if defined(NTLM_PORTABLE)
123#include "base/base64.h"
124#include "net/ntlm/ntlm_test_data.h"
125#endif
126
Douglas Creager3cb042052018-11-06 23:08:52127#if BUILDFLAG(ENABLE_REPORTING)
128#include "net/network_error_logging/network_error_logging_service.h"
129#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14130#include "net/reporting/reporting_cache.h"
Lily Chenfc92ff42019-05-06 22:59:10131#include "net/reporting/reporting_endpoint.h"
Douglas Creager134b52e2018-11-09 18:00:14132#include "net/reporting/reporting_header_parser.h"
133#include "net/reporting/reporting_service.h"
134#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52135#endif // BUILDFLAG(ENABLE_REPORTING)
136
robpercival214763f2016-07-01 23:27:01137using net::test::IsError;
138using net::test::IsOk;
139
[email protected]ad65a3e2013-12-25 18:18:01140using base::ASCIIToUTF16;
141
David Benjamin3b94b0f2019-04-25 23:07:52142using testing::AnyOf;
143
initial.commit586acc5fe2008-07-26 22:42:52144//-----------------------------------------------------------------------------
145
ttuttle859dc7a2015-04-23 19:42:29146namespace net {
147
[email protected]13c8a092010-07-29 06:15:44148namespace {
149
[email protected]42cba2fb2013-03-29 19:58:57150const base::string16 kBar(ASCIIToUTF16("bar"));
151const base::string16 kBar2(ASCIIToUTF16("bar2"));
152const base::string16 kBar3(ASCIIToUTF16("bar3"));
153const base::string16 kBaz(ASCIIToUTF16("baz"));
154const base::string16 kFirst(ASCIIToUTF16("first"));
155const base::string16 kFoo(ASCIIToUTF16("foo"));
156const base::string16 kFoo2(ASCIIToUTF16("foo2"));
157const base::string16 kFoo3(ASCIIToUTF16("foo3"));
158const base::string16 kFou(ASCIIToUTF16("fou"));
159const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57160const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44161
bnc2df4b522016-07-08 18:17:43162const char kAlternativeServiceHttpHeader[] =
163 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
164
ttuttle859dc7a2015-04-23 19:42:29165int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40166 return session
167 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
168 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29169 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02170}
171
ttuttle859dc7a2015-04-23 19:42:29172bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40173 return session
174 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
175 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29176 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52177}
178
[email protected]f3da152d2012-06-02 01:00:57179// Takes in a Value created from a NetLogHttpResponseParameter, and returns
180// a JSONified list of headers as a single string. Uses single quotes instead
Eric Roman79cc7552019-07-19 02:17:54181// of double quotes for easier comparison.
182std::string GetHeaders(const base::Value& params) {
183 if (!params.is_dict())
184 return "";
185 const base::Value* header_list = params.FindListKey("headers");
186 if (!header_list)
187 return "";
188 std::string headers;
189 base::JSONWriter::Write(*header_list, &headers);
190 base::ReplaceChars(headers, "\"", "'", &headers);
191 return headers;
[email protected]f3da152d2012-06-02 01:00:57192}
193
[email protected]029c83b62013-01-24 05:28:20194// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
195// used.
ttuttle859dc7a2015-04-23 19:42:29196void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20197 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19198 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25199
[email protected]029c83b62013-01-24 05:28:20200 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
201 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
202
ttuttle859dc7a2015-04-23 19:42:29203 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20204 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25205
206 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25207
[email protected]3b23a222013-05-15 21:33:25208 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25209 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
210 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25211 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25212}
213
[email protected]029c83b62013-01-24 05:28:20214// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
215// used.
ttuttle859dc7a2015-04-23 19:42:29216void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25217 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20218 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19219 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20220
221 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
222 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
223
ttuttle859dc7a2015-04-23 19:42:29224 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
225 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20226 EXPECT_LE(load_timing_info.connect_timing.connect_end,
227 load_timing_info.send_start);
228
229 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20230
[email protected]3b23a222013-05-15 21:33:25231 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20232 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
233 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25234 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20235}
236
237// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
238// used.
ttuttle859dc7a2015-04-23 19:42:29239void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20240 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19241 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20242
ttuttle859dc7a2015-04-23 19:42:29243 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20244
245 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
246 EXPECT_LE(load_timing_info.proxy_resolve_start,
247 load_timing_info.proxy_resolve_end);
248 EXPECT_LE(load_timing_info.proxy_resolve_end,
249 load_timing_info.send_start);
250 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20251
[email protected]3b23a222013-05-15 21:33:25252 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20253 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
254 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25255 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20256}
257
258// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
259// used.
ttuttle859dc7a2015-04-23 19:42:29260void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20261 int connect_timing_flags) {
262 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19263 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20264
265 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
266 EXPECT_LE(load_timing_info.proxy_resolve_start,
267 load_timing_info.proxy_resolve_end);
268 EXPECT_LE(load_timing_info.proxy_resolve_end,
269 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29270 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
271 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20272 EXPECT_LE(load_timing_info.connect_timing.connect_end,
273 load_timing_info.send_start);
274
275 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20276
[email protected]3b23a222013-05-15 21:33:25277 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20278 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
279 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25280 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25281}
282
Matt Menke2436b2f2018-12-11 18:07:11283// ProxyResolver that records URLs passed to it, and that can be told what
284// result to return.
285class CapturingProxyResolver : public ProxyResolver {
286 public:
287 CapturingProxyResolver()
288 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
289 ~CapturingProxyResolver() override = default;
290
291 int GetProxyForURL(const GURL& url,
292 ProxyInfo* results,
293 CompletionOnceCallback callback,
294 std::unique_ptr<Request>* request,
295 const NetLogWithSource& net_log) override {
296 results->UseProxyServer(proxy_server_);
297 resolved_.push_back(url);
298 return OK;
299 }
300
301 // Sets whether the resolver should use direct connections, instead of a
302 // proxy.
303 void set_proxy_server(ProxyServer proxy_server) {
304 proxy_server_ = proxy_server;
305 }
306
307 const std::vector<GURL>& resolved() const { return resolved_; }
308
309 private:
310 std::vector<GURL> resolved_;
311
312 ProxyServer proxy_server_;
313
314 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
315};
316
317class CapturingProxyResolverFactory : public ProxyResolverFactory {
318 public:
319 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
320 : ProxyResolverFactory(false), resolver_(resolver) {}
321
322 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
323 std::unique_ptr<ProxyResolver>* resolver,
324 CompletionOnceCallback callback,
325 std::unique_ptr<Request>* request) override {
326 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
327 return OK;
328 }
329
330 private:
331 ProxyResolver* resolver_;
332};
333
danakj1fd259a02016-04-16 03:17:09334std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42335 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34336 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14337}
338
xunjieli96f2a402017-06-05 17:24:27339class FailingProxyResolverFactory : public ProxyResolverFactory {
340 public:
341 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
342
343 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42344 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
345 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17346 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42347 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27348 return ERR_PAC_SCRIPT_FAILED;
349 }
350};
351
[email protected]448d4ca52012-03-04 04:12:23352} // namespace
353
Bence Béky98447b12018-05-08 03:14:01354class HttpNetworkTransactionTest : public PlatformTest,
Gabriel Charette694c3c332019-08-19 14:53:05355 public WithTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03356 public:
bncd16676a2016-07-20 16:23:01357 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03358 // Important to restore the per-pool limit first, since the pool limit must
359 // always be greater than group limit, and the tests reduce both limits.
360 ClientSocketPoolManager::set_max_sockets_per_pool(
361 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
362 ClientSocketPoolManager::set_max_sockets_per_group(
363 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
364 }
365
[email protected]e3ceb682011-06-28 23:55:46366 protected:
[email protected]23e482282013-06-14 16:08:02367 HttpNetworkTransactionTest()
Gabriel Charette694c3c332019-08-19 14:53:05368 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
Matt Menked6fd2a52019-03-20 06:14:36369 dummy_connect_job_params_(
370 nullptr /* client_socket_factory */,
371 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40372 nullptr /* http_auth_cache */,
373 nullptr /* http_auth_handler_factory */,
374 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13375 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40376 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36377 nullptr /* proxy_delegate */,
378 nullptr /* http_user_agent_settings */,
David Benjamin24725be2019-07-24 20:57:18379 nullptr /* ssl_client_context */,
Matt Menked6fd2a52019-03-20 06:14:36380 nullptr /* socket_performance_watcher_factory */,
381 nullptr /* network_quality_estimator */,
382 nullptr /* net_log */,
383 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56384 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15385 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03386 HttpNetworkSession::NORMAL_SOCKET_POOL)),
387 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
388 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28389 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03390 }
[email protected]bb88e1d32013-05-03 23:11:07391
[email protected]e3ceb682011-06-28 23:55:46392 struct SimpleGetHelperResult {
393 int rv;
394 std::string status_line;
395 std::string response_data;
sclittlefb249892015-09-10 21:33:22396 int64_t total_received_bytes;
397 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25398 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47399 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59400 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46401 };
402
dcheng67be2b1f2014-10-27 21:47:29403 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50404 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55405 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56406 // Set an initial delay to ensure that the first call to TimeTicks::Now()
407 // before incrementing the counter does not return a null value.
Matt Menke6dc08232019-10-03 18:00:28408 FastForwardBy(base::TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54409 }
410
dcheng67be2b1f2014-10-27 21:47:29411 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50412 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55413 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09414 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55415 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09416 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50417 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55418 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09419 }
420
Andrew Comminos1f2ff1cc2018-12-14 05:22:38421 void Check100ResponseTiming(bool use_spdy);
422
[email protected]202965992011-12-07 23:04:51423 // Either |write_failure| specifies a write failure or |read_failure|
424 // specifies a read failure when using a reused socket. In either case, the
425 // failure should cause the network transaction to resend the request, and the
426 // other argument should be NULL.
427 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
428 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52429
[email protected]a34f61ee2014-03-18 20:59:49430 // Either |write_failure| specifies a write failure or |read_failure|
431 // specifies a read failure when using a reused socket. In either case, the
432 // failure should cause the network transaction to resend the request, and the
433 // other argument should be NULL.
434 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10435 const MockRead* read_failure,
436 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49437
Ryan Sleevib8d7ea02018-05-07 20:01:01438 SimpleGetHelperResult SimpleGetHelperForData(
439 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15440 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52441
[email protected]ff007e162009-05-23 09:13:15442 HttpRequestInfo request;
443 request.method = "GET";
bncce36dca22015-04-21 22:11:23444 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10445 request.traffic_annotation =
446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52447
vishal.b62985ca92015-04-17 08:45:51448 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07449 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09450 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16451 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27452
Ryan Sleevib8d7ea02018-05-07 20:01:01453 for (auto* provider : providers) {
454 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29455 }
initial.commit586acc5fe2008-07-26 22:42:52456
[email protected]49639fa2011-12-20 23:22:41457 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52458
eroman24bc6a12015-05-06 19:55:48459 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16460 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01461 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52462
[email protected]ff007e162009-05-23 09:13:15463 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16464 out.total_received_bytes = trans.GetTotalReceivedBytes();
465 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25466
467 // Even in the failure cases that use this function, connections are always
468 // successfully established before the error.
bnc691fda62016-08-12 00:43:16469 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25470 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
471
[email protected]ff007e162009-05-23 09:13:15472 if (out.rv != OK)
473 return out;
474
bnc691fda62016-08-12 00:43:16475 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50476 // Can't use ASSERT_* inside helper functions like this, so
477 // return an error.
wezca1070932016-05-26 20:30:52478 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50479 out.rv = ERR_UNEXPECTED;
480 return out;
481 }
[email protected]ff007e162009-05-23 09:13:15482 out.status_line = response->headers->GetStatusLine();
483
Tsuyoshi Horo01faed62019-02-20 22:11:37484 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
485 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19486
ttuttled9dbc652015-09-29 20:00:59487 bool got_endpoint =
bnc691fda62016-08-12 00:43:16488 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59489 EXPECT_EQ(got_endpoint,
490 out.remote_endpoint_after_start.address().size() > 0);
491
bnc691fda62016-08-12 00:43:16492 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01493 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40494
Eric Roman79cc7552019-07-19 02:17:54495 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:39496 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00497 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
498 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39499 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00500 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
501 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15502
Eric Roman79cc7552019-07-19 02:17:54503 EXPECT_EQ("GET / HTTP/1.1\r\n",
504 GetStringValueFromParams(entries[pos], "line"));
[email protected]f3da152d2012-06-02 01:00:57505
bncce36dca22015-04-21 22:11:23506 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
Eric Roman79cc7552019-07-19 02:17:54507 GetHeaders(entries[pos].params));
[email protected]3deb9a52010-11-11 00:24:40508
bnc691fda62016-08-12 00:43:16509 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22510 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16511 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22512
bnc691fda62016-08-12 00:43:16513 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47514 return out;
[email protected]ff007e162009-05-23 09:13:15515 }
initial.commit586acc5fe2008-07-26 22:42:52516
Ryan Sleevib8d7ea02018-05-07 20:01:01517 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22518 MockWrite data_writes[] = {
519 MockWrite("GET / HTTP/1.1\r\n"
520 "Host: www.example.org\r\n"
521 "Connection: keep-alive\r\n\r\n"),
522 };
[email protected]5a60c8b2011-10-19 20:14:29523
Ryan Sleevib8d7ea02018-05-07 20:01:01524 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22525 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01526 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22527
Ryan Sleevib8d7ea02018-05-07 20:01:01528 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22529 return out;
[email protected]b8015c42013-12-24 15:18:19530 }
531
bnc032658ba2016-09-26 18:17:15532 void AddSSLSocketData() {
533 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49534 ssl_.ssl_info.cert =
535 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
536 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15537 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
538 }
539
[email protected]ff007e162009-05-23 09:13:15540 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
541 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52542
[email protected]ff007e162009-05-23 09:13:15543 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07544
[email protected]bb88e1d32013-05-03 23:11:07545 void CheckErrorIsPassedBack(int error, IoMode mode);
546
Matt Menked6fd2a52019-03-20 06:14:36547 const CommonConnectJobParams dummy_connect_job_params_;
548
Douglas Creager134b52e2018-11-09 18:00:14549 // These clocks are defined here, even though they're only used in the
550 // Reporting tests below, since they need to be destroyed after
551 // |session_deps_|.
552 base::SimpleTestClock clock_;
553 base::SimpleTestTickClock tick_clock_;
554
[email protected]4bd46222013-05-14 19:32:23555 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07556 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15557 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03558
559 // Original socket limits. Some tests set these. Safest to always restore
560 // them once each test has been run.
561 int old_max_group_sockets_;
562 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15563};
[email protected]231d5a32008-09-13 00:45:27564
[email protected]448d4ca52012-03-04 04:12:23565namespace {
566
ryansturm49a8cb12016-06-15 16:51:09567class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27568 public:
ryansturm49a8cb12016-06-15 16:51:09569 BeforeHeadersSentHandler()
570 : observed_before_headers_sent_with_proxy_(false),
571 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27572
ryansturm49a8cb12016-06-15 16:51:09573 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
574 HttpRequestHeaders* request_headers) {
575 observed_before_headers_sent_ = true;
576 if (!proxy_info.is_http() && !proxy_info.is_https() &&
577 !proxy_info.is_quic()) {
578 return;
579 }
580 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27581 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
582 }
583
ryansturm49a8cb12016-06-15 16:51:09584 bool observed_before_headers_sent_with_proxy() const {
585 return observed_before_headers_sent_with_proxy_;
586 }
587
588 bool observed_before_headers_sent() const {
589 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27590 }
591
592 std::string observed_proxy_server_uri() const {
593 return observed_proxy_server_uri_;
594 }
595
596 private:
ryansturm49a8cb12016-06-15 16:51:09597 bool observed_before_headers_sent_with_proxy_;
598 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27599 std::string observed_proxy_server_uri_;
600
ryansturm49a8cb12016-06-15 16:51:09601 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27602};
603
[email protected]15a5ccf82008-10-23 19:57:43604// Fill |str| with a long header list that consumes >= |size| bytes.
605void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51606 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19607 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
608 const int sizeof_row = strlen(row);
609 const int num_rows = static_cast<int>(
610 ceil(static_cast<float>(size) / sizeof_row));
611 const int sizeof_data = num_rows * sizeof_row;
612 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43613 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51614
[email protected]4ddaf2502008-10-23 18:26:19615 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43616 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19617}
618
thakis84dff942015-07-28 20:47:38619#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09620uint64_t MockGetMSTime() {
621 // Tue, 23 May 2017 20:13:07 +0000
622 return 131400439870000000;
623}
624
[email protected]385a4672009-03-11 22:21:29625// Alternative functions that eliminate randomness and dependency on the local
626// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37627void MockGenerateRandom(uint8_t* output, size_t n) {
628 // This is set to 0xaa because the client challenge for testing in
629 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
630 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29631}
632
[email protected]fe2bc6a2009-03-23 16:52:20633std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37634 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29635}
thakis84dff942015-07-28 20:47:38636#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29637
Matt Menked6fd2a52019-03-20 06:14:36638class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31639 public:
Matt Menked6fd2a52019-03-20 06:14:36640 explicit CaptureGroupIdTransportSocketPool(
641 const CommonConnectJobParams* common_connect_job_params)
642 : TransportClientSocketPool(0,
643 0,
644 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36645 ProxyServer::Direct(),
646 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52647 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18648
Matt Menkef6edce752019-03-19 17:21:56649 const ClientSocketPool::GroupId& last_group_id_received() const {
650 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49651 }
652
Tarun Bansal162eabe52018-01-20 01:16:39653 bool socket_requested() const { return socket_requested_; }
654
Matt Menke28ac03e2019-02-25 22:25:50655 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56656 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03657 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28658 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50659 RequestPriority priority,
660 const SocketTag& socket_tag,
661 ClientSocketPool::RespectLimits respect_limits,
662 ClientSocketHandle* handle,
663 CompletionOnceCallback callback,
664 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
665 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56666 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39667 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31668 return ERR_IO_PENDING;
669 }
Matt Menkef6edce752019-03-19 17:21:56670 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21671 ClientSocketHandle* handle,
672 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56673 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09674 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24675 int64_t generation) override {}
dmichaeld6e570d2014-12-18 22:30:57676 void CloseIdleSockets() override {}
Matt Menkef6edce752019-03-19 17:21:56677 void CloseIdleSocketsInGroup(
678 const ClientSocketPool::GroupId& group_id) override {}
dmichaeld6e570d2014-12-18 22:30:57679 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56680 size_t IdleSocketCountInGroup(
681 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31682 return 0;
683 }
Matt Menkef6edce752019-03-19 17:21:56684 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57685 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31686 return LOAD_STATE_IDLE;
687 }
[email protected]d80a4322009-08-14 07:07:49688
689 private:
Matt Menkef6edce752019-03-19 17:21:56690 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39691 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31692};
693
[email protected]231d5a32008-09-13 00:45:27694//-----------------------------------------------------------------------------
695
[email protected]79cb5c12011-09-12 13:12:04696// Helper functions for validating that AuthChallengeInfo's are correctly
697// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58698bool CheckBasicServerAuth(
699 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04700 if (!auth_challenge)
701 return false;
702 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43703 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04704 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19705 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04706 return true;
707}
708
David Benjamin2eb827f2019-04-29 18:31:04709bool CheckBasicSecureServerAuth(
710 const base::Optional<AuthChallengeInfo>& auth_challenge) {
711 if (!auth_challenge)
712 return false;
713 EXPECT_FALSE(auth_challenge->is_proxy);
714 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
715 EXPECT_EQ("MyRealm1", auth_challenge->realm);
716 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
717 return true;
718}
719
Emily Starkf2c9bbd2019-04-09 17:08:58720bool CheckBasicProxyAuth(
721 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04722 if (!auth_challenge)
723 return false;
724 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43725 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
726 EXPECT_EQ("MyRealm1", auth_challenge->realm);
727 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
728 return true;
729}
730
Emily Starkf2c9bbd2019-04-09 17:08:58731bool CheckBasicSecureProxyAuth(
732 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43733 if (!auth_challenge)
734 return false;
735 EXPECT_TRUE(auth_challenge->is_proxy);
736 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04737 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19738 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04739 return true;
740}
741
Emily Starkf2c9bbd2019-04-09 17:08:58742bool CheckDigestServerAuth(
743 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04744 if (!auth_challenge)
745 return false;
746 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43747 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04748 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19749 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04750 return true;
751}
752
thakis84dff942015-07-28 20:47:38753#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58754bool CheckNTLMServerAuth(
755 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04756 if (!auth_challenge)
757 return false;
758 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55759 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04760 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19761 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04762 return true;
763}
David Benjamin5cb91132018-04-06 05:54:49764
Emily Starkf2c9bbd2019-04-09 17:08:58765bool CheckNTLMProxyAuth(
766 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49767 if (!auth_challenge)
768 return false;
769 EXPECT_TRUE(auth_challenge->is_proxy);
770 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
771 EXPECT_EQ(std::string(), auth_challenge->realm);
772 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
773 return true;
774}
thakis84dff942015-07-28 20:47:38775#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04776
[email protected]448d4ca52012-03-04 04:12:23777} // namespace
778
Shivani Sharma8ae506c2019-07-21 21:08:27779// TODO(950069): Add testing for frame_origin in NetworkIsolationKey
780// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
781
bncd16676a2016-07-20 16:23:01782TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09783 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16784 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27785}
786
bncd16676a2016-07-20 16:23:01787TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27788 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35789 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
790 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06791 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27792 };
Ryan Sleevib8d7ea02018-05-07 20:01:01793 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01794 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27795 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
796 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01797 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22798 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47799 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59800
801 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27802}
803
804// Response with no status line.
bncd16676a2016-07-20 16:23:01805TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27806 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35807 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06808 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27809 };
Ryan Sleevib8d7ea02018-05-07 20:01:01810 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41811 EXPECT_THAT(out.rv, IsOk());
812 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
813 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01814 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41815 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27816}
817
mmenkea7da6da2016-09-01 21:56:52818// Response with no status line, and a weird port. Should fail by default.
819TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
820 MockRead data_reads[] = {
821 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
822 };
823
Ryan Sleevib8d7ea02018-05-07 20:01:01824 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52825 session_deps_.socket_factory->AddSocketDataProvider(&data);
826
827 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
828
krasinc06a72a2016-12-21 03:42:46829 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58830 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19831 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52832
mmenkea7da6da2016-09-01 21:56:52833 request.method = "GET";
834 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10835 request.traffic_annotation =
836 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
837
mmenkea7da6da2016-09-01 21:56:52838 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:20839 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52840 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
841}
842
Shivani Sharmafdcaefd2017-11-02 00:12:26843// Tests that request info can be destroyed after the headers phase is complete.
844TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
845 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
846 auto trans =
847 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
848
849 MockRead data_reads[] = {
850 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
851 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
852 };
Ryan Sleevib8d7ea02018-05-07 20:01:01853 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26854 session_deps_.socket_factory->AddSocketDataProvider(&data);
855
856 TestCompletionCallback callback;
857
858 {
859 auto request = std::make_unique<HttpRequestInfo>();
860 request->method = "GET";
861 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10862 request->traffic_annotation =
863 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26864
865 int rv =
866 trans->Start(request.get(), callback.callback(), NetLogWithSource());
867
868 EXPECT_THAT(callback.GetResult(rv), IsOk());
869 } // Let request info be destroyed.
870
871 trans.reset();
872}
873
[email protected]231d5a32008-09-13 00:45:27874// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01875TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27876 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35877 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06878 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27879 };
Ryan Sleevib8d7ea02018-05-07 20:01:01880 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01881 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27882 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
883 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01884 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22885 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27886}
887
888// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01889TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27890 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35891 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06892 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27893 };
Ryan Sleevib8d7ea02018-05-07 20:01:01894 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01895 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27896 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
897 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01898 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22899 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27900}
901
902// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01903TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27904 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35905 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06906 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27907 };
Ryan Sleevib8d7ea02018-05-07 20:01:01908 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41909 EXPECT_THAT(out.rv, IsOk());
910 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
911 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01912 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41913 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27914}
915
916// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01917TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27918 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35919 MockRead("\n"),
920 MockRead("\n"),
921 MockRead("Q"),
922 MockRead("J"),
923 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06924 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27925 };
Ryan Sleevib8d7ea02018-05-07 20:01:01926 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01927 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27928 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
929 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01930 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22931 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27932}
933
934// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01935TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27936 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35937 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06938 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27939 };
Ryan Sleevib8d7ea02018-05-07 20:01:01940 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41941 EXPECT_THAT(out.rv, IsOk());
942 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
943 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01944 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41945 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52946}
947
[email protected]f9d44aa2008-09-23 23:57:17948// Simulate a 204 response, lacking a Content-Length header, sent over a
949// persistent connection. The response should still terminate since a 204
950// cannot have a response body.
bncd16676a2016-07-20 16:23:01951TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19952 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17953 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35954 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19955 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06956 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17957 };
Ryan Sleevib8d7ea02018-05-07 20:01:01958 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01959 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:17960 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
961 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01962 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22963 int64_t response_size = reads_size - strlen(junk);
964 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17965}
966
[email protected]0877e3d2009-10-17 22:29:57967// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:01968TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19969 std::string final_chunk = "0\r\n\r\n";
970 std::string extra_data = "HTTP/1.1 200 OK\r\n";
971 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57972 MockRead data_reads[] = {
973 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
974 MockRead("5\r\nHello\r\n"),
975 MockRead("1\r\n"),
976 MockRead(" \r\n"),
977 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19978 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06979 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57980 };
Ryan Sleevib8d7ea02018-05-07 20:01:01981 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01982 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:57983 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
984 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01985 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22986 int64_t response_size = reads_size - extra_data.size();
987 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57988}
989
[email protected]9fe44f52010-09-23 18:36:00990// Next tests deal with http://crbug.com/56344.
991
bncd16676a2016-07-20 16:23:01992TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00993 MultipleContentLengthHeadersNoTransferEncoding) {
994 MockRead data_reads[] = {
995 MockRead("HTTP/1.1 200 OK\r\n"),
996 MockRead("Content-Length: 10\r\n"),
997 MockRead("Content-Length: 5\r\n\r\n"),
998 };
Ryan Sleevib8d7ea02018-05-07 20:01:01999 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011000 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001001}
1002
bncd16676a2016-07-20 16:23:011003TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041004 DuplicateContentLengthHeadersNoTransferEncoding) {
1005 MockRead data_reads[] = {
1006 MockRead("HTTP/1.1 200 OK\r\n"),
1007 MockRead("Content-Length: 5\r\n"),
1008 MockRead("Content-Length: 5\r\n\r\n"),
1009 MockRead("Hello"),
1010 };
Ryan Sleevib8d7ea02018-05-07 20:01:011011 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011012 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041013 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1014 EXPECT_EQ("Hello", out.response_data);
1015}
1016
bncd16676a2016-07-20 16:23:011017TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041018 ComplexContentLengthHeadersNoTransferEncoding) {
1019 // More than 2 dupes.
1020 {
1021 MockRead data_reads[] = {
1022 MockRead("HTTP/1.1 200 OK\r\n"),
1023 MockRead("Content-Length: 5\r\n"),
1024 MockRead("Content-Length: 5\r\n"),
1025 MockRead("Content-Length: 5\r\n\r\n"),
1026 MockRead("Hello"),
1027 };
Ryan Sleevib8d7ea02018-05-07 20:01:011028 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011029 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041030 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1031 EXPECT_EQ("Hello", out.response_data);
1032 }
1033 // HTTP/1.0
1034 {
1035 MockRead data_reads[] = {
1036 MockRead("HTTP/1.0 200 OK\r\n"),
1037 MockRead("Content-Length: 5\r\n"),
1038 MockRead("Content-Length: 5\r\n"),
1039 MockRead("Content-Length: 5\r\n\r\n"),
1040 MockRead("Hello"),
1041 };
Ryan Sleevib8d7ea02018-05-07 20:01:011042 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011043 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041044 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1045 EXPECT_EQ("Hello", out.response_data);
1046 }
1047 // 2 dupes and one mismatched.
1048 {
1049 MockRead data_reads[] = {
1050 MockRead("HTTP/1.1 200 OK\r\n"),
1051 MockRead("Content-Length: 10\r\n"),
1052 MockRead("Content-Length: 10\r\n"),
1053 MockRead("Content-Length: 5\r\n\r\n"),
1054 };
Ryan Sleevib8d7ea02018-05-07 20:01:011055 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011056 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041057 }
1058}
1059
bncd16676a2016-07-20 16:23:011060TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001061 MultipleContentLengthHeadersTransferEncoding) {
1062 MockRead data_reads[] = {
1063 MockRead("HTTP/1.1 200 OK\r\n"),
1064 MockRead("Content-Length: 666\r\n"),
1065 MockRead("Content-Length: 1337\r\n"),
1066 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1067 MockRead("5\r\nHello\r\n"),
1068 MockRead("1\r\n"),
1069 MockRead(" \r\n"),
1070 MockRead("5\r\nworld\r\n"),
1071 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061072 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001073 };
Ryan Sleevib8d7ea02018-05-07 20:01:011074 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011075 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001076 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1077 EXPECT_EQ("Hello world", out.response_data);
1078}
1079
[email protected]1628fe92011-10-04 23:04:551080// Next tests deal with http://crbug.com/98895.
1081
1082// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011083TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551084 MockRead data_reads[] = {
1085 MockRead("HTTP/1.1 200 OK\r\n"),
1086 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1087 MockRead("Content-Length: 5\r\n\r\n"),
1088 MockRead("Hello"),
1089 };
Ryan Sleevib8d7ea02018-05-07 20:01:011090 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011091 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551092 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1093 EXPECT_EQ("Hello", out.response_data);
1094}
1095
[email protected]54a9c6e52012-03-21 20:10:591096// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011097TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551098 MockRead data_reads[] = {
1099 MockRead("HTTP/1.1 200 OK\r\n"),
1100 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1101 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1102 MockRead("Content-Length: 5\r\n\r\n"),
1103 MockRead("Hello"),
1104 };
Ryan Sleevib8d7ea02018-05-07 20:01:011105 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011106 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591107 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1108 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551109}
1110
1111// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011112TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551113 MockRead data_reads[] = {
1114 MockRead("HTTP/1.1 200 OK\r\n"),
1115 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1116 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1117 MockRead("Content-Length: 5\r\n\r\n"),
1118 MockRead("Hello"),
1119 };
Ryan Sleevib8d7ea02018-05-07 20:01:011120 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011121 EXPECT_THAT(out.rv,
1122 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551123}
1124
[email protected]54a9c6e52012-03-21 20:10:591125// Checks that two identical Location headers result in no error.
1126// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011127TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551128 MockRead data_reads[] = {
1129 MockRead("HTTP/1.1 302 Redirect\r\n"),
1130 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591131 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551132 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061133 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551134 };
1135
1136 HttpRequestInfo request;
1137 request.method = "GET";
1138 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101139 request.traffic_annotation =
1140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551141
danakj1fd259a02016-04-16 03:17:091142 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161143 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551144
Ryan Sleevib8d7ea02018-05-07 20:01:011145 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071146 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551147
[email protected]49639fa2011-12-20 23:22:411148 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551149
tfarina428341112016-09-22 13:38:201150 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011151 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551152
robpercival214763f2016-07-01 23:27:011153 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551154
bnc691fda62016-08-12 00:43:161155 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521156 ASSERT_TRUE(response);
1157 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551158 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1159 std::string url;
1160 EXPECT_TRUE(response->headers->IsRedirect(&url));
1161 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471162 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551163}
1164
[email protected]1628fe92011-10-04 23:04:551165// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011166TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551167 MockRead data_reads[] = {
1168 MockRead("HTTP/1.1 302 Redirect\r\n"),
1169 MockRead("Location: http://good.com/\r\n"),
1170 MockRead("Location: http://evil.com/\r\n"),
1171 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061172 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551173 };
Ryan Sleevib8d7ea02018-05-07 20:01:011174 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011175 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551176}
1177
[email protected]ef0faf2e72009-03-05 23:27:231178// Do a request using the HEAD method. Verify that we don't try to read the
1179// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011180TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421181 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231182 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231183 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101184 request.traffic_annotation =
1185 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231186
danakj1fd259a02016-04-16 03:17:091187 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161188 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091189 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161190 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091191 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1192 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271193
[email protected]ef0faf2e72009-03-05 23:27:231194 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131195 MockWrite("HEAD / HTTP/1.1\r\n"
1196 "Host: www.example.org\r\n"
1197 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231198 };
1199 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231200 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1201 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231202
mmenked39192ee2015-12-09 00:57:231203 // No response body because the test stops reading here.
1204 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231205 };
1206
Ryan Sleevib8d7ea02018-05-07 20:01:011207 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071208 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231209
[email protected]49639fa2011-12-20 23:22:411210 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231211
tfarina428341112016-09-22 13:38:201212 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011213 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231214
1215 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011216 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231217
bnc691fda62016-08-12 00:43:161218 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521219 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231220
1221 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521222 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231223 EXPECT_EQ(1234, response->headers->GetContentLength());
1224 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471225 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091226 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1227 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231228
1229 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101230 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231231 bool has_server_header = response->headers->EnumerateHeader(
1232 &iter, "Server", &server_header);
1233 EXPECT_TRUE(has_server_header);
1234 EXPECT_EQ("Blah", server_header);
1235
1236 // Reading should give EOF right away, since there is no message body
1237 // (despite non-zero content-length).
1238 std::string response_data;
bnc691fda62016-08-12 00:43:161239 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011240 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231241 EXPECT_EQ("", response_data);
1242}
1243
bncd16676a2016-07-20 16:23:011244TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091245 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521246
1247 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351248 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1249 MockRead("hello"),
1250 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1251 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061252 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521253 };
Ryan Sleevib8d7ea02018-05-07 20:01:011254 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071255 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521256
[email protected]0b0bf032010-09-21 18:08:501257 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521258 "hello", "world"
1259 };
1260
1261 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421262 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521263 request.method = "GET";
bncce36dca22015-04-21 22:11:231264 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101265 request.traffic_annotation =
1266 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521267
bnc691fda62016-08-12 00:43:161268 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271269
[email protected]49639fa2011-12-20 23:22:411270 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521271
tfarina428341112016-09-22 13:38:201272 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011273 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521274
1275 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011276 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521277
bnc691fda62016-08-12 00:43:161278 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521279 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521280
wezca1070932016-05-26 20:30:521281 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251282 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471283 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521284
1285 std::string response_data;
bnc691fda62016-08-12 00:43:161286 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011287 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251288 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521289 }
1290}
1291
bncd16676a2016-07-20 16:23:011292TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091293 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221294 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191295 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221296 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271297
[email protected]1c773ea12009-04-28 19:58:421298 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521299 request.method = "POST";
1300 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271301 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:101302 request.traffic_annotation =
1303 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521304
shivanishab9a143952016-09-19 17:23:411305 // Check the upload progress returned before initialization is correct.
1306 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1307 EXPECT_EQ(0u, progress.size());
1308 EXPECT_EQ(0u, progress.position());
1309
danakj1fd259a02016-04-16 03:17:091310 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161311 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271312
initial.commit586acc5fe2008-07-26 22:42:521313 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351314 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1315 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1316 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061317 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521318 };
Ryan Sleevib8d7ea02018-05-07 20:01:011319 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071320 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521321
[email protected]49639fa2011-12-20 23:22:411322 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521323
tfarina428341112016-09-22 13:38:201324 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011325 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521326
1327 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011328 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521329
bnc691fda62016-08-12 00:43:161330 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521331 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521332
wezca1070932016-05-26 20:30:521333 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251334 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521335
1336 std::string response_data;
bnc691fda62016-08-12 00:43:161337 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011338 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251339 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521340}
1341
[email protected]3a2d3662009-03-27 03:49:141342// This test is almost the same as Ignores100 above, but the response contains
1343// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571344// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011345TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421346 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141347 request.method = "GET";
1348 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101349 request.traffic_annotation =
1350 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141351
danakj1fd259a02016-04-16 03:17:091352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161353 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271354
[email protected]3a2d3662009-03-27 03:49:141355 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571356 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1357 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141358 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061359 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141360 };
Ryan Sleevib8d7ea02018-05-07 20:01:011361 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071362 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141363
[email protected]49639fa2011-12-20 23:22:411364 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141365
tfarina428341112016-09-22 13:38:201366 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011367 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141368
1369 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011370 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141371
bnc691fda62016-08-12 00:43:161372 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521373 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141374
wezca1070932016-05-26 20:30:521375 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141376 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1377
1378 std::string response_data;
bnc691fda62016-08-12 00:43:161379 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011380 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141381 EXPECT_EQ("hello world", response_data);
1382}
1383
Andrew Comminos517a92c2019-01-14 17:49:561384TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1385 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381386 base::TimeDelta::FromMilliseconds(10);
1387
1388 HttpRequestInfo request;
1389 request.method = "GET";
1390 request.url = GURL("http://www.foo.com/");
1391 request.traffic_annotation =
1392 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1393
1394 std::vector<MockWrite> data_writes = {
1395 MockWrite(ASYNC, 0,
1396 "GET / HTTP/1.1\r\n"
1397 "Host: www.foo.com\r\n"
1398 "Connection: keep-alive\r\n\r\n"),
1399 };
1400
1401 std::vector<MockRead> data_reads = {
1402 // Write one byte of the status line, followed by a pause.
1403 MockRead(ASYNC, 1, "H"),
1404 MockRead(ASYNC, ERR_IO_PENDING, 2),
1405 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1406 MockRead(ASYNC, 4, "hello world"),
1407 MockRead(SYNCHRONOUS, OK, 5),
1408 };
1409
1410 SequencedSocketData data(data_reads, data_writes);
1411 session_deps_.socket_factory->AddSocketDataProvider(&data);
1412
1413 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1414
1415 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1416
1417 TestCompletionCallback callback;
1418
1419 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1420 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1421
1422 data.RunUntilPaused();
1423 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561424 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381425 data.Resume();
1426
1427 rv = callback.WaitForResult();
1428 EXPECT_THAT(rv, IsOk());
1429
1430 const HttpResponseInfo* response = trans.GetResponseInfo();
1431 ASSERT_TRUE(response);
1432
1433 EXPECT_TRUE(response->headers);
1434 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1435
1436 LoadTimingInfo load_timing_info;
1437 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1438 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1439 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561440 // Ensure we didn't include the delay in the TTFB time.
1441 EXPECT_EQ(load_timing_info.receive_headers_start,
1442 load_timing_info.connect_timing.connect_end);
1443 // Ensure that the mock clock advanced at all.
1444 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1445 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381446
1447 std::string response_data;
1448 rv = ReadTransaction(&trans, &response_data);
1449 EXPECT_THAT(rv, IsOk());
1450 EXPECT_EQ("hello world", response_data);
1451}
1452
1453// Tests that the time-to-first-byte reported in a transaction's load timing
1454// info uses the first response, even if 1XX/informational.
1455void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561456 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381457 base::TimeDelta::FromMilliseconds(10);
1458
1459 HttpRequestInfo request;
1460 request.method = "GET";
1461 request.url = GURL("https://www.foo.com/");
1462 request.traffic_annotation =
1463 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1464
1465 SSLSocketDataProvider ssl(ASYNC, OK);
1466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1467
1468 std::vector<MockWrite> data_writes;
1469 std::vector<MockRead> data_reads;
1470
1471 spdy::SpdySerializedFrame spdy_req(
1472 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1473
1474 spdy::SpdyHeaderBlock spdy_resp1_headers;
1475 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1476 spdy::SpdySerializedFrame spdy_resp1(
1477 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1478 spdy::SpdySerializedFrame spdy_resp2(
1479 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1480 spdy::SpdySerializedFrame spdy_data(
1481 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1482
1483 if (use_spdy) {
1484 ssl.next_proto = kProtoHTTP2;
1485
1486 data_writes = {CreateMockWrite(spdy_req, 0)};
1487
1488 data_reads = {
1489 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1490 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1491 MockRead(SYNCHRONOUS, OK, 5),
1492 };
1493 } else {
1494 data_writes = {
1495 MockWrite(ASYNC, 0,
1496 "GET / HTTP/1.1\r\n"
1497 "Host: www.foo.com\r\n"
1498 "Connection: keep-alive\r\n\r\n"),
1499 };
1500
1501 data_reads = {
1502 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1503 MockRead(ASYNC, ERR_IO_PENDING, 2),
1504
1505 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1506 MockRead(ASYNC, 4, "hello world"),
1507 MockRead(SYNCHRONOUS, OK, 5),
1508 };
1509 }
1510
1511 SequencedSocketData data(data_reads, data_writes);
1512 session_deps_.socket_factory->AddSocketDataProvider(&data);
1513
1514 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1515
1516 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1517
1518 TestCompletionCallback callback;
1519
1520 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1521 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1522
1523 data.RunUntilPaused();
1524 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1525 // the delay before parsing the 200 response.
1526 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561527 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381528 data.Resume();
1529
1530 rv = callback.WaitForResult();
1531 EXPECT_THAT(rv, IsOk());
1532
1533 const HttpResponseInfo* response = trans.GetResponseInfo();
1534 ASSERT_TRUE(response);
1535
1536 LoadTimingInfo load_timing_info;
1537 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1538 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1539 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561540 // Ensure we didn't include the delay in the TTFB time.
1541 EXPECT_EQ(load_timing_info.receive_headers_start,
1542 load_timing_info.connect_timing.connect_end);
1543 // Ensure that the mock clock advanced at all.
1544 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1545 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381546
1547 std::string response_data;
1548 rv = ReadTransaction(&trans, &response_data);
1549 EXPECT_THAT(rv, IsOk());
1550 EXPECT_EQ("hello world", response_data);
1551}
1552
Andrew Comminos517a92c2019-01-14 17:49:561553TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381554 Check100ResponseTiming(false /* use_spdy */);
1555}
1556
Andrew Comminos517a92c2019-01-14 17:49:561557TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381558 Check100ResponseTiming(true /* use_spdy */);
1559}
1560
bncd16676a2016-07-20 16:23:011561TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081562 HttpRequestInfo request;
1563 request.method = "POST";
1564 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101565 request.traffic_annotation =
1566 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081567
danakj1fd259a02016-04-16 03:17:091568 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081570
1571 MockRead data_reads[] = {
1572 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1573 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381574 };
Ryan Sleevib8d7ea02018-05-07 20:01:011575 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081576 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381577
zmo9528c9f42015-08-04 22:12:081578 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381579
tfarina428341112016-09-22 13:38:201580 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011581 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381582
zmo9528c9f42015-08-04 22:12:081583 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011584 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381585
zmo9528c9f42015-08-04 22:12:081586 std::string response_data;
bnc691fda62016-08-12 00:43:161587 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011588 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081589 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381590}
1591
bncd16676a2016-07-20 16:23:011592TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381593 HttpRequestInfo request;
1594 request.method = "POST";
1595 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101596 request.traffic_annotation =
1597 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381598
danakj1fd259a02016-04-16 03:17:091599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161600 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271601
[email protected]ee9410e72010-01-07 01:42:381602 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061603 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381604 };
Ryan Sleevib8d7ea02018-05-07 20:01:011605 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071606 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381607
[email protected]49639fa2011-12-20 23:22:411608 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381609
tfarina428341112016-09-22 13:38:201610 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011611 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381612
1613 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011614 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381615}
1616
[email protected]23e482282013-06-14 16:08:021617void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511618 const MockWrite* write_failure,
1619 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421620 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521621 request.method = "GET";
1622 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101623 request.traffic_annotation =
1624 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521625
vishal.b62985ca92015-04-17 08:45:511626 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071627 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091628 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271629
[email protected]202965992011-12-07 23:04:511630 // Written data for successfully sending both requests.
1631 MockWrite data1_writes[] = {
1632 MockWrite("GET / HTTP/1.1\r\n"
1633 "Host: www.foo.com\r\n"
1634 "Connection: keep-alive\r\n\r\n"),
1635 MockWrite("GET / HTTP/1.1\r\n"
1636 "Host: www.foo.com\r\n"
1637 "Connection: keep-alive\r\n\r\n")
1638 };
1639
1640 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521641 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351642 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1643 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061644 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521645 };
[email protected]202965992011-12-07 23:04:511646
1647 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491648 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511649 data1_writes[1] = *write_failure;
1650 } else {
1651 ASSERT_TRUE(read_failure);
1652 data1_reads[2] = *read_failure;
1653 }
1654
Ryan Sleevib8d7ea02018-05-07 20:01:011655 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071656 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521657
1658 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351659 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1660 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061661 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521662 };
Ryan Sleevib8d7ea02018-05-07 20:01:011663 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071664 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521665
thestig9d3bb0c2015-01-24 00:49:511666 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521667 "hello", "world"
1668 };
1669
mikecironef22f9812016-10-04 03:40:191670 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521671 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411672 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521673
bnc691fda62016-08-12 00:43:161674 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521675
tfarina428341112016-09-22 13:38:201676 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011677 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521678
1679 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011680 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521681
[email protected]58e32bb2013-01-21 18:23:251682 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161683 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251684 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1685 if (i == 0) {
1686 first_socket_log_id = load_timing_info.socket_log_id;
1687 } else {
1688 // The second request should be using a new socket.
1689 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1690 }
1691
bnc691fda62016-08-12 00:43:161692 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521693 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521694
wezca1070932016-05-26 20:30:521695 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471696 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251697 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521698
1699 std::string response_data;
bnc691fda62016-08-12 00:43:161700 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011701 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251702 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521703 }
1704}
[email protected]3d2a59b2008-09-26 19:44:251705
[email protected]a34f61ee2014-03-18 20:59:491706void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1707 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101708 const MockRead* read_failure,
1709 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491710 HttpRequestInfo request;
1711 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101712 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101713 request.traffic_annotation =
1714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491715
vishal.b62985ca92015-04-17 08:45:511716 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491717 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091718 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491719
[email protected]09356c652014-03-25 15:36:101720 SSLSocketDataProvider ssl1(ASYNC, OK);
1721 SSLSocketDataProvider ssl2(ASYNC, OK);
1722 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361723 ssl1.next_proto = kProtoHTTP2;
1724 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101725 }
1726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491728
[email protected]09356c652014-03-25 15:36:101729 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131730 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491731 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131732 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351733 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131734 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191735 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491736
[email protected]09356c652014-03-25 15:36:101737 // HTTP/1.1 versions of the request and response.
1738 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1739 "Host: www.foo.com\r\n"
1740 "Connection: keep-alive\r\n\r\n";
1741 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1742 const char kHttpData[] = "hello";
1743
1744 std::vector<MockRead> data1_reads;
1745 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491746 if (write_failure) {
1747 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101748 data1_writes.push_back(*write_failure);
1749 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491750 } else {
1751 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101752 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411753 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101754 } else {
1755 data1_writes.push_back(MockWrite(kHttpRequest));
1756 }
1757 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491758 }
1759
Ryan Sleevib8d7ea02018-05-07 20:01:011760 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491761 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1762
[email protected]09356c652014-03-25 15:36:101763 std::vector<MockRead> data2_reads;
1764 std::vector<MockWrite> data2_writes;
1765
1766 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411767 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101768
bncdf80d44fd2016-07-15 20:27:411769 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1770 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101771 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1772 } else {
1773 data2_writes.push_back(
1774 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1775
1776 data2_reads.push_back(
1777 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1778 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1779 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1780 }
Ryan Sleevib8d7ea02018-05-07 20:01:011781 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491782 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1783
1784 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591785 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491786 // Wait for the preconnect to complete.
1787 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1788 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231789 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491790
1791 // Make the request.
1792 TestCompletionCallback callback;
1793
bnc691fda62016-08-12 00:43:161794 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491795
tfarina428341112016-09-22 13:38:201796 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011797 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491798
1799 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011800 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491801
1802 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161803 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101804 TestLoadTimingNotReused(
1805 load_timing_info,
1806 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491807
bnc691fda62016-08-12 00:43:161808 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521809 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491810
wezca1070932016-05-26 20:30:521811 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021812 if (response->was_fetched_via_spdy) {
1813 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1814 } else {
1815 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1816 }
[email protected]a34f61ee2014-03-18 20:59:491817
1818 std::string response_data;
bnc691fda62016-08-12 00:43:161819 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011820 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101821 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491822}
1823
Biljith Jayan45a41722017-08-16 18:43:141824// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:181825// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:141826// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1827TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1828 HttpRequestInfo request;
1829 request.method = "GET";
1830 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101831 request.traffic_annotation =
1832 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141833
1834 // Check whether we give up after the third try.
1835
1836 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131837 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141838 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131839 spdy::SpdySerializedFrame spdy_response_go_away(
1840 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011841 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1842 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141843
1844 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011845 StaticSocketDataProvider data1(data_read1, data_write);
1846 StaticSocketDataProvider data2(data_read1, data_write);
1847 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141848
1849 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1850 AddSSLSocketData();
1851 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1852 AddSSLSocketData();
1853 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1854 AddSSLSocketData();
1855
1856 TestCompletionCallback callback;
1857 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1858 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1859
1860 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1861 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1862
1863 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:181864 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:141865}
1866
1867TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1868 HttpRequestInfo request;
1869 request.method = "GET";
1870 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101871 request.traffic_annotation =
1872 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141873
1874 // Check whether we try atleast thrice before giving up.
1875
1876 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131877 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141878 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131879 spdy::SpdySerializedFrame spdy_response_go_away(
1880 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011881 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1882 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141883
1884 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131885 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141886 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131887 spdy::SpdySerializedFrame spdy_data(
1888 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141889 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1890 CreateMockRead(spdy_data, 2)};
1891
1892 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011893 StaticSocketDataProvider data1(data_read1, data_write);
1894 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141895 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011896 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141897
1898 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1899 AddSSLSocketData();
1900 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1901 AddSSLSocketData();
1902 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1903 AddSSLSocketData();
1904
1905 TestCompletionCallback callback;
1906 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1907 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1908
1909 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1910 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1911
1912 rv = callback.WaitForResult();
1913 EXPECT_THAT(rv, IsOk());
1914}
1915
bncd16676a2016-07-20 16:23:011916TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061917 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351918 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511919}
1920
bncd16676a2016-07-20 16:23:011921TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061922 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351923 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251924}
1925
bncd16676a2016-07-20 16:23:011926TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061927 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351928 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251929}
1930
[email protected]d58ceea82014-06-04 10:55:541931// Make sure that on a 408 response (Request Timeout), the request is retried,
1932// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011933TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541934 MockRead read_failure(SYNCHRONOUS,
1935 "HTTP/1.1 408 Request Timeout\r\n"
1936 "Connection: Keep-Alive\r\n"
1937 "Content-Length: 6\r\n\r\n"
1938 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351939 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:541940}
1941
bncd16676a2016-07-20 16:23:011942TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:491943 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351944 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:491945}
1946
bncd16676a2016-07-20 16:23:011947TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:491948 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351949 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491950}
1951
bncd16676a2016-07-20 16:23:011952TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:491953 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351954 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101955}
1956
bncd16676a2016-07-20 16:23:011957TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101958 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351959 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101960}
1961
[email protected]d58ceea82014-06-04 10:55:541962// Make sure that on a 408 response (Request Timeout), the request is retried,
1963// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:011964TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:541965 MockRead read_failure(SYNCHRONOUS,
1966 "HTTP/1.1 408 Request Timeout\r\n"
1967 "Connection: Keep-Alive\r\n"
1968 "Content-Length: 6\r\n\r\n"
1969 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351970 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
1971 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:541972}
1973
bncd16676a2016-07-20 16:23:011974TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:101975 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351976 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:101977}
1978
bncd16676a2016-07-20 16:23:011979TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:101980 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351981 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101982}
1983
bncd16676a2016-07-20 16:23:011984TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:101985 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351986 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101987}
1988
bncd16676a2016-07-20 16:23:011989TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101990 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351991 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491992}
1993
bncd16676a2016-07-20 16:23:011994TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421995 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251996 request.method = "GET";
bncce36dca22015-04-21 22:11:231997 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101998 request.traffic_annotation =
1999 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252000
danakj1fd259a02016-04-16 03:17:092001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162002 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272003
[email protected]3d2a59b2008-09-26 19:44:252004 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062005 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352006 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2007 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062008 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252009 };
Ryan Sleevib8d7ea02018-05-07 20:01:012010 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072011 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252012
[email protected]49639fa2011-12-20 23:22:412013 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252014
tfarina428341112016-09-22 13:38:202015 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012016 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252017
2018 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012019 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592020
2021 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162022 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592023 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252024}
2025
2026// What do various browsers do when the server closes a non-keepalive
2027// connection without sending any response header or body?
2028//
2029// IE7: error page
2030// Safari 3.1.2 (Windows): error page
2031// Firefox 3.0.1: blank page
2032// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422033// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2034// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012035TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252036 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062037 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352038 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2039 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062040 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252041 };
Ryan Sleevib8d7ea02018-05-07 20:01:012042 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012043 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252044}
[email protected]1826a402014-01-08 15:40:482045
[email protected]7a5378b2012-11-04 03:25:172046// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2047// tests. There was a bug causing HttpNetworkTransaction to hang in the
2048// destructor in such situations.
2049// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012050TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172051 HttpRequestInfo request;
2052 request.method = "GET";
bncce36dca22015-04-21 22:11:232053 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102054 request.traffic_annotation =
2055 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172056
danakj1fd259a02016-04-16 03:17:092057 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582058 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192059 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172060
2061 MockRead data_reads[] = {
2062 MockRead("HTTP/1.0 200 OK\r\n"),
2063 MockRead("Connection: keep-alive\r\n"),
2064 MockRead("Content-Length: 100\r\n\r\n"),
2065 MockRead("hello"),
2066 MockRead(SYNCHRONOUS, 0),
2067 };
Ryan Sleevib8d7ea02018-05-07 20:01:012068 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072069 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172070
2071 TestCompletionCallback callback;
2072
tfarina428341112016-09-22 13:38:202073 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012074 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172075
2076 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012077 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172078
Victor Costan9c7302b2018-08-27 16:39:442079 scoped_refptr<IOBufferWithSize> io_buf =
2080 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502081 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172082 if (rv == ERR_IO_PENDING)
2083 rv = callback.WaitForResult();
2084 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502085 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012086 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172087
2088 trans.reset();
fdoray92e35a72016-06-10 15:54:552089 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172090 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2091}
2092
bncd16676a2016-07-20 16:23:012093TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172094 HttpRequestInfo request;
2095 request.method = "GET";
bncce36dca22015-04-21 22:11:232096 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102097 request.traffic_annotation =
2098 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172099
danakj1fd259a02016-04-16 03:17:092100 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582101 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192102 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172103
2104 MockRead data_reads[] = {
2105 MockRead("HTTP/1.0 200 OK\r\n"),
2106 MockRead("Connection: keep-alive\r\n"),
2107 MockRead("Content-Length: 100\r\n\r\n"),
2108 MockRead(SYNCHRONOUS, 0),
2109 };
Ryan Sleevib8d7ea02018-05-07 20:01:012110 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072111 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172112
2113 TestCompletionCallback callback;
2114
tfarina428341112016-09-22 13:38:202115 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012116 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172117
2118 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012119 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172120
Victor Costan9c7302b2018-08-27 16:39:442121 scoped_refptr<IOBufferWithSize> io_buf(
2122 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502123 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172124 if (rv == ERR_IO_PENDING)
2125 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012126 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172127
2128 trans.reset();
fdoray92e35a72016-06-10 15:54:552129 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172130 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2131}
2132
[email protected]0b0bf032010-09-21 18:08:502133// Test that we correctly reuse a keep-alive connection after not explicitly
2134// reading the body.
bncd16676a2016-07-20 16:23:012135TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132136 HttpRequestInfo request;
2137 request.method = "GET";
2138 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102139 request.traffic_annotation =
2140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132141
vishal.b62985ca92015-04-17 08:45:512142 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072143 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092144 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272145
mmenkecc2298e2015-12-07 18:20:182146 const char* request_data =
2147 "GET / HTTP/1.1\r\n"
2148 "Host: www.foo.com\r\n"
2149 "Connection: keep-alive\r\n\r\n";
2150 MockWrite data_writes[] = {
2151 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2152 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2153 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2154 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2155 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2156 };
2157
[email protected]0b0bf032010-09-21 18:08:502158 // Note that because all these reads happen in the same
2159 // StaticSocketDataProvider, it shows that the same socket is being reused for
2160 // all transactions.
mmenkecc2298e2015-12-07 18:20:182161 MockRead data_reads[] = {
2162 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2163 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2164 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2165 MockRead(ASYNC, 7,
2166 "HTTP/1.1 302 Found\r\n"
2167 "Content-Length: 0\r\n\r\n"),
2168 MockRead(ASYNC, 9,
2169 "HTTP/1.1 302 Found\r\n"
2170 "Content-Length: 5\r\n\r\n"
2171 "hello"),
2172 MockRead(ASYNC, 11,
2173 "HTTP/1.1 301 Moved Permanently\r\n"
2174 "Content-Length: 0\r\n\r\n"),
2175 MockRead(ASYNC, 13,
2176 "HTTP/1.1 301 Moved Permanently\r\n"
2177 "Content-Length: 5\r\n\r\n"
2178 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132179
mmenkecc2298e2015-12-07 18:20:182180 // In the next two rounds, IsConnectedAndIdle returns false, due to
2181 // the set_busy_before_sync_reads(true) call, while the
2182 // HttpNetworkTransaction is being shut down, but the socket is still
2183 // reuseable. See http://crbug.com/544255.
2184 MockRead(ASYNC, 15,
2185 "HTTP/1.1 200 Hunky-Dory\r\n"
2186 "Content-Length: 5\r\n\r\n"),
2187 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132188
mmenkecc2298e2015-12-07 18:20:182189 MockRead(ASYNC, 18,
2190 "HTTP/1.1 200 Hunky-Dory\r\n"
2191 "Content-Length: 5\r\n\r\n"
2192 "he"),
2193 MockRead(SYNCHRONOUS, 19, "llo"),
2194
2195 // The body of the final request is actually read.
2196 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2197 MockRead(ASYNC, 22, "hello"),
2198 };
Ryan Sleevib8d7ea02018-05-07 20:01:012199 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182200 data.set_busy_before_sync_reads(true);
2201 session_deps_.socket_factory->AddSocketDataProvider(&data);
2202
Avi Drissman4365a4782018-12-28 19:26:242203 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502204 std::string response_lines[kNumUnreadBodies];
2205
mikecironef22f9812016-10-04 03:40:192206 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182207 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412208 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132209
Jeremy Roman0579ed62017-08-29 15:56:192210 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582211 session.get());
[email protected]fc31d6a42010-06-24 18:05:132212
tfarina428341112016-09-22 13:38:202213 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012214 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132215
[email protected]58e32bb2013-01-21 18:23:252216 LoadTimingInfo load_timing_info;
2217 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2218 if (i == 0) {
2219 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2220 first_socket_log_id = load_timing_info.socket_log_id;
2221 } else {
2222 TestLoadTimingReused(load_timing_info);
2223 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2224 }
2225
[email protected]fc31d6a42010-06-24 18:05:132226 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182227 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132228
mmenkecc2298e2015-12-07 18:20:182229 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502230 response_lines[i] = response->headers->GetStatusLine();
2231
mmenkecc2298e2015-12-07 18:20:182232 // Delete the transaction without reading the response bodies. Then spin
2233 // the message loop, so the response bodies are drained.
2234 trans.reset();
2235 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132236 }
[email protected]0b0bf032010-09-21 18:08:502237
2238 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182239 "HTTP/1.1 204 No Content",
2240 "HTTP/1.1 205 Reset Content",
2241 "HTTP/1.1 304 Not Modified",
2242 "HTTP/1.1 302 Found",
2243 "HTTP/1.1 302 Found",
2244 "HTTP/1.1 301 Moved Permanently",
2245 "HTTP/1.1 301 Moved Permanently",
2246 "HTTP/1.1 200 Hunky-Dory",
2247 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502248 };
2249
Avi Drissman4365a4782018-12-28 19:26:242250 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272251 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502252
2253 for (int i = 0; i < kNumUnreadBodies; ++i)
2254 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2255
[email protected]49639fa2011-12-20 23:22:412256 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162257 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:202258 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012259 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162260 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182261 ASSERT_TRUE(response);
2262 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2264 std::string response_data;
bnc691fda62016-08-12 00:43:162265 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012266 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502267 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132268}
2269
mmenke5f94fda2016-06-02 20:54:132270// Sockets that receive extra data after a response is complete should not be
2271// reused.
bncd16676a2016-07-20 16:23:012272TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132273 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2274 MockWrite data_writes1[] = {
2275 MockWrite("HEAD / HTTP/1.1\r\n"
2276 "Host: www.borked.com\r\n"
2277 "Connection: keep-alive\r\n\r\n"),
2278 };
2279
2280 MockRead data_reads1[] = {
2281 MockRead("HTTP/1.1 200 OK\r\n"
2282 "Connection: keep-alive\r\n"
2283 "Content-Length: 22\r\n\r\n"
2284 "This server is borked."),
2285 };
2286
2287 MockWrite data_writes2[] = {
2288 MockWrite("GET /foo HTTP/1.1\r\n"
2289 "Host: www.borked.com\r\n"
2290 "Connection: keep-alive\r\n\r\n"),
2291 };
2292
2293 MockRead data_reads2[] = {
2294 MockRead("HTTP/1.1 200 OK\r\n"
2295 "Content-Length: 3\r\n\r\n"
2296 "foo"),
2297 };
Ryan Sleevib8d7ea02018-05-07 20:01:012298 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132299 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012300 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132301 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2302
2303 TestCompletionCallback callback;
2304 HttpRequestInfo request1;
2305 request1.method = "HEAD";
2306 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102307 request1.traffic_annotation =
2308 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132309
bnc87dcefc2017-05-25 12:47:582310 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192311 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:202312 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012313 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132314
2315 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2316 ASSERT_TRUE(response1);
2317 ASSERT_TRUE(response1->headers);
2318 EXPECT_EQ(200, response1->headers->response_code());
2319 EXPECT_TRUE(response1->headers->IsKeepAlive());
2320
2321 std::string response_data1;
robpercival214763f2016-07-01 23:27:012322 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132323 EXPECT_EQ("", response_data1);
2324 // Deleting the transaction attempts to release the socket back into the
2325 // socket pool.
2326 trans1.reset();
2327
2328 HttpRequestInfo request2;
2329 request2.method = "GET";
2330 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102331 request2.traffic_annotation =
2332 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132333
bnc87dcefc2017-05-25 12:47:582334 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192335 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:202336 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012337 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132338
2339 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2340 ASSERT_TRUE(response2);
2341 ASSERT_TRUE(response2->headers);
2342 EXPECT_EQ(200, response2->headers->response_code());
2343
2344 std::string response_data2;
robpercival214763f2016-07-01 23:27:012345 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132346 EXPECT_EQ("foo", response_data2);
2347}
2348
bncd16676a2016-07-20 16:23:012349TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132350 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2351 MockWrite data_writes1[] = {
2352 MockWrite("GET / HTTP/1.1\r\n"
2353 "Host: www.borked.com\r\n"
2354 "Connection: keep-alive\r\n\r\n"),
2355 };
2356
2357 MockRead data_reads1[] = {
2358 MockRead("HTTP/1.1 200 OK\r\n"
2359 "Connection: keep-alive\r\n"
2360 "Content-Length: 22\r\n\r\n"
2361 "This server is borked."
2362 "Bonus data!"),
2363 };
2364
2365 MockWrite data_writes2[] = {
2366 MockWrite("GET /foo HTTP/1.1\r\n"
2367 "Host: www.borked.com\r\n"
2368 "Connection: keep-alive\r\n\r\n"),
2369 };
2370
2371 MockRead data_reads2[] = {
2372 MockRead("HTTP/1.1 200 OK\r\n"
2373 "Content-Length: 3\r\n\r\n"
2374 "foo"),
2375 };
Ryan Sleevib8d7ea02018-05-07 20:01:012376 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132377 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012378 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132379 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2380
2381 TestCompletionCallback callback;
2382 HttpRequestInfo request1;
2383 request1.method = "GET";
2384 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102385 request1.traffic_annotation =
2386 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132387
bnc87dcefc2017-05-25 12:47:582388 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192389 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:202390 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012391 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132392
2393 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2394 ASSERT_TRUE(response1);
2395 ASSERT_TRUE(response1->headers);
2396 EXPECT_EQ(200, response1->headers->response_code());
2397 EXPECT_TRUE(response1->headers->IsKeepAlive());
2398
2399 std::string response_data1;
robpercival214763f2016-07-01 23:27:012400 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132401 EXPECT_EQ("This server is borked.", response_data1);
2402 // Deleting the transaction attempts to release the socket back into the
2403 // socket pool.
2404 trans1.reset();
2405
2406 HttpRequestInfo request2;
2407 request2.method = "GET";
2408 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102409 request2.traffic_annotation =
2410 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132411
bnc87dcefc2017-05-25 12:47:582412 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192413 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:202414 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012415 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132416
2417 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2418 ASSERT_TRUE(response2);
2419 ASSERT_TRUE(response2->headers);
2420 EXPECT_EQ(200, response2->headers->response_code());
2421
2422 std::string response_data2;
robpercival214763f2016-07-01 23:27:012423 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132424 EXPECT_EQ("foo", response_data2);
2425}
2426
bncd16676a2016-07-20 16:23:012427TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132428 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2429 MockWrite data_writes1[] = {
2430 MockWrite("GET / HTTP/1.1\r\n"
2431 "Host: www.borked.com\r\n"
2432 "Connection: keep-alive\r\n\r\n"),
2433 };
2434
2435 MockRead data_reads1[] = {
2436 MockRead("HTTP/1.1 200 OK\r\n"
2437 "Connection: keep-alive\r\n"
2438 "Transfer-Encoding: chunked\r\n\r\n"),
2439 MockRead("16\r\nThis server is borked.\r\n"),
2440 MockRead("0\r\n\r\nBonus data!"),
2441 };
2442
2443 MockWrite data_writes2[] = {
2444 MockWrite("GET /foo HTTP/1.1\r\n"
2445 "Host: www.borked.com\r\n"
2446 "Connection: keep-alive\r\n\r\n"),
2447 };
2448
2449 MockRead data_reads2[] = {
2450 MockRead("HTTP/1.1 200 OK\r\n"
2451 "Content-Length: 3\r\n\r\n"
2452 "foo"),
2453 };
Ryan Sleevib8d7ea02018-05-07 20:01:012454 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132455 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012456 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132457 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2458
2459 TestCompletionCallback callback;
2460 HttpRequestInfo request1;
2461 request1.method = "GET";
2462 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102463 request1.traffic_annotation =
2464 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132465
bnc87dcefc2017-05-25 12:47:582466 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192467 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:202468 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012469 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132470
2471 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2472 ASSERT_TRUE(response1);
2473 ASSERT_TRUE(response1->headers);
2474 EXPECT_EQ(200, response1->headers->response_code());
2475 EXPECT_TRUE(response1->headers->IsKeepAlive());
2476
2477 std::string response_data1;
robpercival214763f2016-07-01 23:27:012478 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132479 EXPECT_EQ("This server is borked.", response_data1);
2480 // Deleting the transaction attempts to release the socket back into the
2481 // socket pool.
2482 trans1.reset();
2483
2484 HttpRequestInfo request2;
2485 request2.method = "GET";
2486 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102487 request2.traffic_annotation =
2488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132489
bnc87dcefc2017-05-25 12:47:582490 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192491 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:202492 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012493 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132494
2495 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2496 ASSERT_TRUE(response2);
2497 ASSERT_TRUE(response2->headers);
2498 EXPECT_EQ(200, response2->headers->response_code());
2499
2500 std::string response_data2;
robpercival214763f2016-07-01 23:27:012501 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132502 EXPECT_EQ("foo", response_data2);
2503}
2504
2505// This is a little different from the others - it tests the case that the
2506// HttpStreamParser doesn't know if there's extra data on a socket or not when
2507// the HttpNetworkTransaction is torn down, because the response body hasn't
2508// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012509TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132510 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2511 MockWrite data_writes1[] = {
2512 MockWrite("GET / HTTP/1.1\r\n"
2513 "Host: www.borked.com\r\n"
2514 "Connection: keep-alive\r\n\r\n"),
2515 };
2516
2517 MockRead data_reads1[] = {
2518 MockRead("HTTP/1.1 200 OK\r\n"
2519 "Connection: keep-alive\r\n"
2520 "Transfer-Encoding: chunked\r\n\r\n"),
2521 MockRead("16\r\nThis server is borked.\r\n"),
2522 MockRead("0\r\n\r\nBonus data!"),
2523 };
Ryan Sleevib8d7ea02018-05-07 20:01:012524 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132525 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2526
2527 TestCompletionCallback callback;
2528 HttpRequestInfo request1;
2529 request1.method = "GET";
2530 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102531 request1.traffic_annotation =
2532 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132533
bnc87dcefc2017-05-25 12:47:582534 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192535 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582536 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012537 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132538
bnc87dcefc2017-05-25 12:47:582539 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132540 ASSERT_TRUE(response1);
2541 ASSERT_TRUE(response1->headers);
2542 EXPECT_EQ(200, response1->headers->response_code());
2543 EXPECT_TRUE(response1->headers->IsKeepAlive());
2544
2545 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2546 // response body.
bnc87dcefc2017-05-25 12:47:582547 trans.reset();
mmenke5f94fda2016-06-02 20:54:132548
2549 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2550 // socket can't be reused, rather than returning it to the socket pool.
2551 base::RunLoop().RunUntilIdle();
2552
2553 // There should be no idle sockets in the pool.
2554 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2555}
2556
[email protected]038e9a32008-10-08 22:40:162557// Test the request-challenge-retry sequence for basic auth.
2558// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012559TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422560 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162561 request.method = "GET";
bncce36dca22015-04-21 22:11:232562 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102563 request.traffic_annotation =
2564 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162565
vishal.b62985ca92015-04-17 08:45:512566 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072567 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092568 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272570
[email protected]f9ee6b52008-11-08 06:46:232571 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232572 MockWrite(
2573 "GET / HTTP/1.1\r\n"
2574 "Host: www.example.org\r\n"
2575 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232576 };
2577
[email protected]038e9a32008-10-08 22:40:162578 MockRead data_reads1[] = {
2579 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2580 // Give a couple authenticate options (only the middle one is actually
2581 // supported).
[email protected]22927ad2009-09-21 19:56:192582 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162583 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2584 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2585 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2586 // Large content-length -- won't matter, as connection will be reset.
2587 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062588 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162589 };
2590
2591 // After calling trans->RestartWithAuth(), this is the request we should
2592 // be issuing -- the final header line contains the credentials.
2593 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232594 MockWrite(
2595 "GET / HTTP/1.1\r\n"
2596 "Host: www.example.org\r\n"
2597 "Connection: keep-alive\r\n"
2598 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162599 };
2600
2601 // Lastly, the server responds with the actual content.
2602 MockRead data_reads2[] = {
2603 MockRead("HTTP/1.0 200 OK\r\n"),
2604 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2605 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062606 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162607 };
2608
Ryan Sleevib8d7ea02018-05-07 20:01:012609 StaticSocketDataProvider data1(data_reads1, data_writes1);
2610 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072611 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2612 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162613
[email protected]49639fa2011-12-20 23:22:412614 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162615
tfarina428341112016-09-22 13:38:202616 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012617 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162618
2619 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012620 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162621
[email protected]58e32bb2013-01-21 18:23:252622 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162623 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252624 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2625
Ryan Sleevib8d7ea02018-05-07 20:01:012626 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162627 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012628 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162629 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192630
bnc691fda62016-08-12 00:43:162631 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522632 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582633 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162634
[email protected]49639fa2011-12-20 23:22:412635 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162636
bnc691fda62016-08-12 00:43:162637 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012638 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162639
2640 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012641 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162642
[email protected]58e32bb2013-01-21 18:23:252643 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162644 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252645 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2646 // The load timing after restart should have a new socket ID, and times after
2647 // those of the first load timing.
2648 EXPECT_LE(load_timing_info1.receive_headers_end,
2649 load_timing_info2.connect_timing.connect_start);
2650 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2651
Ryan Sleevib8d7ea02018-05-07 20:01:012652 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162653 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012654 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162655 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192656
bnc691fda62016-08-12 00:43:162657 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522658 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582659 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162660 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162661}
2662
ttuttled9dbc652015-09-29 20:00:592663// Test the request-challenge-retry sequence for basic auth.
2664// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012665TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592666 HttpRequestInfo request;
2667 request.method = "GET";
2668 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102669 request.traffic_annotation =
2670 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592671
2672 TestNetLog log;
2673 MockHostResolver* resolver = new MockHostResolver();
2674 session_deps_.net_log = &log;
2675 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092676 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162677 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592678
2679 resolver->rules()->ClearRules();
2680 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2681
2682 MockWrite data_writes1[] = {
2683 MockWrite("GET / HTTP/1.1\r\n"
2684 "Host: www.example.org\r\n"
2685 "Connection: keep-alive\r\n\r\n"),
2686 };
2687
2688 MockRead data_reads1[] = {
2689 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2690 // Give a couple authenticate options (only the middle one is actually
2691 // supported).
2692 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2693 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2694 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2695 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2696 // Large content-length -- won't matter, as connection will be reset.
2697 MockRead("Content-Length: 10000\r\n\r\n"),
2698 MockRead(SYNCHRONOUS, ERR_FAILED),
2699 };
2700
2701 // After calling trans->RestartWithAuth(), this is the request we should
2702 // be issuing -- the final header line contains the credentials.
2703 MockWrite data_writes2[] = {
2704 MockWrite("GET / HTTP/1.1\r\n"
2705 "Host: www.example.org\r\n"
2706 "Connection: keep-alive\r\n"
2707 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2708 };
2709
2710 // Lastly, the server responds with the actual content.
2711 MockRead data_reads2[] = {
2712 MockRead("HTTP/1.0 200 OK\r\n"),
2713 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2714 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2715 };
2716
Ryan Sleevib8d7ea02018-05-07 20:01:012717 StaticSocketDataProvider data1(data_reads1, data_writes1);
2718 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592719 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2720 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2721
2722 TestCompletionCallback callback1;
2723
bnc691fda62016-08-12 00:43:162724 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina428341112016-09-22 13:38:202725 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592726
2727 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162728 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592729 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2730
Ryan Sleevib8d7ea02018-05-07 20:01:012731 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162732 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012733 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162734 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592735
bnc691fda62016-08-12 00:43:162736 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592737 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582738 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592739
2740 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162741 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592742 ASSERT_FALSE(endpoint.address().empty());
2743 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2744
2745 resolver->rules()->ClearRules();
2746 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2747
2748 TestCompletionCallback callback2;
2749
bnc691fda62016-08-12 00:43:162750 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592751 AuthCredentials(kFoo, kBar), callback2.callback())));
2752
2753 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162754 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592755 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2756 // The load timing after restart should have a new socket ID, and times after
2757 // those of the first load timing.
2758 EXPECT_LE(load_timing_info1.receive_headers_end,
2759 load_timing_info2.connect_timing.connect_start);
2760 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2761
Ryan Sleevib8d7ea02018-05-07 20:01:012762 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162763 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012764 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162765 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592766
bnc691fda62016-08-12 00:43:162767 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592768 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582769 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592770 EXPECT_EQ(100, response->headers->GetContentLength());
2771
bnc691fda62016-08-12 00:43:162772 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592773 ASSERT_FALSE(endpoint.address().empty());
2774 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2775}
2776
David Benjamin83ddfb32018-03-30 01:07:522777// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2778// will eventually give up.
2779TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2780 HttpRequestInfo request;
2781 request.method = "GET";
2782 request.url = GURL("http://www.example.org/");
2783 request.traffic_annotation =
2784 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2785
2786 TestNetLog log;
2787 session_deps_.net_log = &log;
2788 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2789 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2790
2791 MockWrite data_writes[] = {
2792 MockWrite("GET / HTTP/1.1\r\n"
2793 "Host: www.example.org\r\n"
2794 "Connection: keep-alive\r\n\r\n"),
2795 };
2796
2797 MockRead data_reads[] = {
2798 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2799 // Give a couple authenticate options (only the middle one is actually
2800 // supported).
2801 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2802 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2803 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2804 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2805 // Large content-length -- won't matter, as connection will be reset.
2806 MockRead("Content-Length: 10000\r\n\r\n"),
2807 MockRead(SYNCHRONOUS, ERR_FAILED),
2808 };
2809
2810 // After calling trans->RestartWithAuth(), this is the request we should
2811 // be issuing -- the final header line contains the credentials.
2812 MockWrite data_writes_restart[] = {
2813 MockWrite("GET / HTTP/1.1\r\n"
2814 "Host: www.example.org\r\n"
2815 "Connection: keep-alive\r\n"
2816 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2817 };
2818
Ryan Sleevib8d7ea02018-05-07 20:01:012819 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522820 session_deps_.socket_factory->AddSocketDataProvider(&data);
2821
2822 TestCompletionCallback callback;
2823 int rv = callback.GetResult(
2824 trans.Start(&request, callback.callback(), NetLogWithSource()));
2825
2826 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2827 for (int i = 0; i < 32; i++) {
2828 // Check the previous response was a 401.
2829 EXPECT_THAT(rv, IsOk());
2830 const HttpResponseInfo* response = trans.GetResponseInfo();
2831 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582832 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522833
2834 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012835 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522836 session_deps_.socket_factory->AddSocketDataProvider(
2837 data_restarts.back().get());
2838 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2839 callback.callback()));
2840 }
2841
2842 // After too many tries, the transaction should have given up.
2843 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2844}
2845
bncd16676a2016-07-20 16:23:012846TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462847 HttpRequestInfo request;
2848 request.method = "GET";
bncce36dca22015-04-21 22:11:232849 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292850 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:102851 request.traffic_annotation =
2852 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462853
danakj1fd259a02016-04-16 03:17:092854 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162855 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272856
[email protected]861fcd52009-08-26 02:33:462857 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232858 MockWrite(
2859 "GET / HTTP/1.1\r\n"
2860 "Host: www.example.org\r\n"
2861 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462862 };
2863
2864 MockRead data_reads[] = {
2865 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2866 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2868 // Large content-length -- won't matter, as connection will be reset.
2869 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062870 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462871 };
2872
Ryan Sleevib8d7ea02018-05-07 20:01:012873 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072874 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412875 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462876
tfarina428341112016-09-22 13:38:202877 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012878 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462879
2880 rv = callback.WaitForResult();
2881 EXPECT_EQ(0, rv);
2882
Ryan Sleevib8d7ea02018-05-07 20:01:012883 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162884 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012885 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162886 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192887
bnc691fda62016-08-12 00:43:162888 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522889 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582890 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462891}
2892
[email protected]2d2697f92009-02-18 21:00:322893// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2894// connection.
bncd16676a2016-07-20 16:23:012895TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182896 // On the second pass, the body read of the auth challenge is synchronous, so
2897 // IsConnectedAndIdle returns false. The socket should still be drained and
2898 // reused. See http://crbug.com/544255.
2899 for (int i = 0; i < 2; ++i) {
2900 HttpRequestInfo request;
2901 request.method = "GET";
2902 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102903 request.traffic_annotation =
2904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322905
mmenkecc2298e2015-12-07 18:20:182906 TestNetLog log;
2907 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092908 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272909
mmenkecc2298e2015-12-07 18:20:182910 MockWrite data_writes[] = {
2911 MockWrite(ASYNC, 0,
2912 "GET / HTTP/1.1\r\n"
2913 "Host: www.example.org\r\n"
2914 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322915
bnc691fda62016-08-12 00:43:162916 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182917 // be issuing -- the final header line contains the credentials.
2918 MockWrite(ASYNC, 6,
2919 "GET / HTTP/1.1\r\n"
2920 "Host: www.example.org\r\n"
2921 "Connection: keep-alive\r\n"
2922 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2923 };
[email protected]2d2697f92009-02-18 21:00:322924
mmenkecc2298e2015-12-07 18:20:182925 MockRead data_reads[] = {
2926 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2927 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2928 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2929 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2930 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322931
mmenkecc2298e2015-12-07 18:20:182932 // Lastly, the server responds with the actual content.
2933 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2934 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2935 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2936 MockRead(ASYNC, 10, "Hello"),
2937 };
[email protected]2d2697f92009-02-18 21:00:322938
Ryan Sleevib8d7ea02018-05-07 20:01:012939 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182940 data.set_busy_before_sync_reads(true);
2941 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462942
mmenkecc2298e2015-12-07 18:20:182943 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322944
bnc691fda62016-08-12 00:43:162945 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:202946 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012947 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322948
mmenkecc2298e2015-12-07 18:20:182949 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162950 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:182951 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322952
bnc691fda62016-08-12 00:43:162953 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182954 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582955 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:322956
mmenkecc2298e2015-12-07 18:20:182957 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252958
bnc691fda62016-08-12 00:43:162959 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2960 callback2.callback());
robpercival214763f2016-07-01 23:27:012961 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322962
mmenkecc2298e2015-12-07 18:20:182963 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162964 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:182965 TestLoadTimingReused(load_timing_info2);
2966 // The load timing after restart should have the same socket ID, and times
2967 // those of the first load timing.
2968 EXPECT_LE(load_timing_info1.receive_headers_end,
2969 load_timing_info2.send_start);
2970 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322971
bnc691fda62016-08-12 00:43:162972 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182973 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582974 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:182975 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322976
mmenkecc2298e2015-12-07 18:20:182977 std::string response_data;
bnc691fda62016-08-12 00:43:162978 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:322979
Ryan Sleevib8d7ea02018-05-07 20:01:012980 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162981 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012982 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162983 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:182984 }
[email protected]2d2697f92009-02-18 21:00:322985}
2986
2987// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2988// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:012989TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422990 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322991 request.method = "GET";
bncce36dca22015-04-21 22:11:232992 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102993 request.traffic_annotation =
2994 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322995
danakj1fd259a02016-04-16 03:17:092996 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272997
[email protected]2d2697f92009-02-18 21:00:322998 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:162999 MockWrite("GET / HTTP/1.1\r\n"
3000 "Host: www.example.org\r\n"
3001 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323002
bnc691fda62016-08-12 00:43:163003 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233004 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163005 MockWrite("GET / HTTP/1.1\r\n"
3006 "Host: www.example.org\r\n"
3007 "Connection: keep-alive\r\n"
3008 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323009 };
3010
[email protected]2d2697f92009-02-18 21:00:323011 MockRead data_reads1[] = {
3012 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3013 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313014 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323015
3016 // Lastly, the server responds with the actual content.
3017 MockRead("HTTP/1.1 200 OK\r\n"),
3018 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503019 MockRead("Content-Length: 5\r\n\r\n"),
3020 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323021 };
3022
[email protected]2d0a4f92011-05-05 16:38:463023 // An incorrect reconnect would cause this to be read.
3024 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063025 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463026 };
3027
Ryan Sleevib8d7ea02018-05-07 20:01:013028 StaticSocketDataProvider data1(data_reads1, data_writes1);
3029 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073030 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3031 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323032
[email protected]49639fa2011-12-20 23:22:413033 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323034
bnc691fda62016-08-12 00:43:163035 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:203036 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013037 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323038
3039 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013040 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323041
bnc691fda62016-08-12 00:43:163042 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523043 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583044 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323045
[email protected]49639fa2011-12-20 23:22:413046 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323047
bnc691fda62016-08-12 00:43:163048 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013049 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323050
3051 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013052 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323053
bnc691fda62016-08-12 00:43:163054 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523055 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583056 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503057 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323058}
3059
3060// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3061// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013062TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423063 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323064 request.method = "GET";
bncce36dca22015-04-21 22:11:233065 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103066 request.traffic_annotation =
3067 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323068
danakj1fd259a02016-04-16 03:17:093069 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273070
[email protected]2d2697f92009-02-18 21:00:323071 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163072 MockWrite("GET / HTTP/1.1\r\n"
3073 "Host: www.example.org\r\n"
3074 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323075
bnc691fda62016-08-12 00:43:163076 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233077 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163078 MockWrite("GET / HTTP/1.1\r\n"
3079 "Host: www.example.org\r\n"
3080 "Connection: keep-alive\r\n"
3081 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323082 };
3083
3084 // Respond with 5 kb of response body.
3085 std::string large_body_string("Unauthorized");
3086 large_body_string.append(5 * 1024, ' ');
3087 large_body_string.append("\r\n");
3088
3089 MockRead data_reads1[] = {
3090 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3091 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3092 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3093 // 5134 = 12 + 5 * 1024 + 2
3094 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063095 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323096
3097 // Lastly, the server responds with the actual content.
3098 MockRead("HTTP/1.1 200 OK\r\n"),
3099 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503100 MockRead("Content-Length: 5\r\n\r\n"),
3101 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323102 };
3103
[email protected]2d0a4f92011-05-05 16:38:463104 // An incorrect reconnect would cause this to be read.
3105 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063106 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463107 };
3108
Ryan Sleevib8d7ea02018-05-07 20:01:013109 StaticSocketDataProvider data1(data_reads1, data_writes1);
3110 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073111 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3112 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323113
[email protected]49639fa2011-12-20 23:22:413114 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323115
bnc691fda62016-08-12 00:43:163116 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:203117 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323119
3120 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013121 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323122
bnc691fda62016-08-12 00:43:163123 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523124 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583125 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323126
[email protected]49639fa2011-12-20 23:22:413127 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323128
bnc691fda62016-08-12 00:43:163129 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013130 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323131
3132 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013133 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323134
bnc691fda62016-08-12 00:43:163135 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523136 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583137 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503138 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323139}
3140
3141// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313142// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013143TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313144 HttpRequestInfo request;
3145 request.method = "GET";
bncce36dca22015-04-21 22:11:233146 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103147 request.traffic_annotation =
3148 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313149
danakj1fd259a02016-04-16 03:17:093150 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273151
[email protected]11203f012009-11-12 23:02:313152 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233153 MockWrite(
3154 "GET / HTTP/1.1\r\n"
3155 "Host: www.example.org\r\n"
3156 "Connection: keep-alive\r\n\r\n"),
3157 // This simulates the seemingly successful write to a closed connection
3158 // if the bug is not fixed.
3159 MockWrite(
3160 "GET / HTTP/1.1\r\n"
3161 "Host: www.example.org\r\n"
3162 "Connection: keep-alive\r\n"
3163 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313164 };
3165
3166 MockRead data_reads1[] = {
3167 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3168 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3169 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3170 MockRead("Content-Length: 14\r\n\r\n"),
3171 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063172 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313173 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063174 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313175 };
3176
bnc691fda62016-08-12 00:43:163177 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313178 // be issuing -- the final header line contains the credentials.
3179 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233180 MockWrite(
3181 "GET / HTTP/1.1\r\n"
3182 "Host: www.example.org\r\n"
3183 "Connection: keep-alive\r\n"
3184 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313185 };
3186
3187 // Lastly, the server responds with the actual content.
3188 MockRead data_reads2[] = {
3189 MockRead("HTTP/1.1 200 OK\r\n"),
3190 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503191 MockRead("Content-Length: 5\r\n\r\n"),
3192 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313193 };
3194
Ryan Sleevib8d7ea02018-05-07 20:01:013195 StaticSocketDataProvider data1(data_reads1, data_writes1);
3196 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073197 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3198 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313199
[email protected]49639fa2011-12-20 23:22:413200 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313201
bnc691fda62016-08-12 00:43:163202 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:203203 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013204 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313205
3206 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013207 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313208
bnc691fda62016-08-12 00:43:163209 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523210 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583211 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313212
[email protected]49639fa2011-12-20 23:22:413213 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313214
bnc691fda62016-08-12 00:43:163215 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013216 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313217
3218 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013219 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313220
bnc691fda62016-08-12 00:43:163221 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523222 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583223 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503224 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313225}
3226
[email protected]394816e92010-08-03 07:38:593227// Test the request-challenge-retry sequence for basic auth, over a connection
3228// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013229TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013230 HttpRequestInfo request;
3231 request.method = "GET";
bncce36dca22015-04-21 22:11:233232 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013233 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293234 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103235 request.traffic_annotation =
3236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013237
3238 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593239 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493240 ProxyResolutionService::CreateFixedFromPacResult(
3241 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513242 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013243 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093244 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013245
3246 // Since we have proxy, should try to establish tunnel.
3247 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543248 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173249 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543250 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013251 };
3252
mmenkee71e15332015-10-07 16:39:543253 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013254 // connection.
3255 MockRead data_reads1[] = {
3256 // No credentials.
3257 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3258 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543259 };
ttuttle34f63b52015-03-05 04:33:013260
mmenkee71e15332015-10-07 16:39:543261 // Since the first connection couldn't be reused, need to establish another
3262 // once given credentials.
3263 MockWrite data_writes2[] = {
3264 // After calling trans->RestartWithAuth(), this is the request we should
3265 // be issuing -- the final header line contains the credentials.
3266 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173267 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543268 "Proxy-Connection: keep-alive\r\n"
3269 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3270
3271 MockWrite("GET / HTTP/1.1\r\n"
3272 "Host: www.example.org\r\n"
3273 "Connection: keep-alive\r\n\r\n"),
3274 };
3275
3276 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013277 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3278
3279 MockRead("HTTP/1.1 200 OK\r\n"),
3280 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3281 MockRead("Content-Length: 5\r\n\r\n"),
3282 MockRead(SYNCHRONOUS, "hello"),
3283 };
3284
Ryan Sleevib8d7ea02018-05-07 20:01:013285 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013286 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013287 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543288 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013289 SSLSocketDataProvider ssl(ASYNC, OK);
3290 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3291
3292 TestCompletionCallback callback1;
3293
bnc87dcefc2017-05-25 12:47:583294 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193295 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013296
3297 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013299
3300 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013301 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543302 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013303 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003304 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3305 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013306 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003307 entries, pos,
3308 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3309 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013310
3311 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523312 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013313 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523314 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013315 EXPECT_EQ(407, response->headers->response_code());
3316 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583317 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013318
3319 LoadTimingInfo load_timing_info;
3320 // CONNECT requests and responses are handled at the connect job level, so
3321 // the transaction does not yet have a connection.
3322 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3323
3324 TestCompletionCallback callback2;
3325
3326 rv =
3327 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013328 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013329
3330 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013331 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013332
3333 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523334 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013335
3336 EXPECT_TRUE(response->headers->IsKeepAlive());
3337 EXPECT_EQ(200, response->headers->response_code());
3338 EXPECT_EQ(5, response->headers->GetContentLength());
3339 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3340
Matt Menke96092e62019-10-18 04:09:333341 // Check that credentials were successfully cached, with the right target.
3342 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
3343 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
3344 HttpAuth::AUTH_SCHEME_BASIC);
3345 ASSERT_TRUE(entry);
3346 ASSERT_EQ(kFoo, entry->credentials().username());
3347 ASSERT_EQ(kBar, entry->credentials().password());
3348
ttuttle34f63b52015-03-05 04:33:013349 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583350 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013351
3352 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3353 TestLoadTimingNotReusedWithPac(load_timing_info,
3354 CONNECT_TIMING_HAS_SSL_TIMES);
3355
3356 trans.reset();
3357 session->CloseAllConnections();
3358}
3359
3360// Test the request-challenge-retry sequence for basic auth, over a connection
3361// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013362TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593363 HttpRequestInfo request;
3364 request.method = "GET";
bncce36dca22015-04-21 22:11:233365 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593366 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293367 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103368 request.traffic_annotation =
3369 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593370
[email protected]cb9bf6ca2011-01-28 13:15:273371 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593372 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493373 ProxyResolutionService::CreateFixedFromPacResult(
3374 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513375 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073376 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093377 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273378
[email protected]394816e92010-08-03 07:38:593379 // Since we have proxy, should try to establish tunnel.
3380 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543381 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173382 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543383 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113384 };
3385
mmenkee71e15332015-10-07 16:39:543386 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083387 // connection.
3388 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543389 // No credentials.
3390 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3391 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3392 MockRead("Proxy-Connection: close\r\n\r\n"),
3393 };
mmenkee0b5c882015-08-26 20:29:113394
mmenkee71e15332015-10-07 16:39:543395 MockWrite data_writes2[] = {
3396 // After calling trans->RestartWithAuth(), this is the request we should
3397 // be issuing -- the final header line contains the credentials.
3398 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173399 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543400 "Proxy-Connection: keep-alive\r\n"
3401 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083402
mmenkee71e15332015-10-07 16:39:543403 MockWrite("GET / HTTP/1.1\r\n"
3404 "Host: www.example.org\r\n"
3405 "Connection: keep-alive\r\n\r\n"),
3406 };
3407
3408 MockRead data_reads2[] = {
3409 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3410
3411 MockRead("HTTP/1.1 200 OK\r\n"),
3412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3413 MockRead("Content-Length: 5\r\n\r\n"),
3414 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593415 };
3416
Ryan Sleevib8d7ea02018-05-07 20:01:013417 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073418 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013419 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543420 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063421 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593423
[email protected]49639fa2011-12-20 23:22:413424 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593425
bnc87dcefc2017-05-25 12:47:583426 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193427 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503428
[email protected]49639fa2011-12-20 23:22:413429 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013430 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593431
3432 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013433 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543434 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593435 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003436 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3437 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593438 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403439 entries, pos,
mikecirone8b85c432016-09-08 19:11:003440 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3441 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593442
3443 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523444 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013445 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523446 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593447 EXPECT_EQ(407, response->headers->response_code());
3448 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583449 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593450
[email protected]029c83b62013-01-24 05:28:203451 LoadTimingInfo load_timing_info;
3452 // CONNECT requests and responses are handled at the connect job level, so
3453 // the transaction does not yet have a connection.
3454 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3455
[email protected]49639fa2011-12-20 23:22:413456 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593457
[email protected]49639fa2011-12-20 23:22:413458 rv = trans->RestartWithAuth(
3459 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013460 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593461
3462 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013463 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593464
3465 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523466 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593467
3468 EXPECT_TRUE(response->headers->IsKeepAlive());
3469 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503470 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593471 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3472
3473 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583474 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503475
[email protected]029c83b62013-01-24 05:28:203476 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3477 TestLoadTimingNotReusedWithPac(load_timing_info,
3478 CONNECT_TIMING_HAS_SSL_TIMES);
3479
[email protected]0b0bf032010-09-21 18:08:503480 trans.reset();
[email protected]102e27c2011-02-23 01:01:313481 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:593482}
3483
[email protected]11203f012009-11-12 23:02:313484// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013485// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013486TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233487 // On the second pass, the body read of the auth challenge is synchronous, so
3488 // IsConnectedAndIdle returns false. The socket should still be drained and
3489 // reused. See http://crbug.com/544255.
3490 for (int i = 0; i < 2; ++i) {
3491 HttpRequestInfo request;
3492 request.method = "GET";
3493 request.url = GURL("https://www.example.org/");
3494 // Ensure that proxy authentication is attempted even
3495 // when the no authentication data flag is set.
3496 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103497 request.traffic_annotation =
3498 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013499
mmenked39192ee2015-12-09 00:57:233500 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593501 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493502 ProxyResolutionService::CreateFixed("myproxy:70",
3503 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233504 BoundTestNetLog log;
3505 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093506 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013507
bnc691fda62016-08-12 00:43:163508 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013509
mmenked39192ee2015-12-09 00:57:233510 // Since we have proxy, should try to establish tunnel.
3511 MockWrite data_writes1[] = {
3512 MockWrite(ASYNC, 0,
3513 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3514 "Host: www.example.org:443\r\n"
3515 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013516
bnc691fda62016-08-12 00:43:163517 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233518 // be issuing -- the final header line contains the credentials.
3519 MockWrite(ASYNC, 3,
3520 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3521 "Host: www.example.org:443\r\n"
3522 "Proxy-Connection: keep-alive\r\n"
3523 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3524 };
ttuttle34f63b52015-03-05 04:33:013525
mmenked39192ee2015-12-09 00:57:233526 // The proxy responds to the connect with a 407, using a persistent
3527 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3528 MockRead data_reads1[] = {
3529 // No credentials.
3530 MockRead(ASYNC, 1,
3531 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3532 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3533 "Proxy-Connection: keep-alive\r\n"
3534 "Content-Length: 10\r\n\r\n"),
3535 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013536
mmenked39192ee2015-12-09 00:57:233537 // Wrong credentials (wrong password).
3538 MockRead(ASYNC, 4,
3539 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3540 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3541 "Proxy-Connection: keep-alive\r\n"
3542 "Content-Length: 10\r\n\r\n"),
3543 // No response body because the test stops reading here.
3544 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3545 };
ttuttle34f63b52015-03-05 04:33:013546
Ryan Sleevib8d7ea02018-05-07 20:01:013547 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233548 data1.set_busy_before_sync_reads(true);
3549 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013550
mmenked39192ee2015-12-09 00:57:233551 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013552
bnc691fda62016-08-12 00:43:163553 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013554 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013555
Eric Roman79cc7552019-07-19 02:17:543556 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233557 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003558 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3559 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233560 ExpectLogContainsSomewhere(
3561 entries, pos,
mikecirone8b85c432016-09-08 19:11:003562 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3563 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013564
bnc691fda62016-08-12 00:43:163565 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233566 ASSERT_TRUE(response);
3567 ASSERT_TRUE(response->headers);
3568 EXPECT_TRUE(response->headers->IsKeepAlive());
3569 EXPECT_EQ(407, response->headers->response_code());
3570 EXPECT_EQ(10, response->headers->GetContentLength());
3571 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583572 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013573
mmenked39192ee2015-12-09 00:57:233574 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013575
mmenked39192ee2015-12-09 00:57:233576 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163577 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3578 callback2.callback());
robpercival214763f2016-07-01 23:27:013579 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013580
bnc691fda62016-08-12 00:43:163581 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233582 ASSERT_TRUE(response);
3583 ASSERT_TRUE(response->headers);
3584 EXPECT_TRUE(response->headers->IsKeepAlive());
3585 EXPECT_EQ(407, response->headers->response_code());
3586 EXPECT_EQ(10, response->headers->GetContentLength());
3587 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583588 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013589
mmenked39192ee2015-12-09 00:57:233590 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3591 // out of scope.
3592 session->CloseAllConnections();
3593 }
ttuttle34f63b52015-03-05 04:33:013594}
3595
3596// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3597// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013598TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233599 // On the second pass, the body read of the auth challenge is synchronous, so
3600 // IsConnectedAndIdle returns false. The socket should still be drained and
3601 // reused. See http://crbug.com/544255.
3602 for (int i = 0; i < 2; ++i) {
3603 HttpRequestInfo request;
3604 request.method = "GET";
3605 request.url = GURL("https://www.example.org/");
3606 // Ensure that proxy authentication is attempted even
3607 // when the no authentication data flag is set.
3608 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103609 request.traffic_annotation =
3610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233611
3612 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593613 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493614 ProxyResolutionService::CreateFixed("myproxy:70",
3615 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233616 BoundTestNetLog log;
3617 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093618 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233619
bnc691fda62016-08-12 00:43:163620 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233621
3622 // Since we have proxy, should try to establish tunnel.
3623 MockWrite data_writes1[] = {
3624 MockWrite(ASYNC, 0,
3625 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3626 "Host: www.example.org:443\r\n"
3627 "Proxy-Connection: keep-alive\r\n\r\n"),
3628
bnc691fda62016-08-12 00:43:163629 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233630 // be issuing -- the final header line contains the credentials.
3631 MockWrite(ASYNC, 3,
3632 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3633 "Host: www.example.org:443\r\n"
3634 "Proxy-Connection: keep-alive\r\n"
3635 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3636 };
3637
3638 // The proxy responds to the connect with a 407, using a persistent
3639 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3640 MockRead data_reads1[] = {
3641 // No credentials.
3642 MockRead(ASYNC, 1,
3643 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3644 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3645 "Content-Length: 10\r\n\r\n"),
3646 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3647
3648 // Wrong credentials (wrong password).
3649 MockRead(ASYNC, 4,
3650 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3651 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3652 "Content-Length: 10\r\n\r\n"),
3653 // No response body because the test stops reading here.
3654 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3655 };
3656
Ryan Sleevib8d7ea02018-05-07 20:01:013657 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233658 data1.set_busy_before_sync_reads(true);
3659 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3660
3661 TestCompletionCallback callback1;
3662
bnc691fda62016-08-12 00:43:163663 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013664 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233665
Eric Roman79cc7552019-07-19 02:17:543666 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233667 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003668 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3669 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233670 ExpectLogContainsSomewhere(
3671 entries, pos,
mikecirone8b85c432016-09-08 19:11:003672 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3673 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233674
bnc691fda62016-08-12 00:43:163675 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233676 ASSERT_TRUE(response);
3677 ASSERT_TRUE(response->headers);
3678 EXPECT_TRUE(response->headers->IsKeepAlive());
3679 EXPECT_EQ(407, response->headers->response_code());
3680 EXPECT_EQ(10, response->headers->GetContentLength());
3681 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583682 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503683 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233684
3685 TestCompletionCallback callback2;
3686
3687 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163688 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3689 callback2.callback());
robpercival214763f2016-07-01 23:27:013690 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233691
bnc691fda62016-08-12 00:43:163692 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233693 ASSERT_TRUE(response);
3694 ASSERT_TRUE(response->headers);
3695 EXPECT_TRUE(response->headers->IsKeepAlive());
3696 EXPECT_EQ(407, response->headers->response_code());
3697 EXPECT_EQ(10, response->headers->GetContentLength());
3698 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583699 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503700 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233701
3702 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3703 // out of scope.
3704 session->CloseAllConnections();
3705 }
3706}
3707
3708// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3709// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3710// the case the server sends extra data on the original socket, so it can't be
3711// reused.
bncd16676a2016-07-20 16:23:013712TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273713 HttpRequestInfo request;
3714 request.method = "GET";
bncce36dca22015-04-21 22:11:233715 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273716 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293717 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103718 request.traffic_annotation =
3719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273720
[email protected]2d2697f92009-02-18 21:00:323721 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593722 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493723 ProxyResolutionService::CreateFixedFromPacResult(
3724 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513725 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073726 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093727 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323728
[email protected]2d2697f92009-02-18 21:00:323729 // Since we have proxy, should try to establish tunnel.
3730 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233731 MockWrite(ASYNC, 0,
3732 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173733 "Host: www.example.org:443\r\n"
3734 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233735 };
[email protected]2d2697f92009-02-18 21:00:323736
mmenked39192ee2015-12-09 00:57:233737 // The proxy responds to the connect with a 407, using a persistent, but sends
3738 // extra data, so the socket cannot be reused.
3739 MockRead data_reads1[] = {
3740 // No credentials.
3741 MockRead(ASYNC, 1,
3742 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3743 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3744 "Content-Length: 10\r\n\r\n"),
3745 MockRead(SYNCHRONOUS, 2, "0123456789"),
3746 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3747 };
3748
3749 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233750 // After calling trans->RestartWithAuth(), this is the request we should
3751 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233752 MockWrite(ASYNC, 0,
3753 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173754 "Host: www.example.org:443\r\n"
3755 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233756 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3757
3758 MockWrite(ASYNC, 2,
3759 "GET / HTTP/1.1\r\n"
3760 "Host: www.example.org\r\n"
3761 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323762 };
3763
mmenked39192ee2015-12-09 00:57:233764 MockRead data_reads2[] = {
3765 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323766
mmenked39192ee2015-12-09 00:57:233767 MockRead(ASYNC, 3,
3768 "HTTP/1.1 200 OK\r\n"
3769 "Content-Type: text/html; charset=iso-8859-1\r\n"
3770 "Content-Length: 5\r\n\r\n"),
3771 // No response body because the test stops reading here.
3772 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323773 };
3774
Ryan Sleevib8d7ea02018-05-07 20:01:013775 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233776 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073777 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013778 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233779 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3780 SSLSocketDataProvider ssl(ASYNC, OK);
3781 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323782
[email protected]49639fa2011-12-20 23:22:413783 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323784
bnc87dcefc2017-05-25 12:47:583785 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193786 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323787
mmenked39192ee2015-12-09 00:57:233788 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013789 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233790
Eric Roman79cc7552019-07-19 02:17:543791 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393792 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003793 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3794 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393795 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403796 entries, pos,
mikecirone8b85c432016-09-08 19:11:003797 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3798 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323799
[email protected]1c773ea12009-04-28 19:58:423800 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243801 ASSERT_TRUE(response);
3802 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323803 EXPECT_TRUE(response->headers->IsKeepAlive());
3804 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423805 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583806 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323807
mmenked39192ee2015-12-09 00:57:233808 LoadTimingInfo load_timing_info;
3809 // CONNECT requests and responses are handled at the connect job level, so
3810 // the transaction does not yet have a connection.
3811 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3812
[email protected]49639fa2011-12-20 23:22:413813 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323814
mmenked39192ee2015-12-09 00:57:233815 rv =
3816 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013817 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323818
[email protected]2d2697f92009-02-18 21:00:323819 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233820 EXPECT_EQ(200, response->headers->response_code());
3821 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423822 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133823
mmenked39192ee2015-12-09 00:57:233824 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583825 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233826
3827 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3828 TestLoadTimingNotReusedWithPac(load_timing_info,
3829 CONNECT_TIMING_HAS_SSL_TIMES);
3830
3831 trans.reset();
[email protected]102e27c2011-02-23 01:01:313832 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323833}
3834
mmenkee71e15332015-10-07 16:39:543835// Test the case a proxy closes a socket while the challenge body is being
3836// drained.
bncd16676a2016-07-20 16:23:013837TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543838 HttpRequestInfo request;
3839 request.method = "GET";
3840 request.url = GURL("https://www.example.org/");
3841 // Ensure that proxy authentication is attempted even
3842 // when the no authentication data flag is set.
3843 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103844 request.traffic_annotation =
3845 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543846
3847 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493848 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3849 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093850 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543851
bnc691fda62016-08-12 00:43:163852 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543853
3854 // Since we have proxy, should try to establish tunnel.
3855 MockWrite data_writes1[] = {
3856 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173857 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543858 "Proxy-Connection: keep-alive\r\n\r\n"),
3859 };
3860
3861 // The proxy responds to the connect with a 407, using a persistent
3862 // connection.
3863 MockRead data_reads1[] = {
3864 // No credentials.
3865 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3866 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3867 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3868 // Server hands up in the middle of the body.
3869 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3870 };
3871
3872 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163873 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543874 // be issuing -- the final header line contains the credentials.
3875 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173876 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543877 "Proxy-Connection: keep-alive\r\n"
3878 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3879
3880 MockWrite("GET / HTTP/1.1\r\n"
3881 "Host: www.example.org\r\n"
3882 "Connection: keep-alive\r\n\r\n"),
3883 };
3884
3885 MockRead data_reads2[] = {
3886 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3887
3888 MockRead("HTTP/1.1 200 OK\r\n"),
3889 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3890 MockRead("Content-Length: 5\r\n\r\n"),
3891 MockRead(SYNCHRONOUS, "hello"),
3892 };
3893
Ryan Sleevib8d7ea02018-05-07 20:01:013894 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543895 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013896 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543897 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3898 SSLSocketDataProvider ssl(ASYNC, OK);
3899 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3900
3901 TestCompletionCallback callback;
3902
tfarina428341112016-09-22 13:38:203903 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013904 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543905
bnc691fda62016-08-12 00:43:163906 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543907 ASSERT_TRUE(response);
3908 ASSERT_TRUE(response->headers);
3909 EXPECT_TRUE(response->headers->IsKeepAlive());
3910 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583911 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543912
bnc691fda62016-08-12 00:43:163913 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013914 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543915
bnc691fda62016-08-12 00:43:163916 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543917 ASSERT_TRUE(response);
3918 ASSERT_TRUE(response->headers);
3919 EXPECT_TRUE(response->headers->IsKeepAlive());
3920 EXPECT_EQ(200, response->headers->response_code());
3921 std::string body;
bnc691fda62016-08-12 00:43:163922 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543923 EXPECT_EQ("hello", body);
3924}
3925
[email protected]a8e9b162009-03-12 00:06:443926// Test that we don't read the response body when we fail to establish a tunnel,
3927// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013928TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273929 HttpRequestInfo request;
3930 request.method = "GET";
bncce36dca22015-04-21 22:11:233931 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103932 request.traffic_annotation =
3933 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273934
[email protected]a8e9b162009-03-12 00:06:443935 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493936 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3937 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443938
danakj1fd259a02016-04-16 03:17:093939 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443940
bnc691fda62016-08-12 00:43:163941 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443942
[email protected]a8e9b162009-03-12 00:06:443943 // Since we have proxy, should try to establish tunnel.
3944 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173945 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3946 "Host: www.example.org:443\r\n"
3947 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443948 };
3949
3950 // The proxy responds to the connect with a 407.
3951 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243952 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3953 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3954 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233955 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243956 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443957 };
3958
Ryan Sleevib8d7ea02018-05-07 20:01:013959 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073960 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443961
[email protected]49639fa2011-12-20 23:22:413962 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443963
tfarina428341112016-09-22 13:38:203964 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013965 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:443966
3967 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013968 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:443969
bnc691fda62016-08-12 00:43:163970 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243971 ASSERT_TRUE(response);
3972 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443973 EXPECT_TRUE(response->headers->IsKeepAlive());
3974 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423975 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443976
3977 std::string response_data;
bnc691fda62016-08-12 00:43:163978 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:013979 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:183980
3981 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313982 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443983}
3984
Matt Menke96092e62019-10-18 04:09:333985// Test the no-tunnel HTTP auth case where proxy and server origins and realms
3986// are the same, but the user/passwords are different. Serves to verify
3987// credentials are correctly separated based on HttpAuth::Target.
3988TEST_F(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
3989 HttpRequestInfo request;
3990 request.method = "GET";
3991 request.url = GURL("http://myproxy:70/");
3992 request.traffic_annotation =
3993 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3994
3995 // Proxy matches request URL.
3996 session_deps_.proxy_resolution_service =
3997 ProxyResolutionService::CreateFixedFromPacResult(
3998 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
3999 BoundTestNetLog log;
4000 session_deps_.net_log = log.bound().net_log();
4001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4002
4003 MockWrite data_writes[] = {
4004 // Initial request gets a proxy auth challenge.
4005 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4006 "Host: myproxy:70\r\n"
4007 "Proxy-Connection: keep-alive\r\n\r\n"),
4008 // Rety with proxy auth credentials, which will result in a server auth
4009 // challenge.
4010 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4011 "Host: myproxy:70\r\n"
4012 "Proxy-Connection: keep-alive\r\n"
4013 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4014 // Rety with proxy and server auth credentials, which gets a response.
4015 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4016 "Host: myproxy:70\r\n"
4017 "Proxy-Connection: keep-alive\r\n"
4018 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4019 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4020 // A second request should preemptively send the correct proxy and server
4021 // auth headers.
4022 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4023 "Host: myproxy:70\r\n"
4024 "Proxy-Connection: keep-alive\r\n"
4025 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4026 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4027 };
4028
4029 MockRead data_reads[] = {
4030 // Proxy auth challenge.
4031 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4032 "Proxy-Connection: keep-alive\r\n"
4033 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4034 "Content-Length: 0\r\n\r\n"),
4035 // Server auth challenge.
4036 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4037 "Proxy-Connection: keep-alive\r\n"
4038 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4039 "Content-Length: 0\r\n\r\n"),
4040 // Response.
4041 MockRead("HTTP/1.1 200 OK\r\n"
4042 "Proxy-Connection: keep-alive\r\n"
4043 "Content-Length: 5\r\n\r\n"
4044 "hello"),
4045 // Response to second request.
4046 MockRead("HTTP/1.1 200 OK\r\n"
4047 "Proxy-Connection: keep-alive\r\n"
4048 "Content-Length: 2\r\n\r\n"
4049 "hi"),
4050 };
4051
4052 StaticSocketDataProvider data(data_reads, data_writes);
4053 session_deps_.socket_factory->AddSocketDataProvider(&data);
4054
4055 TestCompletionCallback callback;
4056
4057 auto trans =
4058 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4059 int rv = trans->Start(&request, callback.callback(), log.bound());
4060 EXPECT_THAT(callback.GetResult(rv), IsOk());
4061 const HttpResponseInfo* response = trans->GetResponseInfo();
4062 ASSERT_TRUE(response);
4063 ASSERT_TRUE(response->headers);
4064 EXPECT_EQ(407, response->headers->response_code());
4065 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4066
4067 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4068 EXPECT_THAT(callback.GetResult(rv), IsOk());
4069 response = trans->GetResponseInfo();
4070 ASSERT_TRUE(response);
4071 EXPECT_EQ(401, response->headers->response_code());
4072 EXPECT_FALSE(response->auth_challenge->is_proxy);
4073 EXPECT_EQ("http://myproxy:70",
4074 response->auth_challenge->challenger.Serialize());
4075 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4076 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4077
4078 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4079 callback.callback());
4080 EXPECT_THAT(callback.GetResult(rv), IsOk());
4081 response = trans->GetResponseInfo();
4082 ASSERT_TRUE(response);
4083 EXPECT_EQ(200, response->headers->response_code());
4084 // The password prompt info should not be set.
4085 EXPECT_FALSE(response->auth_challenge.has_value());
4086
4087 std::string response_data;
4088 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4089 EXPECT_EQ("hello", response_data);
4090
4091 // Check that the credentials were cached correctly.
4092 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4093 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4094 HttpAuth::AUTH_SCHEME_BASIC);
4095 ASSERT_TRUE(entry);
4096 ASSERT_EQ(kFoo, entry->credentials().username());
4097 ASSERT_EQ(kBar, entry->credentials().password());
4098 entry = session->http_auth_cache()->Lookup(GURL("http://myproxy:70"),
4099 HttpAuth::AUTH_SERVER, "MyRealm1",
4100 HttpAuth::AUTH_SCHEME_BASIC);
4101 ASSERT_TRUE(entry);
4102 ASSERT_EQ(kFoo2, entry->credentials().username());
4103 ASSERT_EQ(kBar2, entry->credentials().password());
4104
4105 // Make another request, which should automatically send the correct proxy and
4106 // server auth credentials and get another response.
4107 trans =
4108 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4109 rv = trans->Start(&request, callback.callback(), log.bound());
4110 EXPECT_THAT(callback.GetResult(rv), IsOk());
4111 response = trans->GetResponseInfo();
4112 ASSERT_TRUE(response);
4113 EXPECT_EQ(200, response->headers->response_code());
4114 // The password prompt info should not be set.
4115 EXPECT_FALSE(response->auth_challenge.has_value());
4116
4117 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4118 EXPECT_EQ("hi", response_data);
4119
4120 trans.reset();
4121 session->CloseAllConnections();
4122}
4123
ttuttle7933c112015-01-06 00:55:244124// Test that we don't pass extraneous headers from the proxy's response to the
4125// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014126TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244127 HttpRequestInfo request;
4128 request.method = "GET";
bncce36dca22015-04-21 22:11:234129 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104130 request.traffic_annotation =
4131 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244132
4133 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:494134 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4135 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244136
danakj1fd259a02016-04-16 03:17:094137 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244138
bnc691fda62016-08-12 00:43:164139 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244140
4141 // Since we have proxy, should try to establish tunnel.
4142 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174143 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4144 "Host: www.example.org:443\r\n"
4145 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244146 };
4147
4148 // The proxy responds to the connect with a 407.
4149 MockRead data_reads[] = {
4150 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4151 MockRead("X-Foo: bar\r\n"),
4152 MockRead("Set-Cookie: foo=bar\r\n"),
4153 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4154 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234155 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244156 };
4157
Ryan Sleevib8d7ea02018-05-07 20:01:014158 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244159 session_deps_.socket_factory->AddSocketDataProvider(&data);
4160
4161 TestCompletionCallback callback;
4162
tfarina428341112016-09-22 13:38:204163 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014164 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244165
4166 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014167 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244168
bnc691fda62016-08-12 00:43:164169 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244170 ASSERT_TRUE(response);
4171 ASSERT_TRUE(response->headers);
4172 EXPECT_TRUE(response->headers->IsKeepAlive());
4173 EXPECT_EQ(407, response->headers->response_code());
4174 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4175 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4176 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4177
4178 std::string response_data;
bnc691fda62016-08-12 00:43:164179 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014180 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244181
4182 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4183 session->CloseAllConnections();
4184}
4185
[email protected]8fdbcd22010-05-05 02:54:524186// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4187// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014188TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524189 HttpRequestInfo request;
4190 request.method = "GET";
bncce36dca22015-04-21 22:11:234191 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104192 request.traffic_annotation =
4193 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524194
[email protected]cb9bf6ca2011-01-28 13:15:274195 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094196 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164197 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274198
[email protected]8fdbcd22010-05-05 02:54:524199 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234200 MockWrite(
4201 "GET / HTTP/1.1\r\n"
4202 "Host: www.example.org\r\n"
4203 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524204 };
4205
4206 MockRead data_reads1[] = {
4207 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4208 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4209 // Large content-length -- won't matter, as connection will be reset.
4210 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064211 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524212 };
4213
Ryan Sleevib8d7ea02018-05-07 20:01:014214 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074215 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524216
[email protected]49639fa2011-12-20 23:22:414217 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524218
tfarina428341112016-09-22 13:38:204219 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014220 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524221
4222 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014223 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524224}
4225
[email protected]7a67a8152010-11-05 18:31:104226// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4227// through a non-authenticating proxy. The request should fail with
4228// ERR_UNEXPECTED_PROXY_AUTH.
4229// Note that it is impossible to detect if an HTTP server returns a 407 through
4230// a non-authenticating proxy - there is nothing to indicate whether the
4231// response came from the proxy or the server, so it is treated as if the proxy
4232// issued the challenge.
bncd16676a2016-07-20 16:23:014233TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274234 HttpRequestInfo request;
4235 request.method = "GET";
bncce36dca22015-04-21 22:11:234236 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104237 request.traffic_annotation =
4238 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274239
Ramin Halavatica8d5252018-03-12 05:33:494240 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4241 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514242 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074243 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094244 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104245
[email protected]7a67a8152010-11-05 18:31:104246 // Since we have proxy, should try to establish tunnel.
4247 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174248 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4249 "Host: www.example.org:443\r\n"
4250 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104251
rsleevidb16bb02015-11-12 23:47:174252 MockWrite("GET / HTTP/1.1\r\n"
4253 "Host: www.example.org\r\n"
4254 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104255 };
4256
4257 MockRead data_reads1[] = {
4258 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4259
4260 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4261 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4262 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064263 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104264 };
4265
Ryan Sleevib8d7ea02018-05-07 20:01:014266 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074267 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064268 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104270
[email protected]49639fa2011-12-20 23:22:414271 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104272
bnc691fda62016-08-12 00:43:164273 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104274
bnc691fda62016-08-12 00:43:164275 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014276 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104277
4278 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014279 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544280 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104281 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004282 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4283 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104284 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404285 entries, pos,
mikecirone8b85c432016-09-08 19:11:004286 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4287 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104288}
[email protected]2df19bb2010-08-25 20:13:464289
mmenke2a1781d2015-10-07 19:25:334290// Test a proxy auth scheme that allows default credentials and a proxy server
4291// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014292TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334293 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4294 HttpRequestInfo request;
4295 request.method = "GET";
4296 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104297 request.traffic_annotation =
4298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334299
4300 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594301 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494302 ProxyResolutionService::CreateFixedFromPacResult(
4303 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334304
Jeremy Roman0579ed62017-08-29 15:56:194305 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334306 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194307 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334308 mock_handler->set_allows_default_credentials(true);
4309 auth_handler_factory->AddMockHandler(mock_handler.release(),
4310 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484311 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334312
4313 // Add NetLog just so can verify load timing information gets a NetLog ID.
4314 NetLog net_log;
4315 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094316 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334317
4318 // Since we have proxy, should try to establish tunnel.
4319 MockWrite data_writes1[] = {
4320 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174321 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334322 "Proxy-Connection: keep-alive\r\n\r\n"),
4323 };
4324
4325 // The proxy responds to the connect with a 407, using a non-persistent
4326 // connection.
4327 MockRead data_reads1[] = {
4328 // No credentials.
4329 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4330 MockRead("Proxy-Authenticate: Mock\r\n"),
4331 MockRead("Proxy-Connection: close\r\n\r\n"),
4332 };
4333
4334 // Since the first connection couldn't be reused, need to establish another
4335 // once given credentials.
4336 MockWrite data_writes2[] = {
4337 // After calling trans->RestartWithAuth(), this is the request we should
4338 // be issuing -- the final header line contains the credentials.
4339 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174340 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334341 "Proxy-Connection: keep-alive\r\n"
4342 "Proxy-Authorization: auth_token\r\n\r\n"),
4343
4344 MockWrite("GET / HTTP/1.1\r\n"
4345 "Host: www.example.org\r\n"
4346 "Connection: keep-alive\r\n\r\n"),
4347 };
4348
4349 MockRead data_reads2[] = {
4350 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4351
4352 MockRead("HTTP/1.1 200 OK\r\n"),
4353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4354 MockRead("Content-Length: 5\r\n\r\n"),
4355 MockRead(SYNCHRONOUS, "hello"),
4356 };
4357
Ryan Sleevib8d7ea02018-05-07 20:01:014358 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334359 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014360 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334361 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4362 SSLSocketDataProvider ssl(ASYNC, OK);
4363 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4364
bnc87dcefc2017-05-25 12:47:584365 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194366 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334367
4368 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:204369 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014370 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334371
4372 const HttpResponseInfo* response = trans->GetResponseInfo();
4373 ASSERT_TRUE(response);
4374 ASSERT_TRUE(response->headers);
4375 EXPECT_FALSE(response->headers->IsKeepAlive());
4376 EXPECT_EQ(407, response->headers->response_code());
4377 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4378 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584379 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334380
4381 LoadTimingInfo load_timing_info;
4382 // CONNECT requests and responses are handled at the connect job level, so
4383 // the transaction does not yet have a connection.
4384 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4385
4386 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014387 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334388 response = trans->GetResponseInfo();
4389 ASSERT_TRUE(response);
4390 ASSERT_TRUE(response->headers);
4391 EXPECT_TRUE(response->headers->IsKeepAlive());
4392 EXPECT_EQ(200, response->headers->response_code());
4393 EXPECT_EQ(5, response->headers->GetContentLength());
4394 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4395
4396 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584397 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334398
4399 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4400 TestLoadTimingNotReusedWithPac(load_timing_info,
4401 CONNECT_TIMING_HAS_SSL_TIMES);
4402
4403 trans.reset();
4404 session->CloseAllConnections();
4405}
4406
4407// Test a proxy auth scheme that allows default credentials and a proxy server
4408// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014409TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334410 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4411 HttpRequestInfo request;
4412 request.method = "GET";
4413 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104414 request.traffic_annotation =
4415 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334416
4417 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594418 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494419 ProxyResolutionService::CreateFixedFromPacResult(
4420 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334421
Jeremy Roman0579ed62017-08-29 15:56:194422 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334423 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194424 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334425 mock_handler->set_allows_default_credentials(true);
4426 auth_handler_factory->AddMockHandler(mock_handler.release(),
4427 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484428 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334429
4430 // Add NetLog just so can verify load timing information gets a NetLog ID.
4431 NetLog net_log;
4432 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094433 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334434
4435 // Should try to establish tunnel.
4436 MockWrite data_writes1[] = {
4437 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174438 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334439 "Proxy-Connection: keep-alive\r\n\r\n"),
4440
4441 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174442 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334443 "Proxy-Connection: keep-alive\r\n"
4444 "Proxy-Authorization: auth_token\r\n\r\n"),
4445 };
4446
4447 // The proxy responds to the connect with a 407, using a non-persistent
4448 // connection.
4449 MockRead data_reads1[] = {
4450 // No credentials.
4451 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4452 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4453 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4454 };
4455
4456 // Since the first connection was closed, need to establish another once given
4457 // credentials.
4458 MockWrite data_writes2[] = {
4459 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174460 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334461 "Proxy-Connection: keep-alive\r\n"
4462 "Proxy-Authorization: auth_token\r\n\r\n"),
4463
4464 MockWrite("GET / HTTP/1.1\r\n"
4465 "Host: www.example.org\r\n"
4466 "Connection: keep-alive\r\n\r\n"),
4467 };
4468
4469 MockRead data_reads2[] = {
4470 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4471
4472 MockRead("HTTP/1.1 200 OK\r\n"),
4473 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4474 MockRead("Content-Length: 5\r\n\r\n"),
4475 MockRead(SYNCHRONOUS, "hello"),
4476 };
4477
Ryan Sleevib8d7ea02018-05-07 20:01:014478 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334479 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014480 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334481 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4482 SSLSocketDataProvider ssl(ASYNC, OK);
4483 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4484
bnc87dcefc2017-05-25 12:47:584485 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194486 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334487
4488 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:204489 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014490 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334491
4492 const HttpResponseInfo* response = trans->GetResponseInfo();
4493 ASSERT_TRUE(response);
4494 ASSERT_TRUE(response->headers);
4495 EXPECT_TRUE(response->headers->IsKeepAlive());
4496 EXPECT_EQ(407, response->headers->response_code());
4497 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4498 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584499 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334500
4501 LoadTimingInfo load_timing_info;
4502 // CONNECT requests and responses are handled at the connect job level, so
4503 // the transaction does not yet have a connection.
4504 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4505
4506 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014507 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334508
4509 response = trans->GetResponseInfo();
4510 ASSERT_TRUE(response);
4511 ASSERT_TRUE(response->headers);
4512 EXPECT_TRUE(response->headers->IsKeepAlive());
4513 EXPECT_EQ(200, response->headers->response_code());
4514 EXPECT_EQ(5, response->headers->GetContentLength());
4515 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4516
4517 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584518 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334519
4520 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4521 TestLoadTimingNotReusedWithPac(load_timing_info,
4522 CONNECT_TIMING_HAS_SSL_TIMES);
4523
4524 trans.reset();
4525 session->CloseAllConnections();
4526}
4527
4528// Test a proxy auth scheme that allows default credentials and a proxy server
4529// that hangs up when credentials are initially sent, and hangs up again when
4530// they are retried.
bncd16676a2016-07-20 16:23:014531TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334532 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
4533 HttpRequestInfo request;
4534 request.method = "GET";
4535 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104536 request.traffic_annotation =
4537 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334538
4539 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594540 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494541 ProxyResolutionService::CreateFixedFromPacResult(
4542 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334543
Jeremy Roman0579ed62017-08-29 15:56:194544 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334545 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194546 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334547 mock_handler->set_allows_default_credentials(true);
4548 auth_handler_factory->AddMockHandler(mock_handler.release(),
4549 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484550 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334551
4552 // Add NetLog just so can verify load timing information gets a NetLog ID.
4553 NetLog net_log;
4554 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094555 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334556
4557 // Should try to establish tunnel.
4558 MockWrite data_writes1[] = {
4559 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174560 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334561 "Proxy-Connection: keep-alive\r\n\r\n"),
4562
4563 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174564 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334565 "Proxy-Connection: keep-alive\r\n"
4566 "Proxy-Authorization: auth_token\r\n\r\n"),
4567 };
4568
4569 // The proxy responds to the connect with a 407, and then hangs up after the
4570 // second request is sent.
4571 MockRead data_reads1[] = {
4572 // No credentials.
4573 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4574 MockRead("Content-Length: 0\r\n"),
4575 MockRead("Proxy-Connection: keep-alive\r\n"),
4576 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4577 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4578 };
4579
4580 // HttpNetworkTransaction sees a reused connection that was closed with
4581 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
4582 // request.
4583 MockWrite data_writes2[] = {
4584 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174585 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334586 "Proxy-Connection: keep-alive\r\n\r\n"),
4587 };
4588
4589 // The proxy, having had more than enough of us, just hangs up.
4590 MockRead data_reads2[] = {
4591 // No credentials.
4592 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4593 };
4594
Ryan Sleevib8d7ea02018-05-07 20:01:014595 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334596 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014597 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334598 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4599
bnc87dcefc2017-05-25 12:47:584600 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194601 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334602
4603 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:204604 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014605 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334606
4607 const HttpResponseInfo* response = trans->GetResponseInfo();
4608 ASSERT_TRUE(response);
4609 ASSERT_TRUE(response->headers);
4610 EXPECT_TRUE(response->headers->IsKeepAlive());
4611 EXPECT_EQ(407, response->headers->response_code());
4612 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4613 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584614 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334615
4616 LoadTimingInfo load_timing_info;
4617 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4618
4619 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014620 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:334621
4622 trans.reset();
4623 session->CloseAllConnections();
4624}
4625
Asanka Herathbc3f8f62018-11-16 23:08:304626// This test exercises an odd edge case where the proxy closes the connection
4627// after the authentication handshake is complete. Presumably this technique is
4628// used in lieu of returning a 403 or 5xx status code when the authentication
4629// succeeds, but the user is not authorized to connect to the destination
4630// server. There's no standard for what a proxy should do to indicate a blocked
4631// site.
4632TEST_F(HttpNetworkTransactionTest,
4633 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
4634 HttpRequestInfo request;
4635 request.method = "GET";
4636 request.url = GURL("https://www.example.org/");
4637 request.traffic_annotation =
4638 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4639
4640 // Configure against proxy server "myproxy:70".
4641 session_deps_.proxy_resolution_service =
4642 ProxyResolutionService::CreateFixedFromPacResult(
4643 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4644
Asanka Herathbc3f8f62018-11-16 23:08:304645 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
4646 auth_handler_factory->set_do_init_from_challenge(true);
4647
4648 // Create two mock AuthHandlers. This is because the transaction gets retried
4649 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
4650 // was a real network error.
4651 //
4652 // The handlers support both default and explicit credentials. The retry
4653 // mentioned above should be able to reuse the default identity. Thus there
4654 // should never be a need to prompt for explicit credentials.
4655 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
4656 mock_handler->set_allows_default_credentials(true);
4657 mock_handler->set_allows_explicit_credentials(true);
4658 mock_handler->set_connection_based(true);
4659 auth_handler_factory->AddMockHandler(mock_handler.release(),
4660 HttpAuth::AUTH_PROXY);
4661 mock_handler = std::make_unique<HttpAuthHandlerMock>();
4662 mock_handler->set_allows_default_credentials(true);
4663 mock_handler->set_allows_explicit_credentials(true);
4664 mock_handler->set_connection_based(true);
4665 auth_handler_factory->AddMockHandler(mock_handler.release(),
4666 HttpAuth::AUTH_PROXY);
4667 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4668
4669 NetLog net_log;
4670 session_deps_.net_log = &net_log;
4671 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4672
4673 // Data for both sockets.
4674 //
4675 // Writes are for the tunnel establishment attempts and the
4676 // authentication handshake.
4677 MockWrite data_writes1[] = {
4678 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4679 "Host: www.example.org:443\r\n"
4680 "Proxy-Connection: keep-alive\r\n\r\n"),
4681
4682 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4683 "Host: www.example.org:443\r\n"
4684 "Proxy-Connection: keep-alive\r\n"
4685 "Proxy-Authorization: auth_token\r\n\r\n"),
4686
4687 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4688 "Host: www.example.org:443\r\n"
4689 "Proxy-Connection: keep-alive\r\n"
4690 "Proxy-Authorization: auth_token\r\n\r\n"),
4691 };
4692
4693 // The server side of the authentication handshake. Note that the response to
4694 // the final CONNECT request is ERR_CONNECTION_CLOSED.
4695 MockRead data_reads1[] = {
4696 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4697 MockRead("Content-Length: 0\r\n"),
4698 MockRead("Proxy-Connection: keep-alive\r\n"),
4699 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4700
4701 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4702 MockRead("Content-Length: 0\r\n"),
4703 MockRead("Proxy-Connection: keep-alive\r\n"),
4704 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
4705
4706 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4707 };
4708
4709 StaticSocketDataProvider data1(data_reads1, data_writes1);
4710 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4711
4712 // The second socket is for the reconnection attempt. Data is identical to the
4713 // first attempt.
4714 StaticSocketDataProvider data2(data_reads1, data_writes1);
4715 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4716
4717 auto trans =
4718 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4719
4720 TestCompletionCallback callback;
4721 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4722
4723 // Two rounds per handshake. After one retry, the error is propagated up the
4724 // stack.
4725 for (int i = 0; i < 4; ++i) {
4726 EXPECT_THAT(callback.GetResult(rv), IsOk());
4727
4728 const HttpResponseInfo* response = trans->GetResponseInfo();
4729 ASSERT_TRUE(response);
4730 ASSERT_TRUE(response->headers);
4731 EXPECT_EQ(407, response->headers->response_code());
4732 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
4733
4734 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4735 }
4736
4737 // One shall be the number thou shalt retry, and the number of the retrying
4738 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
4739 // that thou then proceed to one. Three is right out. Once the number one,
4740 // being the first number, be reached, then lobbest thou thy
4741 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
4742 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
4743
4744 trans.reset();
4745 session->CloseAllConnections();
4746}
4747
mmenke2a1781d2015-10-07 19:25:334748// Test a proxy auth scheme that allows default credentials and a proxy server
4749// that hangs up when credentials are initially sent, and sends a challenge
4750// again they are retried.
bncd16676a2016-07-20 16:23:014751TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334752 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
4753 HttpRequestInfo request;
4754 request.method = "GET";
4755 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104756 request.traffic_annotation =
4757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334758
4759 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594760 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494761 ProxyResolutionService::CreateFixedFromPacResult(
4762 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334763
Jeremy Roman0579ed62017-08-29 15:56:194764 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334765 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194766 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334767 mock_handler->set_allows_default_credentials(true);
4768 auth_handler_factory->AddMockHandler(mock_handler.release(),
4769 HttpAuth::AUTH_PROXY);
4770 // Add another handler for the second challenge. It supports default
4771 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194772 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334773 mock_handler->set_allows_default_credentials(true);
4774 auth_handler_factory->AddMockHandler(mock_handler.release(),
4775 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484776 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334777
4778 // Add NetLog just so can verify load timing information gets a NetLog ID.
4779 NetLog net_log;
4780 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094781 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334782
4783 // Should try to establish tunnel.
4784 MockWrite data_writes1[] = {
4785 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174786 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334787 "Proxy-Connection: keep-alive\r\n\r\n"),
4788 };
4789
4790 // The proxy responds to the connect with a 407, using a non-persistent
4791 // connection.
4792 MockRead data_reads1[] = {
4793 // No credentials.
4794 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4795 MockRead("Proxy-Authenticate: Mock\r\n"),
4796 MockRead("Proxy-Connection: close\r\n\r\n"),
4797 };
4798
4799 // Since the first connection was closed, need to establish another once given
4800 // credentials.
4801 MockWrite data_writes2[] = {
4802 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174803 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334804 "Proxy-Connection: keep-alive\r\n"
4805 "Proxy-Authorization: auth_token\r\n\r\n"),
4806 };
4807
4808 MockRead data_reads2[] = {
4809 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4810 MockRead("Proxy-Authenticate: Mock\r\n"),
4811 MockRead("Proxy-Connection: close\r\n\r\n"),
4812 };
4813
Ryan Sleevib8d7ea02018-05-07 20:01:014814 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334815 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014816 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334817 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4818 SSLSocketDataProvider ssl(ASYNC, OK);
4819 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4820
bnc87dcefc2017-05-25 12:47:584821 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194822 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334823
4824 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:204825 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014826 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334827
4828 const HttpResponseInfo* response = trans->GetResponseInfo();
4829 ASSERT_TRUE(response);
4830 ASSERT_TRUE(response->headers);
4831 EXPECT_EQ(407, response->headers->response_code());
4832 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4833 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584834 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334835
4836 LoadTimingInfo load_timing_info;
4837 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4838
4839 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014840 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334841 response = trans->GetResponseInfo();
4842 ASSERT_TRUE(response);
4843 ASSERT_TRUE(response->headers);
4844 EXPECT_EQ(407, response->headers->response_code());
4845 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584846 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334847
4848 trans.reset();
4849 session->CloseAllConnections();
4850}
4851
asankae2257db2016-10-11 22:03:164852// A more nuanced test than GenerateAuthToken test which asserts that
4853// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
4854// unnecessarily invalidated, and that if the server co-operates, the
4855// authentication handshake can continue with the same scheme but with a
4856// different identity.
4857TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
4858 HttpRequestInfo request;
4859 request.method = "GET";
4860 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104861 request.traffic_annotation =
4862 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:164863
Jeremy Roman0579ed62017-08-29 15:56:194864 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:164865 auth_handler_factory->set_do_init_from_challenge(true);
4866
4867 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:194868 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164869 mock_handler->set_allows_default_credentials(true);
4870 mock_handler->set_allows_explicit_credentials(true);
4871 mock_handler->set_connection_based(true);
4872 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
4873 auth_handler_factory->AddMockHandler(mock_handler.release(),
4874 HttpAuth::AUTH_SERVER);
4875
4876 // Add another handler for the second challenge. It supports default
4877 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194878 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164879 mock_handler->set_allows_default_credentials(true);
4880 mock_handler->set_allows_explicit_credentials(true);
4881 mock_handler->set_connection_based(true);
4882 auth_handler_factory->AddMockHandler(mock_handler.release(),
4883 HttpAuth::AUTH_SERVER);
4884 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4885
4886 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4887
4888 MockWrite data_writes1[] = {
4889 MockWrite("GET / HTTP/1.1\r\n"
4890 "Host: www.example.org\r\n"
4891 "Connection: keep-alive\r\n\r\n"),
4892 };
4893
4894 MockRead data_reads1[] = {
4895 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4896 "WWW-Authenticate: Mock\r\n"
4897 "Connection: keep-alive\r\n\r\n"),
4898 };
4899
4900 // Identical to data_writes1[]. The AuthHandler encounters a
4901 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
4902 // transaction procceds without an authorization header.
4903 MockWrite data_writes2[] = {
4904 MockWrite("GET / HTTP/1.1\r\n"
4905 "Host: www.example.org\r\n"
4906 "Connection: keep-alive\r\n\r\n"),
4907 };
4908
4909 MockRead data_reads2[] = {
4910 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4911 "WWW-Authenticate: Mock\r\n"
4912 "Connection: keep-alive\r\n\r\n"),
4913 };
4914
4915 MockWrite data_writes3[] = {
4916 MockWrite("GET / HTTP/1.1\r\n"
4917 "Host: www.example.org\r\n"
4918 "Connection: keep-alive\r\n"
4919 "Authorization: auth_token\r\n\r\n"),
4920 };
4921
4922 MockRead data_reads3[] = {
4923 MockRead("HTTP/1.1 200 OK\r\n"
4924 "Content-Length: 5\r\n"
4925 "Content-Type: text/plain\r\n"
4926 "Connection: keep-alive\r\n\r\n"
4927 "Hello"),
4928 };
4929
Ryan Sleevib8d7ea02018-05-07 20:01:014930 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:164931 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4932
Ryan Sleevib8d7ea02018-05-07 20:01:014933 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:164934 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4935
Ryan Sleevib8d7ea02018-05-07 20:01:014936 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:164937 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4938
bnc87dcefc2017-05-25 12:47:584939 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194940 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:164941
4942 TestCompletionCallback callback;
4943 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4944 EXPECT_THAT(callback.GetResult(rv), IsOk());
4945
4946 const HttpResponseInfo* response = trans->GetResponseInfo();
4947 ASSERT_TRUE(response);
4948 ASSERT_TRUE(response->headers);
4949 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4950
4951 // The following three tests assert that an authentication challenge was
4952 // received and that the stack is ready to respond to the challenge using
4953 // ambient credentials.
4954 EXPECT_EQ(401, response->headers->response_code());
4955 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584956 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164957
4958 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4959 EXPECT_THAT(callback.GetResult(rv), IsOk());
4960 response = trans->GetResponseInfo();
4961 ASSERT_TRUE(response);
4962 ASSERT_TRUE(response->headers);
4963
4964 // The following three tests assert that an authentication challenge was
4965 // received and that the stack needs explicit credentials before it is ready
4966 // to respond to the challenge.
4967 EXPECT_EQ(401, response->headers->response_code());
4968 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584969 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164970
4971 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4972 EXPECT_THAT(callback.GetResult(rv), IsOk());
4973 response = trans->GetResponseInfo();
4974 ASSERT_TRUE(response);
4975 ASSERT_TRUE(response->headers);
4976 EXPECT_EQ(200, response->headers->response_code());
4977
4978 trans.reset();
4979 session->CloseAllConnections();
4980}
4981
Matt Menked1eb6d42018-01-17 04:54:064982// Proxy resolver that returns a proxy with the same host and port for different
4983// schemes, based on the path of the URL being requests.
4984class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
4985 public:
4986 SameProxyWithDifferentSchemesProxyResolver() {}
4987 ~SameProxyWithDifferentSchemesProxyResolver() override {}
4988
4989 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
4990
4991 static HostPortPair ProxyHostPortPair() {
4992 return HostPortPair::FromString(ProxyHostPortPairAsString());
4993 }
4994
4995 // ProxyResolver implementation.
4996 int GetProxyForURL(const GURL& url,
4997 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:174998 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:064999 std::unique_ptr<Request>* request,
5000 const NetLogWithSource& /*net_log*/) override {
5001 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:575002 results->set_traffic_annotation(
5003 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:065004 if (url.path() == "/socks4") {
5005 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
5006 return OK;
5007 }
5008 if (url.path() == "/socks5") {
5009 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
5010 return OK;
5011 }
5012 if (url.path() == "/http") {
5013 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
5014 return OK;
5015 }
5016 if (url.path() == "/https") {
5017 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
5018 return OK;
5019 }
Matt Menkee8648fa2019-01-17 16:47:075020 if (url.path() == "/https_trusted") {
5021 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
5022 ProxyHostPortPair(),
5023 true /* is_trusted_proxy */));
5024 return OK;
5025 }
Matt Menked1eb6d42018-01-17 04:54:065026 NOTREACHED();
5027 return ERR_NOT_IMPLEMENTED;
5028 }
5029
5030 private:
5031 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
5032};
5033
5034class SameProxyWithDifferentSchemesProxyResolverFactory
5035 : public ProxyResolverFactory {
5036 public:
5037 SameProxyWithDifferentSchemesProxyResolverFactory()
5038 : ProxyResolverFactory(false) {}
5039
Lily Houghton99597862018-03-07 16:40:425040 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
5041 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:175042 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:425043 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:065044 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
5045 return OK;
5046 }
5047
5048 private:
5049 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
5050};
5051
5052// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:075053// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:065054// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
5055// request to foo.com using proxy.com as an HTTP proxy.
5056TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:495057 session_deps_.proxy_resolution_service =
5058 std::make_unique<ProxyResolutionService>(
5059 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5060 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
5061 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
5062 nullptr);
Matt Menked1eb6d42018-01-17 04:54:065063
5064 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5065
5066 MockWrite socks_writes[] = {
5067 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
5068 kSOCKS4OkRequestLocalHostPort80Length),
5069 MockWrite(SYNCHRONOUS,
5070 "GET /socks4 HTTP/1.1\r\n"
5071 "Host: test\r\n"
5072 "Connection: keep-alive\r\n\r\n"),
5073 };
5074 MockRead socks_reads[] = {
5075 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
5076 MockRead("HTTP/1.0 200 OK\r\n"
5077 "Connection: keep-alive\r\n"
5078 "Content-Length: 15\r\n\r\n"
5079 "SOCKS4 Response"),
5080 };
Ryan Sleevib8d7ea02018-05-07 20:01:015081 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065082 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5083
5084 const char kSOCKS5Request[] = {
5085 0x05, // Version
5086 0x01, // Command (CONNECT)
5087 0x00, // Reserved
5088 0x03, // Address type (DOMAINNAME)
5089 0x04, // Length of domain (4)
5090 't', 'e', 's', 't', // Domain string
5091 0x00, 0x50, // 16-bit port (80)
5092 };
5093 MockWrite socks5_writes[] = {
5094 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245095 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065096 MockWrite(SYNCHRONOUS,
5097 "GET /socks5 HTTP/1.1\r\n"
5098 "Host: test\r\n"
5099 "Connection: keep-alive\r\n\r\n"),
5100 };
5101 MockRead socks5_reads[] = {
5102 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5103 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5104 MockRead("HTTP/1.0 200 OK\r\n"
5105 "Connection: keep-alive\r\n"
5106 "Content-Length: 15\r\n\r\n"
5107 "SOCKS5 Response"),
5108 };
Ryan Sleevib8d7ea02018-05-07 20:01:015109 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065110 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5111
5112 MockWrite http_writes[] = {
5113 MockWrite(SYNCHRONOUS,
5114 "GET http://test/http HTTP/1.1\r\n"
5115 "Host: test\r\n"
5116 "Proxy-Connection: keep-alive\r\n\r\n"),
5117 };
5118 MockRead http_reads[] = {
5119 MockRead("HTTP/1.1 200 OK\r\n"
5120 "Proxy-Connection: keep-alive\r\n"
5121 "Content-Length: 13\r\n\r\n"
5122 "HTTP Response"),
5123 };
Ryan Sleevib8d7ea02018-05-07 20:01:015124 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065125 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5126
5127 MockWrite https_writes[] = {
5128 MockWrite(SYNCHRONOUS,
5129 "GET http://test/https HTTP/1.1\r\n"
5130 "Host: test\r\n"
5131 "Proxy-Connection: keep-alive\r\n\r\n"),
5132 };
5133 MockRead https_reads[] = {
5134 MockRead("HTTP/1.1 200 OK\r\n"
5135 "Proxy-Connection: keep-alive\r\n"
5136 "Content-Length: 14\r\n\r\n"
5137 "HTTPS Response"),
5138 };
Ryan Sleevib8d7ea02018-05-07 20:01:015139 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065140 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5141 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5142 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5143
Matt Menkee8648fa2019-01-17 16:47:075144 MockWrite https_trusted_writes[] = {
5145 MockWrite(SYNCHRONOUS,
5146 "GET http://test/https_trusted HTTP/1.1\r\n"
5147 "Host: test\r\n"
5148 "Proxy-Connection: keep-alive\r\n\r\n"),
5149 };
5150 MockRead https_trusted_reads[] = {
5151 MockRead("HTTP/1.1 200 OK\r\n"
5152 "Proxy-Connection: keep-alive\r\n"
5153 "Content-Length: 22\r\n\r\n"
5154 "HTTPS Trusted Response"),
5155 };
5156 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5157 https_trusted_writes);
5158 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5159 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5160 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5161
Matt Menked1eb6d42018-01-17 04:54:065162 struct TestCase {
5163 GURL url;
5164 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075165 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065166 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075167 int expected_idle_socks4_sockets;
5168 int expected_idle_socks5_sockets;
5169 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5170 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065171 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075172 int expected_idle_https_sockets;
5173 // How many idle sockets there should be in the HTTPS proxy socket pool with
5174 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5175 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065176 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075177 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5178 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5179 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5180 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5181 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5182 1},
Matt Menked1eb6d42018-01-17 04:54:065183 };
5184
5185 for (const auto& test_case : kTestCases) {
5186 HttpRequestInfo request;
5187 request.method = "GET";
5188 request.url = test_case.url;
Ramin Halavatib5e433e62018-02-07 07:41:105189 request.traffic_annotation =
5190 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065191 std::unique_ptr<HttpNetworkTransaction> trans =
5192 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5193 session.get());
5194 TestCompletionCallback callback;
5195 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5196 EXPECT_THAT(callback.GetResult(rv), IsOk());
5197
5198 const HttpResponseInfo* response = trans->GetResponseInfo();
5199 ASSERT_TRUE(response);
5200 ASSERT_TRUE(response->headers);
5201 EXPECT_EQ(200, response->headers->response_code());
5202 std::string response_data;
5203 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5204 EXPECT_EQ(test_case.expected_response, response_data);
5205
5206 // Return the socket to the socket pool, so can make sure it's not used for
5207 // the next requests.
5208 trans.reset();
5209 base::RunLoop().RunUntilIdle();
5210
5211 // Check the number of idle sockets in the pool, to make sure that used
5212 // sockets are indeed being returned to the socket pool. If each request
5213 // doesn't return an idle socket to the pool, the test would incorrectly
5214 // pass.
Matt Menkee8648fa2019-01-17 16:47:075215 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5216 session
Matt Menked23ab952019-03-06 00:24:405217 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075218 HttpNetworkSession::NORMAL_SOCKET_POOL,
5219 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5220 SameProxyWithDifferentSchemesProxyResolver::
5221 ProxyHostPortPair()))
5222 ->IdleSocketCount());
5223 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5224 session
Matt Menked23ab952019-03-06 00:24:405225 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075226 HttpNetworkSession::NORMAL_SOCKET_POOL,
5227 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5228 SameProxyWithDifferentSchemesProxyResolver::
5229 ProxyHostPortPair()))
5230 ->IdleSocketCount());
5231 EXPECT_EQ(test_case.expected_idle_http_sockets,
5232 session
Matt Menked23ab952019-03-06 00:24:405233 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075234 HttpNetworkSession::NORMAL_SOCKET_POOL,
5235 ProxyServer(ProxyServer::SCHEME_HTTP,
5236 SameProxyWithDifferentSchemesProxyResolver::
5237 ProxyHostPortPair()))
5238 ->IdleSocketCount());
5239 EXPECT_EQ(test_case.expected_idle_https_sockets,
5240 session
Matt Menked23ab952019-03-06 00:24:405241 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075242 HttpNetworkSession::NORMAL_SOCKET_POOL,
5243 ProxyServer(ProxyServer::SCHEME_HTTPS,
5244 SameProxyWithDifferentSchemesProxyResolver::
5245 ProxyHostPortPair()))
5246 ->IdleSocketCount());
5247 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5248 session
Matt Menked23ab952019-03-06 00:24:405249 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075250 HttpNetworkSession::NORMAL_SOCKET_POOL,
5251 ProxyServer(ProxyServer::SCHEME_HTTPS,
5252 SameProxyWithDifferentSchemesProxyResolver::
5253 ProxyHostPortPair(),
5254 true /* is_trusted_proxy */))
5255 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065256 }
5257}
5258
[email protected]029c83b62013-01-24 05:28:205259// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015260TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205261 HttpRequestInfo request1;
5262 request1.method = "GET";
bncce36dca22015-04-21 22:11:235263 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105264 request1.traffic_annotation =
5265 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205266
5267 HttpRequestInfo request2;
5268 request2.method = "GET";
bncce36dca22015-04-21 22:11:235269 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105270 request2.traffic_annotation =
5271 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205272
5273 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495274 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5275 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515276 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075277 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095278 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205279
5280 // Since we have proxy, should try to establish tunnel.
5281 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175282 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5283 "Host: www.example.org:443\r\n"
5284 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205285
rsleevidb16bb02015-11-12 23:47:175286 MockWrite("GET /1 HTTP/1.1\r\n"
5287 "Host: www.example.org\r\n"
5288 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205289
rsleevidb16bb02015-11-12 23:47:175290 MockWrite("GET /2 HTTP/1.1\r\n"
5291 "Host: www.example.org\r\n"
5292 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205293 };
5294
5295 // The proxy responds to the connect with a 407, using a persistent
5296 // connection.
5297 MockRead data_reads1[] = {
5298 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5299
5300 MockRead("HTTP/1.1 200 OK\r\n"),
5301 MockRead("Content-Length: 1\r\n\r\n"),
5302 MockRead(SYNCHRONOUS, "1"),
5303
5304 MockRead("HTTP/1.1 200 OK\r\n"),
5305 MockRead("Content-Length: 2\r\n\r\n"),
5306 MockRead(SYNCHRONOUS, "22"),
5307 };
5308
Ryan Sleevib8d7ea02018-05-07 20:01:015309 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075310 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205311 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075312 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205313
5314 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585315 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195316 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205317
5318 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015319 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205320
5321 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015322 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205323
5324 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525325 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475326 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525327 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205328 EXPECT_EQ(1, response1->headers->GetContentLength());
5329
5330 LoadTimingInfo load_timing_info1;
5331 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5332 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5333
5334 trans1.reset();
5335
5336 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585337 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195338 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205339
5340 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015341 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205342
5343 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015344 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205345
5346 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525347 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475348 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525349 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205350 EXPECT_EQ(2, response2->headers->GetContentLength());
5351
5352 LoadTimingInfo load_timing_info2;
5353 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5354 TestLoadTimingReused(load_timing_info2);
5355
5356 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5357
5358 trans2.reset();
5359 session->CloseAllConnections();
5360}
5361
5362// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015363TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205364 HttpRequestInfo request1;
5365 request1.method = "GET";
bncce36dca22015-04-21 22:11:235366 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105367 request1.traffic_annotation =
5368 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205369
5370 HttpRequestInfo request2;
5371 request2.method = "GET";
bncce36dca22015-04-21 22:11:235372 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105373 request2.traffic_annotation =
5374 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205375
5376 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595377 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495378 ProxyResolutionService::CreateFixedFromPacResult(
5379 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515380 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075381 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095382 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205383
5384 // Since we have proxy, should try to establish tunnel.
5385 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175386 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5387 "Host: www.example.org:443\r\n"
5388 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205389
rsleevidb16bb02015-11-12 23:47:175390 MockWrite("GET /1 HTTP/1.1\r\n"
5391 "Host: www.example.org\r\n"
5392 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205393
rsleevidb16bb02015-11-12 23:47:175394 MockWrite("GET /2 HTTP/1.1\r\n"
5395 "Host: www.example.org\r\n"
5396 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205397 };
5398
5399 // The proxy responds to the connect with a 407, using a persistent
5400 // connection.
5401 MockRead data_reads1[] = {
5402 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5403
5404 MockRead("HTTP/1.1 200 OK\r\n"),
5405 MockRead("Content-Length: 1\r\n\r\n"),
5406 MockRead(SYNCHRONOUS, "1"),
5407
5408 MockRead("HTTP/1.1 200 OK\r\n"),
5409 MockRead("Content-Length: 2\r\n\r\n"),
5410 MockRead(SYNCHRONOUS, "22"),
5411 };
5412
Ryan Sleevib8d7ea02018-05-07 20:01:015413 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075414 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205415 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075416 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205417
5418 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585419 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195420 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205421
5422 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015423 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205424
5425 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015426 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205427
5428 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525429 ASSERT_TRUE(response1);
5430 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205431 EXPECT_EQ(1, response1->headers->GetContentLength());
5432
5433 LoadTimingInfo load_timing_info1;
5434 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5435 TestLoadTimingNotReusedWithPac(load_timing_info1,
5436 CONNECT_TIMING_HAS_SSL_TIMES);
5437
5438 trans1.reset();
5439
5440 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585441 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195442 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205443
5444 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015445 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205446
5447 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015448 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205449
5450 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525451 ASSERT_TRUE(response2);
5452 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205453 EXPECT_EQ(2, response2->headers->GetContentLength());
5454
5455 LoadTimingInfo load_timing_info2;
5456 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5457 TestLoadTimingReusedWithPac(load_timing_info2);
5458
5459 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5460
5461 trans2.reset();
5462 session->CloseAllConnections();
5463}
5464
[email protected]2df19bb2010-08-25 20:13:465465// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015466TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275467 HttpRequestInfo request;
5468 request.method = "GET";
bncce36dca22015-04-21 22:11:235469 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105470 request.traffic_annotation =
5471 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275472
[email protected]2df19bb2010-08-25 20:13:465473 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495474 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5475 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515476 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075477 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095478 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:465479
[email protected]2df19bb2010-08-25 20:13:465480 // Since we have proxy, should use full url
5481 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235482 MockWrite(
5483 "GET http://www.example.org/ HTTP/1.1\r\n"
5484 "Host: www.example.org\r\n"
5485 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465486 };
5487
5488 MockRead data_reads1[] = {
5489 MockRead("HTTP/1.1 200 OK\r\n"),
5490 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5491 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065492 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465493 };
5494
Ryan Sleevib8d7ea02018-05-07 20:01:015495 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075496 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065497 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075498 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465499
[email protected]49639fa2011-12-20 23:22:415500 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465501
bnc691fda62016-08-12 00:43:165502 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505503
bnc691fda62016-08-12 00:43:165504 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015505 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465506
5507 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015508 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465509
[email protected]58e32bb2013-01-21 18:23:255510 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165511 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255512 TestLoadTimingNotReused(load_timing_info,
5513 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5514
bnc691fda62016-08-12 00:43:165515 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525516 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:465517
tbansal2ecbbc72016-10-06 17:15:475518 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:465519 EXPECT_TRUE(response->headers->IsKeepAlive());
5520 EXPECT_EQ(200, response->headers->response_code());
5521 EXPECT_EQ(100, response->headers->GetContentLength());
5522 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5523
5524 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585525 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:465526}
5527
[email protected]7642b5ae2010-09-01 20:55:175528// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015529TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275530 HttpRequestInfo request;
5531 request.method = "GET";
bncce36dca22015-04-21 22:11:235532 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105533 request.traffic_annotation =
5534 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275535
[email protected]7642b5ae2010-09-01 20:55:175536 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495537 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5538 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515539 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075540 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095541 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:175542
bncce36dca22015-04-21 22:11:235543 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135544 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455545 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415546 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:175547
Ryan Hamilton0239aac2018-05-19 00:03:135548 spdy::SpdySerializedFrame resp(
5549 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5550 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:175551 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415552 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:175553 };
5554
Ryan Sleevib8d7ea02018-05-07 20:01:015555 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075556 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:175557
[email protected]8ddf8322012-02-23 18:08:065558 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365559 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075560 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:175561
[email protected]49639fa2011-12-20 23:22:415562 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:175563
bnc691fda62016-08-12 00:43:165564 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505565
bnc691fda62016-08-12 00:43:165566 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015567 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:175568
5569 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015570 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:175571
[email protected]58e32bb2013-01-21 18:23:255572 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165573 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255574 TestLoadTimingNotReused(load_timing_info,
5575 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5576
bnc691fda62016-08-12 00:43:165577 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525578 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:475579 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:525580 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025581 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:175582
5583 std::string response_data;
bnc691fda62016-08-12 00:43:165584 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235585 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:175586}
5587
[email protected]1c173852014-06-19 12:51:505588// Verifies that a session which races and wins against the owning transaction
5589// (completing prior to host resolution), doesn't fail the transaction.
5590// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:015591TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:505592 HttpRequestInfo request;
5593 request.method = "GET";
bncce36dca22015-04-21 22:11:235594 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105595 request.traffic_annotation =
5596 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:505597
5598 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495599 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5600 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515601 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:505602 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095603 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:505604
bncce36dca22015-04-21 22:11:235605 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:135606 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455607 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415608 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:505609
Raul Tambre94493c652019-03-11 17:18:355610 spdy::SpdySerializedFrame resp(
5611 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135612 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:505613 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415614 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:505615 };
5616
Ryan Sleevib8d7ea02018-05-07 20:01:015617 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:505618 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5619
5620 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365621 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:505622 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5623
5624 TestCompletionCallback callback1;
5625
bnc691fda62016-08-12 00:43:165626 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:505627
5628 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:505629 session_deps_.host_resolver->set_ondemand_mode(true);
5630
bnc691fda62016-08-12 00:43:165631 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015632 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:505633
5634 // Race a session to the proxy, which completes first.
5635 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:045636 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:115637 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:345638 SpdySessionKey::IsProxySession::kTrue, SocketTag(),
5639 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]1c173852014-06-19 12:51:505640 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:525641 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:505642
5643 // Unstall the resolution begun by the transaction.
5644 session_deps_.host_resolver->set_ondemand_mode(true);
5645 session_deps_.host_resolver->ResolveAllPending();
5646
5647 EXPECT_FALSE(callback1.have_result());
5648 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015649 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:505650
bnc691fda62016-08-12 00:43:165651 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525652 ASSERT_TRUE(response);
5653 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025654 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:505655
5656 std::string response_data;
bnc691fda62016-08-12 00:43:165657 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:505658 EXPECT_EQ(kUploadData, response_data);
5659}
5660
[email protected]dc7bd1c52010-11-12 00:01:135661// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015662TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:275663 HttpRequestInfo request;
5664 request.method = "GET";
bncce36dca22015-04-21 22:11:235665 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105666 request.traffic_annotation =
5667 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275668
[email protected]79cb5c12011-09-12 13:12:045669 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495670 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5671 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515672 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075673 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095674 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:135675
[email protected]dc7bd1c52010-11-12 00:01:135676 // The first request will be a bare GET, the second request will be a
5677 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:455678 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:135679 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:485680 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385681 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:135682 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465683 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:135684 };
Ryan Hamilton0239aac2018-05-19 00:03:135685 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:245686 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:485687 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:135688 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415689 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:135690 };
5691
5692 // The first response is a 407 proxy authentication challenge, and the second
5693 // response will be a 200 response since the second request includes a valid
5694 // Authorization header.
5695 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465696 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:135697 };
Ryan Hamilton0239aac2018-05-19 00:03:135698 spdy::SpdySerializedFrame resp_authentication(
5699 spdy_util_.ConstructSpdyReplyError(
5700 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:245701 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135702 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:415703 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135704 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:355705 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:135706 spdy::SpdySerializedFrame body_data(
5707 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:135708 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415709 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:465710 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415711 CreateMockRead(resp_data, 4),
5712 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:135713 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:135714 };
5715
Ryan Sleevib8d7ea02018-05-07 20:01:015716 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075717 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:135718
[email protected]8ddf8322012-02-23 18:08:065719 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365720 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075721 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:135722
[email protected]49639fa2011-12-20 23:22:415723 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:135724
bnc691fda62016-08-12 00:43:165725 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:135726
bnc691fda62016-08-12 00:43:165727 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015728 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135729
5730 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015731 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135732
bnc691fda62016-08-12 00:43:165733 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135734
wezca1070932016-05-26 20:30:525735 ASSERT_TRUE(response);
5736 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:135737 EXPECT_EQ(407, response->headers->response_code());
5738 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:585739 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:135740
[email protected]49639fa2011-12-20 23:22:415741 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:135742
bnc691fda62016-08-12 00:43:165743 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015744 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135745
5746 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015747 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135748
bnc691fda62016-08-12 00:43:165749 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135750
wezca1070932016-05-26 20:30:525751 ASSERT_TRUE(response_restart);
5752 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:135753 EXPECT_EQ(200, response_restart->headers->response_code());
5754 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585755 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:135756}
5757
[email protected]d9da5fe2010-10-13 22:37:165758// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:015759TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:275760 HttpRequestInfo request;
5761 request.method = "GET";
bncce36dca22015-04-21 22:11:235762 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105763 request.traffic_annotation =
5764 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275765
[email protected]d9da5fe2010-10-13 22:37:165766 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495767 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5768 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515769 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075770 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095771 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165772
bnc691fda62016-08-12 00:43:165773 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165774
bncce36dca22015-04-21 22:11:235775 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135776 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045777 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5778 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235779 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:165780
bncce36dca22015-04-21 22:11:235781 const char get[] =
5782 "GET / HTTP/1.1\r\n"
5783 "Host: www.example.org\r\n"
5784 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135785 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:195786 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:135787 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355788 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:165789 const char resp[] = "HTTP/1.1 200 OK\r\n"
5790 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135791 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:195792 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:135793 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:195794 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:135795 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:415796 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:045797
5798 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415799 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5800 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:045801 };
5802
[email protected]d9da5fe2010-10-13 22:37:165803 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415804 CreateMockRead(conn_resp, 1, ASYNC),
5805 CreateMockRead(wrapped_get_resp, 3, ASYNC),
5806 CreateMockRead(wrapped_body, 4, ASYNC),
5807 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135808 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:165809 };
5810
Ryan Sleevib8d7ea02018-05-07 20:01:015811 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075812 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165813
[email protected]8ddf8322012-02-23 18:08:065814 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365815 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075816 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065817 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075818 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165819
[email protected]49639fa2011-12-20 23:22:415820 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165821
bnc691fda62016-08-12 00:43:165822 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015823 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165824
5825 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015826 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165827
[email protected]58e32bb2013-01-21 18:23:255828 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165829 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255830 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5831
bnc691fda62016-08-12 00:43:165832 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525833 ASSERT_TRUE(response);
5834 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:165835 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5836
5837 std::string response_data;
bnc691fda62016-08-12 00:43:165838 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:165839 EXPECT_EQ("1234567890", response_data);
5840}
5841
5842// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:015843TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
5844 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:385845
[email protected]cb9bf6ca2011-01-28 13:15:275846 HttpRequestInfo request;
5847 request.method = "GET";
bncce36dca22015-04-21 22:11:235848 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105849 request.traffic_annotation =
5850 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275851
[email protected]d9da5fe2010-10-13 22:37:165852 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495853 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5854 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515855 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075856 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095857 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165858
bnc691fda62016-08-12 00:43:165859 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165860
bncce36dca22015-04-21 22:11:235861 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135862 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045863 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5864 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235865 // fetch https://www.example.org/ via SPDY
5866 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:135867 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:495868 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135869 spdy::SpdySerializedFrame wrapped_get(
5870 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
5871 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355872 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135873 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355874 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135875 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:025876 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135877 spdy::SpdySerializedFrame body(
5878 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
5879 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:025880 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135881 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:415882 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:135883 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:415884 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:045885
5886 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415887 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5888 CreateMockWrite(window_update_get_resp, 6),
5889 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:045890 };
5891
[email protected]d9da5fe2010-10-13 22:37:165892 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415893 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:095894 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:415895 CreateMockRead(wrapped_get_resp, 4, ASYNC),
5896 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135897 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:165898 };
5899
Ryan Sleevib8d7ea02018-05-07 20:01:015900 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075901 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165902
[email protected]8ddf8322012-02-23 18:08:065903 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365904 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075905 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065906 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365907 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075908 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165909
[email protected]49639fa2011-12-20 23:22:415910 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165911
bnc691fda62016-08-12 00:43:165912 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015913 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165914
rch32320842015-05-16 15:57:095915 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:555916 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:095917 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:595918 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:165919 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015920 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165921
[email protected]58e32bb2013-01-21 18:23:255922 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165923 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255924 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5925
bnc691fda62016-08-12 00:43:165926 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525927 ASSERT_TRUE(response);
5928 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025929 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:165930
5931 std::string response_data;
bnc691fda62016-08-12 00:43:165932 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235933 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:165934}
5935
5936// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015937TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:275938 HttpRequestInfo request;
5939 request.method = "GET";
bncce36dca22015-04-21 22:11:235940 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105941 request.traffic_annotation =
5942 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275943
[email protected]d9da5fe2010-10-13 22:37:165944 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495945 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5946 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515947 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075948 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095949 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165950
bnc691fda62016-08-12 00:43:165951 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165952
bncce36dca22015-04-21 22:11:235953 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135954 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045955 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5956 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:135957 spdy::SpdySerializedFrame get(
5958 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:165959
5960 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415961 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:165962 };
5963
Ryan Hamilton0239aac2018-05-19 00:03:135964 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
5965 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:165966 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415967 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:165968 };
5969
Ryan Sleevib8d7ea02018-05-07 20:01:015970 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075971 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165972
[email protected]8ddf8322012-02-23 18:08:065973 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365974 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075975 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065976 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365977 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075978 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165979
[email protected]49639fa2011-12-20 23:22:415980 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165981
bnc691fda62016-08-12 00:43:165982 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015983 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165984
5985 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015986 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:165987
ttuttle960fcbf2016-04-19 13:26:325988 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:165989}
5990
Matt Menkecb2cd0982018-12-19 17:54:045991// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:245992// is observed, but does exist by the time auth credentials are provided. In
5993// this case, auth and SSL are fully negotated on the second request, but then
5994// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:045995TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
5996 ProxyConfig proxy_config;
5997 proxy_config.set_auto_detect(true);
5998 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
5999
6000 CapturingProxyResolver capturing_proxy_resolver;
6001 capturing_proxy_resolver.set_proxy_server(
6002 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
6003 session_deps_.proxy_resolution_service =
6004 std::make_unique<ProxyResolutionService>(
6005 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6006 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6007 std::make_unique<CapturingProxyResolverFactory>(
6008 &capturing_proxy_resolver),
6009 nullptr);
6010
6011 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6012
6013 const char kMyUrl[] = "https://www.example.org/";
6014 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6015 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356016 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:046017 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6018
6019 spdy_util_.UpdateWithStreamDestruction(1);
6020 spdy::SpdySerializedFrame get2(
6021 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
6022 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356023 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:046024 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
6025
6026 MockWrite auth_challenge_writes[] = {
6027 MockWrite(ASYNC, 0,
6028 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6029 "Host: www.example.org:443\r\n"
6030 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:246031 MockWrite(ASYNC, 2,
6032 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6033 "Host: www.example.org:443\r\n"
6034 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:046035 };
6036
6037 MockRead auth_challenge_reads[] = {
6038 MockRead(ASYNC, 1,
6039 "HTTP/1.1 407 Authentication Required\r\n"
6040 "Content-Length: 0\r\n"
6041 "Proxy-Connection: close\r\n"
6042 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
6043 };
6044
6045 MockWrite spdy_writes[] = {
6046 MockWrite(ASYNC, 0,
6047 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6048 "Host: www.example.org:443\r\n"
6049 "Proxy-Connection: keep-alive\r\n"
6050 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6051 CreateMockWrite(get, 2),
6052 CreateMockWrite(get2, 5),
6053 };
6054
6055 MockRead spdy_reads[] = {
6056 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6057 CreateMockRead(get_resp, 3, ASYNC),
6058 CreateMockRead(body, 4, ASYNC),
6059 CreateMockRead(get_resp2, 6, ASYNC),
6060 CreateMockRead(body2, 7, ASYNC),
6061
6062 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
6063 };
6064
Matt Menke5062be22019-05-01 17:50:246065 MockWrite auth_response_writes_discarded_socket[] = {
6066 MockWrite(ASYNC, 0,
6067 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6068 "Host: www.example.org:443\r\n"
6069 "Proxy-Connection: keep-alive\r\n"
6070 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6071 };
6072
6073 MockRead auth_response_reads_discarded_socket[] = {
6074 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6075 };
6076
Matt Menkecb2cd0982018-12-19 17:54:046077 SequencedSocketData auth_challenge1(auth_challenge_reads,
6078 auth_challenge_writes);
6079 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
6080
6081 SequencedSocketData auth_challenge2(auth_challenge_reads,
6082 auth_challenge_writes);
6083 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
6084
6085 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6086 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6087
Matt Menke5062be22019-05-01 17:50:246088 SequencedSocketData auth_response_discarded_socket(
6089 auth_response_reads_discarded_socket,
6090 auth_response_writes_discarded_socket);
6091 session_deps_.socket_factory->AddSocketDataProvider(
6092 &auth_response_discarded_socket);
6093
Matt Menkecb2cd0982018-12-19 17:54:046094 SSLSocketDataProvider ssl(ASYNC, OK);
6095 ssl.next_proto = kProtoHTTP2;
6096 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6097
Matt Menke5062be22019-05-01 17:50:246098 SSLSocketDataProvider ssl2(ASYNC, OK);
6099 ssl2.next_proto = kProtoHTTP2;
6100 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6101
Matt Menkecb2cd0982018-12-19 17:54:046102 TestCompletionCallback callback;
6103 std::string response_data;
6104
6105 // Run first request until an auth challenge is observed.
6106 HttpRequestInfo request1;
6107 request1.method = "GET";
6108 request1.url = GURL(kMyUrl);
6109 request1.traffic_annotation =
6110 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6111 HttpNetworkTransaction trans1(LOWEST, session.get());
6112 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6113 EXPECT_THAT(callback.GetResult(rv), IsOk());
6114 const HttpResponseInfo* response = trans1.GetResponseInfo();
6115 ASSERT_TRUE(response);
6116 ASSERT_TRUE(response->headers);
6117 EXPECT_EQ(407, response->headers->response_code());
6118 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586119 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046120
6121 // Run second request until an auth challenge is observed.
6122 HttpRequestInfo request2;
6123 request2.method = "GET";
6124 request2.url = GURL(kMyUrl);
6125 request2.traffic_annotation =
6126 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6127 HttpNetworkTransaction trans2(LOWEST, session.get());
6128 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6129 EXPECT_THAT(callback.GetResult(rv), IsOk());
6130 response = trans2.GetResponseInfo();
6131 ASSERT_TRUE(response);
6132 ASSERT_TRUE(response->headers);
6133 EXPECT_EQ(407, response->headers->response_code());
6134 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586135 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046136
6137 // Now provide credentials for the first request, and wait for it to complete.
6138 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6139 rv = callback.GetResult(rv);
6140 EXPECT_THAT(rv, IsOk());
6141 response = trans1.GetResponseInfo();
6142 ASSERT_TRUE(response);
6143 ASSERT_TRUE(response->headers);
6144 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6145 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6146 EXPECT_EQ(kUploadData, response_data);
6147
6148 // Now provide credentials for the second request. It should notice the
6149 // existing session, and reuse it.
6150 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6151 EXPECT_THAT(callback.GetResult(rv), IsOk());
6152 response = trans2.GetResponseInfo();
6153 ASSERT_TRUE(response);
6154 ASSERT_TRUE(response->headers);
6155 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6156 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6157 EXPECT_EQ(kUploadData, response_data);
6158}
6159
[email protected]f6c63db52013-02-02 00:35:226160// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6161// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016162TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226163 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6164 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496165 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6166 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516167 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076168 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096169 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506170 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226171
6172 HttpRequestInfo request1;
6173 request1.method = "GET";
bncce36dca22015-04-21 22:11:236174 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226175 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106176 request1.traffic_annotation =
6177 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226178
6179 HttpRequestInfo request2;
6180 request2.method = "GET";
bncce36dca22015-04-21 22:11:236181 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226182 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106183 request2.traffic_annotation =
6184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226185
bncce36dca22015-04-21 22:11:236186 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136187 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046188 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6189 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136190 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356191 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226192
bncce36dca22015-04-21 22:11:236193 // Fetch https://www.example.org/ via HTTP.
6194 const char get1[] =
6195 "GET / HTTP/1.1\r\n"
6196 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226197 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136198 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196199 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226200 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6201 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136202 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196203 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136204 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196205 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136206 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416207 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226208
bncce36dca22015-04-21 22:11:236209 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136210 spdy::SpdyHeaderBlock connect2_block;
6211 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6212 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6213 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046214 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6215 false));
[email protected]601e03f12014-04-06 16:26:396216
Ryan Hamilton0239aac2018-05-19 00:03:136217 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356218 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226219
bncce36dca22015-04-21 22:11:236220 // Fetch https://mail.example.org/ via HTTP.
6221 const char get2[] =
6222 "GET / HTTP/1.1\r\n"
6223 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226224 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136225 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196226 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226227 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6228 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136229 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196230 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136231 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196232 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226233
6234 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416235 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6236 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226237 };
6238
6239 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416240 CreateMockRead(conn_resp1, 1, ASYNC),
6241 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6242 CreateMockRead(wrapped_body1, 4, ASYNC),
6243 CreateMockRead(conn_resp2, 6, ASYNC),
6244 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6245 CreateMockRead(wrapped_body2, 9, ASYNC),
6246 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226247 };
6248
Ryan Sleevib8d7ea02018-05-07 20:01:016249 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506250 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226251
6252 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366253 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506254 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226255 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506256 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226257 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226259
6260 TestCompletionCallback callback;
6261
bnc691fda62016-08-12 00:43:166262 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:206263 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016264 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226265
6266 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166267 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226268 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6269
bnc691fda62016-08-12 00:43:166270 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526271 ASSERT_TRUE(response);
6272 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226273 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6274
6275 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446276 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166277 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506278 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226279
bnc691fda62016-08-12 00:43:166280 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:206281 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016282 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226283
6284 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166285 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226286 // Even though the SPDY connection is reused, a new tunnelled connection has
6287 // to be created, so the socket's load timing looks like a fresh connection.
6288 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6289
6290 // The requests should have different IDs, since they each are using their own
6291 // separate stream.
6292 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6293
bnc691fda62016-08-12 00:43:166294 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506295 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226296}
6297
6298// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6299// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016300TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226301 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6302 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496303 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6304 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516305 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076306 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096307 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506308 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226309
6310 HttpRequestInfo request1;
6311 request1.method = "GET";
bncce36dca22015-04-21 22:11:236312 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226313 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106314 request1.traffic_annotation =
6315 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226316
6317 HttpRequestInfo request2;
6318 request2.method = "GET";
bncce36dca22015-04-21 22:11:236319 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226320 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106321 request2.traffic_annotation =
6322 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226323
bncce36dca22015-04-21 22:11:236324 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136325 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046326 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6327 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136328 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356329 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226330
bncce36dca22015-04-21 22:11:236331 // Fetch https://www.example.org/ via HTTP.
6332 const char get1[] =
6333 "GET / HTTP/1.1\r\n"
6334 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226335 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136336 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196337 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226338 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6339 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136340 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196341 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136342 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196343 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136344 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416345 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226346
bncce36dca22015-04-21 22:11:236347 // Fetch https://www.example.org/2 via HTTP.
6348 const char get2[] =
6349 "GET /2 HTTP/1.1\r\n"
6350 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226351 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136352 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196353 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226354 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6355 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136356 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196357 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136358 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196359 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226360
6361 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416362 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6363 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226364 };
6365
6366 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416367 CreateMockRead(conn_resp1, 1, ASYNC),
6368 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466369 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416370 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466371 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416372 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226373 };
6374
Ryan Sleevib8d7ea02018-05-07 20:01:016375 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506376 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226377
6378 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366379 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506380 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226381 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506382 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226383
6384 TestCompletionCallback callback;
6385
bnc87dcefc2017-05-25 12:47:586386 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196387 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:206388 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016389 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226390
6391 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016392 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226393
6394 LoadTimingInfo load_timing_info;
6395 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6396 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6397
6398 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526399 ASSERT_TRUE(response);
6400 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226401 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6402
6403 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446404 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506405 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226406 trans.reset();
6407
bnc87dcefc2017-05-25 12:47:586408 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196409 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:206410 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016411 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226412
[email protected]f6c63db52013-02-02 00:35:226413 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016414 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226415
6416 LoadTimingInfo load_timing_info2;
6417 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6418 TestLoadTimingReused(load_timing_info2);
6419
6420 // The requests should have the same ID.
6421 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6422
[email protected]90499482013-06-01 00:39:506423 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226424}
6425
6426// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6427// Proxy to different servers.
bncd16676a2016-07-20 16:23:016428TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226429 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496430 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6431 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516432 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076433 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096434 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506435 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226436
6437 HttpRequestInfo request1;
6438 request1.method = "GET";
bncce36dca22015-04-21 22:11:236439 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226440 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106441 request1.traffic_annotation =
6442 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226443
6444 HttpRequestInfo request2;
6445 request2.method = "GET";
bncce36dca22015-04-21 22:11:236446 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226447 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106448 request2.traffic_annotation =
6449 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226450
bncce36dca22015-04-21 22:11:236451 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136452 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236453 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136454 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156455 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136456 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356457 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136458 spdy::SpdySerializedFrame body1(
6459 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386460 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226461
bncce36dca22015-04-21 22:11:236462 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136463 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:236464 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136465 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:156466 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136467 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356468 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136469 spdy::SpdySerializedFrame body2(
6470 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:226471
6472 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416473 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:226474 };
6475
6476 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416477 CreateMockRead(get_resp1, 1, ASYNC),
6478 CreateMockRead(body1, 2, ASYNC),
6479 CreateMockRead(get_resp2, 4, ASYNC),
6480 CreateMockRead(body2, 5, ASYNC),
6481 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:226482 };
6483
Ryan Sleevib8d7ea02018-05-07 20:01:016484 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506485 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226486
6487 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366488 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226490
6491 TestCompletionCallback callback;
6492
bnc87dcefc2017-05-25 12:47:586493 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196494 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:206495 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016496 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226497
6498 LoadTimingInfo load_timing_info;
6499 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6500 TestLoadTimingNotReused(load_timing_info,
6501 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6502
6503 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526504 ASSERT_TRUE(response);
6505 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026506 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:226507
6508 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446509 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:506510 rv = trans->Read(buf.get(), 256, callback.callback());
6511 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226512 // Delete the first request, so the second one can reuse the socket.
6513 trans.reset();
6514
bnc691fda62016-08-12 00:43:166515 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:206516 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016517 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226518
6519 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166520 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226521 TestLoadTimingReused(load_timing_info2);
6522
6523 // The requests should have the same ID.
6524 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6525
bnc691fda62016-08-12 00:43:166526 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506527 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226528}
6529
Matt Menke2436b2f2018-12-11 18:07:116530// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
6531// direct (non-proxied) request to the proxy server are not pooled, as that
6532// would break socket pool isolation.
6533TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
6534 ProxyConfig proxy_config;
6535 proxy_config.set_auto_detect(true);
6536 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6537
6538 CapturingProxyResolver capturing_proxy_resolver;
6539 session_deps_.proxy_resolution_service =
6540 std::make_unique<ProxyResolutionService>(
6541 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6542 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6543 std::make_unique<CapturingProxyResolverFactory>(
6544 &capturing_proxy_resolver),
6545 nullptr);
6546
6547 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6548
6549 SpdyTestUtil spdy_util1;
6550 // CONNECT to www.example.org:443 via HTTP/2.
6551 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046552 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6553 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116554 // fetch https://www.example.org/ via HTTP/2.
6555 const char kMyUrl[] = "https://www.example.org/";
6556 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6557 spdy::SpdySerializedFrame wrapped_get(
6558 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6559 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356560 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116561 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356562 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116563 spdy::SpdySerializedFrame wrapped_get_resp(
6564 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6565 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
6566 spdy::SpdySerializedFrame wrapped_body(
6567 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6568 spdy::SpdySerializedFrame window_update_get_resp(
6569 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6570 spdy::SpdySerializedFrame window_update_body(
6571 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6572
6573 MockWrite spdy_writes1[] = {
6574 CreateMockWrite(connect, 0),
6575 CreateMockWrite(wrapped_get, 2),
6576 CreateMockWrite(window_update_get_resp, 6),
6577 CreateMockWrite(window_update_body, 7),
6578 };
6579
6580 MockRead spdy_reads1[] = {
6581 CreateMockRead(conn_resp, 1, ASYNC),
6582 MockRead(ASYNC, ERR_IO_PENDING, 3),
6583 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6584 CreateMockRead(wrapped_body, 5, ASYNC),
6585 MockRead(ASYNC, 0, 8),
6586 };
6587
6588 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6589 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6590
6591 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
6592 // a new pipe.
6593 SpdyTestUtil spdy_util2;
6594 spdy::SpdySerializedFrame req(
6595 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6596 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
6597
6598 spdy::SpdySerializedFrame resp(
6599 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6600 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
6601 MockRead spdy_reads2[] = {
6602 CreateMockRead(resp, 1),
6603 CreateMockRead(data, 2),
6604 MockRead(ASYNC, 0, 3),
6605 };
6606 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6607 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6608
6609 SSLSocketDataProvider ssl(ASYNC, OK);
6610 ssl.next_proto = kProtoHTTP2;
6611 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6612 SSLSocketDataProvider ssl2(ASYNC, OK);
6613 ssl2.next_proto = kProtoHTTP2;
6614 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6615 SSLSocketDataProvider ssl3(ASYNC, OK);
6616 ssl3.next_proto = kProtoHTTP2;
6617 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6618
6619 TestCompletionCallback callback;
6620 std::string response_data;
6621
6622 // Make a request using proxy:70 as a HTTP/2 proxy.
6623 capturing_proxy_resolver.set_proxy_server(
6624 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6625 HttpRequestInfo request1;
6626 request1.method = "GET";
6627 request1.url = GURL("https://www.example.org/");
6628 request1.traffic_annotation =
6629 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6630
6631 HttpNetworkTransaction trans1(LOWEST, session.get());
6632 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6633 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6634
6635 // Allow the SpdyProxyClientSocket's write callback to complete.
6636 base::RunLoop().RunUntilIdle();
6637 // Now allow the read of the response to complete.
6638 spdy_data1.Resume();
6639 rv = callback.WaitForResult();
6640 EXPECT_THAT(rv, IsOk());
6641
6642 const HttpResponseInfo* response = trans1.GetResponseInfo();
6643 ASSERT_TRUE(response);
6644 ASSERT_TRUE(response->headers);
6645 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6646
6647 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6648 EXPECT_EQ(kUploadData, response_data);
6649 RunUntilIdle();
6650
6651 // Make a direct HTTP/2 request to proxy:70.
6652 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6653 HttpRequestInfo request2;
6654 request2.method = "GET";
6655 request2.url = GURL("https://proxy:70/");
6656 request2.traffic_annotation =
6657 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6658 HttpNetworkTransaction trans2(LOWEST, session.get());
6659 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
6660 NetLogWithSource())),
6661 IsOk());
6662 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6663}
6664
6665// Same as above, but reverse request order, since the code to check for an
6666// existing session is different for tunnels and direct connections.
6667TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
6668 // Configure against https proxy server "myproxy:80".
6669 ProxyConfig proxy_config;
6670 proxy_config.set_auto_detect(true);
6671 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6672
6673 CapturingProxyResolver capturing_proxy_resolver;
6674 session_deps_.proxy_resolution_service =
6675 std::make_unique<ProxyResolutionService>(
6676 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6677 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6678 std::make_unique<CapturingProxyResolverFactory>(
6679 &capturing_proxy_resolver),
6680 nullptr);
6681
6682 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6683 // Fetch https://proxy:70/ via HTTP/2.
6684 SpdyTestUtil spdy_util1;
6685 spdy::SpdySerializedFrame req(
6686 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6687 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
6688
6689 spdy::SpdySerializedFrame resp(
6690 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
6691 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
6692 MockRead spdy_reads1[] = {
6693 CreateMockRead(resp, 1),
6694 CreateMockRead(data, 2),
6695 MockRead(ASYNC, 0, 3),
6696 };
6697 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6698 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6699
6700 SpdyTestUtil spdy_util2;
6701 // CONNECT to www.example.org:443 via HTTP/2.
6702 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046703 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6704 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116705 // fetch https://www.example.org/ via HTTP/2.
6706 const char kMyUrl[] = "https://www.example.org/";
6707 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6708 spdy::SpdySerializedFrame wrapped_get(
6709 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6710 spdy::SpdySerializedFrame conn_resp(
6711 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6712 spdy::SpdySerializedFrame get_resp(
6713 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6714 spdy::SpdySerializedFrame wrapped_get_resp(
6715 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6716 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
6717 spdy::SpdySerializedFrame wrapped_body(
6718 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6719 spdy::SpdySerializedFrame window_update_get_resp(
6720 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6721 spdy::SpdySerializedFrame window_update_body(
6722 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6723
6724 MockWrite spdy_writes2[] = {
6725 CreateMockWrite(connect, 0),
6726 CreateMockWrite(wrapped_get, 2),
6727 CreateMockWrite(window_update_get_resp, 6),
6728 CreateMockWrite(window_update_body, 7),
6729 };
6730
6731 MockRead spdy_reads2[] = {
6732 CreateMockRead(conn_resp, 1, ASYNC),
6733 MockRead(ASYNC, ERR_IO_PENDING, 3),
6734 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6735 CreateMockRead(wrapped_body, 5, ASYNC),
6736 MockRead(ASYNC, 0, 8),
6737 };
6738
6739 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6740 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6741
6742 SSLSocketDataProvider ssl(ASYNC, OK);
6743 ssl.next_proto = kProtoHTTP2;
6744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6745 SSLSocketDataProvider ssl2(ASYNC, OK);
6746 ssl2.next_proto = kProtoHTTP2;
6747 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6748 SSLSocketDataProvider ssl3(ASYNC, OK);
6749 ssl3.next_proto = kProtoHTTP2;
6750 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6751
6752 TestCompletionCallback callback;
6753 std::string response_data;
6754
6755 // Make a direct HTTP/2 request to proxy:70.
6756 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6757 HttpRequestInfo request1;
6758 request1.method = "GET";
6759 request1.url = GURL("https://proxy:70/");
6760 request1.traffic_annotation =
6761 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6762 HttpNetworkTransaction trans1(LOWEST, session.get());
6763 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
6764 NetLogWithSource())),
6765 IsOk());
6766 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6767 RunUntilIdle();
6768
6769 // Make a request using proxy:70 as a HTTP/2 proxy.
6770 capturing_proxy_resolver.set_proxy_server(
6771 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6772 HttpRequestInfo request2;
6773 request2.method = "GET";
6774 request2.url = GURL("https://www.example.org/");
6775 request2.traffic_annotation =
6776 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6777
6778 HttpNetworkTransaction trans2(LOWEST, session.get());
6779 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6780 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6781
6782 // Allow the SpdyProxyClientSocket's write callback to complete.
6783 base::RunLoop().RunUntilIdle();
6784 // Now allow the read of the response to complete.
6785 spdy_data2.Resume();
6786 rv = callback.WaitForResult();
6787 EXPECT_THAT(rv, IsOk());
6788
6789 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
6790 ASSERT_TRUE(response2);
6791 ASSERT_TRUE(response2->headers);
6792 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
6793
6794 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6795 EXPECT_EQ(kUploadData, response_data);
6796}
6797
[email protected]2df19bb2010-08-25 20:13:466798// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:016799TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:466800 HttpRequestInfo request;
6801 request.method = "GET";
bncce36dca22015-04-21 22:11:236802 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:466803 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:296804 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:106805 request.traffic_annotation =
6806 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:466807
[email protected]79cb5c12011-09-12 13:12:046808 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496809 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6810 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516811 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076812 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096813 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276814
[email protected]2df19bb2010-08-25 20:13:466815 // Since we have proxy, should use full url
6816 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:166817 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6818 "Host: www.example.org\r\n"
6819 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466820
bnc691fda62016-08-12 00:43:166821 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:236822 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:166823 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6824 "Host: www.example.org\r\n"
6825 "Proxy-Connection: keep-alive\r\n"
6826 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466827 };
6828
6829 // The proxy responds to the GET with a 407, using a persistent
6830 // connection.
6831 MockRead data_reads1[] = {
6832 // No credentials.
6833 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6834 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6835 MockRead("Proxy-Connection: keep-alive\r\n"),
6836 MockRead("Content-Length: 0\r\n\r\n"),
6837
6838 MockRead("HTTP/1.1 200 OK\r\n"),
6839 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6840 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066841 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466842 };
6843
Ryan Sleevib8d7ea02018-05-07 20:01:016844 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076845 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066846 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076847 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466848
[email protected]49639fa2011-12-20 23:22:416849 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466850
bnc691fda62016-08-12 00:43:166851 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506852
bnc691fda62016-08-12 00:43:166853 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016854 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466855
6856 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016857 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466858
[email protected]58e32bb2013-01-21 18:23:256859 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166860 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256861 TestLoadTimingNotReused(load_timing_info,
6862 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6863
bnc691fda62016-08-12 00:43:166864 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526865 ASSERT_TRUE(response);
6866 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:466867 EXPECT_EQ(407, response->headers->response_code());
6868 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586869 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:506870 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466871
[email protected]49639fa2011-12-20 23:22:416872 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:466873
bnc691fda62016-08-12 00:43:166874 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016875 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466876
6877 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016878 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466879
[email protected]58e32bb2013-01-21 18:23:256880 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:166881 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256882 // Retrying with HTTP AUTH is considered to be reusing a socket.
6883 TestLoadTimingReused(load_timing_info);
6884
bnc691fda62016-08-12 00:43:166885 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526886 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466887
6888 EXPECT_TRUE(response->headers->IsKeepAlive());
6889 EXPECT_EQ(200, response->headers->response_code());
6890 EXPECT_EQ(100, response->headers->GetContentLength());
6891 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:506892 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466893
6894 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586895 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466896}
6897
[email protected]23e482282013-06-14 16:08:026898void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:086899 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:426900 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:086901 request.method = "GET";
bncce36dca22015-04-21 22:11:236902 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106903 request.traffic_annotation =
6904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:086905
[email protected]cb9bf6ca2011-01-28 13:15:276906 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496907 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6908 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096909 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276910
[email protected]c744cf22009-02-27 07:28:086911 // Since we have proxy, should try to establish tunnel.
6912 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:176913 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6914 "Host: www.example.org:443\r\n"
6915 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:086916 };
6917
6918 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:236919 status, MockRead("Content-Length: 10\r\n\r\n"),
6920 // No response body because the test stops reading here.
6921 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:086922 };
6923
Ryan Sleevib8d7ea02018-05-07 20:01:016924 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:076925 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:086926
[email protected]49639fa2011-12-20 23:22:416927 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:086928
bnc691fda62016-08-12 00:43:166929 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506930
tfarina428341112016-09-22 13:38:206931 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016932 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:086933
6934 rv = callback.WaitForResult();
6935 EXPECT_EQ(expected_status, rv);
6936}
6937
[email protected]23e482282013-06-14 16:08:026938void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:236939 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:086940 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:426941 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:086942}
6943
bncd16676a2016-07-20 16:23:016944TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:086945 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
6946}
6947
bncd16676a2016-07-20 16:23:016948TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:086949 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
6950}
6951
bncd16676a2016-07-20 16:23:016952TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:086953 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
6954}
6955
bncd16676a2016-07-20 16:23:016956TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:086957 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
6958}
6959
bncd16676a2016-07-20 16:23:016960TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:086961 ConnectStatusHelper(
6962 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
6963}
6964
bncd16676a2016-07-20 16:23:016965TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:086966 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
6967}
6968
bncd16676a2016-07-20 16:23:016969TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:086970 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
6971}
6972
bncd16676a2016-07-20 16:23:016973TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:086974 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
6975}
6976
bncd16676a2016-07-20 16:23:016977TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:086978 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
6979}
6980
bncd16676a2016-07-20 16:23:016981TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:086982 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
6983}
6984
bncd16676a2016-07-20 16:23:016985TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:086986 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
6987}
6988
bncd16676a2016-07-20 16:23:016989TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:086990 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
6991}
6992
bncd16676a2016-07-20 16:23:016993TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:086994 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
6995}
6996
bncd16676a2016-07-20 16:23:016997TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:086998 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
6999}
7000
bncd16676a2016-07-20 16:23:017001TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:087002 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
7003}
7004
bncd16676a2016-07-20 16:23:017005TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:087006 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
7007}
7008
bncd16676a2016-07-20 16:23:017009TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:377010 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
7011}
7012
bncd16676a2016-07-20 16:23:017013TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:087014 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
7015}
7016
bncd16676a2016-07-20 16:23:017017TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:087018 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
7019}
7020
bncd16676a2016-07-20 16:23:017021TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:087022 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
7023}
7024
bncd16676a2016-07-20 16:23:017025TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:087026 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
7027}
7028
bncd16676a2016-07-20 16:23:017029TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:087030 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
7031}
7032
bncd16676a2016-07-20 16:23:017033TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:087034 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
7035}
7036
bncd16676a2016-07-20 16:23:017037TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:087038 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
7039}
7040
bncd16676a2016-07-20 16:23:017041TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:087042 ConnectStatusHelperWithExpectedStatus(
7043 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:547044 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:087045}
7046
bncd16676a2016-07-20 16:23:017047TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:087048 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
7049}
7050
bncd16676a2016-07-20 16:23:017051TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:087052 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
7053}
7054
bncd16676a2016-07-20 16:23:017055TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:087056 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
7057}
7058
bncd16676a2016-07-20 16:23:017059TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:087060 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
7061}
7062
bncd16676a2016-07-20 16:23:017063TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:087064 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
7065}
7066
bncd16676a2016-07-20 16:23:017067TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:087068 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
7069}
7070
bncd16676a2016-07-20 16:23:017071TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:087072 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
7073}
7074
bncd16676a2016-07-20 16:23:017075TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:087076 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
7077}
7078
bncd16676a2016-07-20 16:23:017079TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:087080 ConnectStatusHelper(
7081 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
7082}
7083
bncd16676a2016-07-20 16:23:017084TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:087085 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
7086}
7087
bncd16676a2016-07-20 16:23:017088TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:087089 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
7090}
7091
bncd16676a2016-07-20 16:23:017092TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:087093 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
7094}
7095
bncd16676a2016-07-20 16:23:017096TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:087097 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
7098}
7099
bncd16676a2016-07-20 16:23:017100TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:087101 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
7102}
7103
bncd16676a2016-07-20 16:23:017104TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:087105 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
7106}
7107
bncd16676a2016-07-20 16:23:017108TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087109 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7110}
7111
[email protected]038e9a32008-10-08 22:40:167112// Test the flow when both the proxy server AND origin server require
7113// authentication. Again, this uses basic auth for both since that is
7114// the simplest to mock.
bncd16676a2016-07-20 16:23:017115TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277116 HttpRequestInfo request;
7117 request.method = "GET";
bncce36dca22015-04-21 22:11:237118 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107119 request.traffic_annotation =
7120 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277121
[email protected]038e9a32008-10-08 22:40:167122 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497123 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7124 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097125 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077126
bnc691fda62016-08-12 00:43:167127 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167128
[email protected]f9ee6b52008-11-08 06:46:237129 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237130 MockWrite(
7131 "GET http://www.example.org/ HTTP/1.1\r\n"
7132 "Host: www.example.org\r\n"
7133 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237134 };
7135
[email protected]038e9a32008-10-08 22:40:167136 MockRead data_reads1[] = {
7137 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7138 // Give a couple authenticate options (only the middle one is actually
7139 // supported).
[email protected]22927ad2009-09-21 19:56:197140 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167141 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7142 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7143 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7144 // Large content-length -- won't matter, as connection will be reset.
7145 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067146 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167147 };
7148
bnc691fda62016-08-12 00:43:167149 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167150 // request we should be issuing -- the final header line contains the
7151 // proxy's credentials.
7152 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237153 MockWrite(
7154 "GET http://www.example.org/ HTTP/1.1\r\n"
7155 "Host: www.example.org\r\n"
7156 "Proxy-Connection: keep-alive\r\n"
7157 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167158 };
7159
7160 // Now the proxy server lets the request pass through to origin server.
7161 // The origin server responds with a 401.
7162 MockRead data_reads2[] = {
7163 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7164 // Note: We are using the same realm-name as the proxy server. This is
7165 // completely valid, as realms are unique across hosts.
7166 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7167 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7168 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067169 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167170 };
7171
bnc691fda62016-08-12 00:43:167172 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167173 // the credentials for both the proxy and origin server.
7174 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237175 MockWrite(
7176 "GET http://www.example.org/ HTTP/1.1\r\n"
7177 "Host: www.example.org\r\n"
7178 "Proxy-Connection: keep-alive\r\n"
7179 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7180 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167181 };
7182
7183 // Lastly we get the desired content.
7184 MockRead data_reads3[] = {
7185 MockRead("HTTP/1.0 200 OK\r\n"),
7186 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7187 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067188 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167189 };
7190
Ryan Sleevib8d7ea02018-05-07 20:01:017191 StaticSocketDataProvider data1(data_reads1, data_writes1);
7192 StaticSocketDataProvider data2(data_reads2, data_writes2);
7193 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077194 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7195 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7196 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167197
[email protected]49639fa2011-12-20 23:22:417198 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167199
tfarina428341112016-09-22 13:38:207200 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017201 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167202
7203 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017204 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167205
bnc691fda62016-08-12 00:43:167206 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527207 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587208 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167209
[email protected]49639fa2011-12-20 23:22:417210 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167211
bnc691fda62016-08-12 00:43:167212 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017213 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167214
7215 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017216 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167217
bnc691fda62016-08-12 00:43:167218 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527219 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587220 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167221
[email protected]49639fa2011-12-20 23:22:417222 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167223
bnc691fda62016-08-12 00:43:167224 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7225 callback3.callback());
robpercival214763f2016-07-01 23:27:017226 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167227
7228 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017229 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167230
bnc691fda62016-08-12 00:43:167231 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587232 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167233 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167234}
[email protected]4ddaf2502008-10-23 18:26:197235
[email protected]ea9dc9a2009-09-05 00:43:327236// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7237// can't hook into its internals to cause it to generate predictable NTLM
7238// authorization headers.
7239#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377240// The NTLM authentication unit tests are based on known test data from the
7241// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7242// flow rather than the implementation of the NTLM protocol. See net/ntlm
7243// for the implementation and testing of the protocol.
7244//
7245// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297246
7247// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557248TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427249 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247250 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557251 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107252 request.traffic_annotation =
7253 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547254
7255 // Ensure load is not disrupted by flags which suppress behaviour specific
7256 // to other auth schemes.
7257 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247258
Zentaro Kavanagh6ccee512017-09-28 18:34:097259 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7260 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097261 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277262
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377263 // Generate the NTLM messages based on known test data.
7264 std::string negotiate_msg;
7265 std::string challenge_msg;
7266 std::string authenticate_msg;
7267 base::Base64Encode(
7268 base::StringPiece(
7269 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247270 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377271 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557272 base::Base64Encode(
7273 base::StringPiece(
7274 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247275 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557276 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377277 base::Base64Encode(
7278 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097279 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557280 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247281 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557282 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377283 &authenticate_msg);
7284
[email protected]3f918782009-02-28 01:29:247285 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557286 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7287 "Host: server\r\n"
7288 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247289 };
7290
7291 MockRead data_reads1[] = {
7292 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047293 // Negotiate and NTLM are often requested together. However, we only want
7294 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7295 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247296 MockRead("WWW-Authenticate: NTLM\r\n"),
7297 MockRead("Connection: close\r\n"),
7298 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367299 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247300 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247301 };
7302
7303 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167304 // After restarting with a null identity, this is the
7305 // request we should be issuing -- the final header line contains a Type
7306 // 1 message.
7307 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557308 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167309 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377310 "Authorization: NTLM "),
7311 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247312
bnc691fda62016-08-12 00:43:167313 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377314 // (using correct credentials). The second request continues on the
7315 // same connection.
bnc691fda62016-08-12 00:43:167316 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557317 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167318 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377319 "Authorization: NTLM "),
7320 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247321 };
7322
7323 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027324 // The origin server responds with a Type 2 message.
7325 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377326 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7327 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027328 MockRead("Content-Type: text/html\r\n\r\n"),
7329 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247330
Bence Béky1e4ef192017-09-18 19:58:027331 // Lastly we get the desired content.
7332 MockRead("HTTP/1.1 200 OK\r\n"),
7333 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7334 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247335 };
7336
Ryan Sleevib8d7ea02018-05-07 20:01:017337 StaticSocketDataProvider data1(data_reads1, data_writes1);
7338 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077339 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7340 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247341
Bence Béky83eb3512017-09-05 12:56:097342 SSLSocketDataProvider ssl1(ASYNC, OK);
7343 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7344 SSLSocketDataProvider ssl2(ASYNC, OK);
7345 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7346
[email protected]49639fa2011-12-20 23:22:417347 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247348
bnc691fda62016-08-12 00:43:167349 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507350
tfarina428341112016-09-22 13:38:207351 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017352 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247353
7354 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017355 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247356
bnc691fda62016-08-12 00:43:167357 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227358
bnc691fda62016-08-12 00:43:167359 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527360 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587361 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247362
[email protected]49639fa2011-12-20 23:22:417363 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257364
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377365 rv = trans.RestartWithAuth(
7366 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7367 callback2.callback());
robpercival214763f2016-07-01 23:27:017368 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257369
7370 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017371 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257372
bnc691fda62016-08-12 00:43:167373 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257374
bnc691fda62016-08-12 00:43:167375 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527376 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587377 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257378
[email protected]49639fa2011-12-20 23:22:417379 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247380
bnc691fda62016-08-12 00:43:167381 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017382 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247383
[email protected]0757e7702009-03-27 04:00:227384 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017385 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247386
bnc691fda62016-08-12 00:43:167387 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527388 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587389 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027390 EXPECT_EQ(14, response->headers->GetContentLength());
7391
7392 std::string response_data;
7393 rv = ReadTransaction(&trans, &response_data);
7394 EXPECT_THAT(rv, IsOk());
7395 EXPECT_EQ("Please Login\r\n", response_data);
7396
7397 EXPECT_TRUE(data1.AllReadDataConsumed());
7398 EXPECT_TRUE(data1.AllWriteDataConsumed());
7399 EXPECT_TRUE(data2.AllReadDataConsumed());
7400 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247401}
7402
[email protected]385a4672009-03-11 22:21:297403// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557404TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427405 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297406 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557407 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107408 request.traffic_annotation =
7409 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297410
Zentaro Kavanagh6ccee512017-09-28 18:34:097411 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7412 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097413 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277414
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377415 // Generate the NTLM messages based on known test data.
7416 std::string negotiate_msg;
7417 std::string challenge_msg;
7418 std::string authenticate_msg;
7419 base::Base64Encode(
7420 base::StringPiece(
7421 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247422 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377423 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557424 base::Base64Encode(
7425 base::StringPiece(
7426 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247427 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557428 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377429 base::Base64Encode(
7430 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097431 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557432 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247433 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557434 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377435 &authenticate_msg);
7436
7437 // The authenticate message when |kWrongPassword| is sent.
7438 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557439 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7440 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7441 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7442 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7443 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7444 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377445
Zentaro Kavanagh1890a3d2018-01-29 19:52:557446 // Sanity check that it's the same length as the correct authenticate message
7447 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377448 ASSERT_EQ(authenticate_msg.length(),
7449 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557450 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377451
[email protected]385a4672009-03-11 22:21:297452 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557453 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7454 "Host: server\r\n"
7455 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297456 };
7457
7458 MockRead data_reads1[] = {
7459 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047460 // Negotiate and NTLM are often requested together. However, we only want
7461 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7462 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:297463 MockRead("WWW-Authenticate: NTLM\r\n"),
7464 MockRead("Connection: close\r\n"),
7465 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367466 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297467 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297468 };
7469
7470 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167471 // After restarting with a null identity, this is the
7472 // request we should be issuing -- the final header line contains a Type
7473 // 1 message.
7474 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557475 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167476 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377477 "Authorization: NTLM "),
7478 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297479
bnc691fda62016-08-12 00:43:167480 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377481 // (using incorrect credentials). The second request continues on the
7482 // same connection.
bnc691fda62016-08-12 00:43:167483 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557484 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167485 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377486 "Authorization: NTLM "),
7487 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297488 };
7489
7490 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377491 // The origin server responds with a Type 2 message.
7492 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7493 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7494 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
7495 MockRead("Content-Type: text/html\r\n\r\n"),
7496 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297497
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377498 // Wrong password.
7499 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7500 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
7501 MockRead("Content-Length: 42\r\n"),
7502 MockRead("Content-Type: text/html\r\n\r\n"),
7503 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297504 };
7505
7506 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:167507 // After restarting with a null identity, this is the
7508 // request we should be issuing -- the final header line contains a Type
7509 // 1 message.
7510 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557511 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167512 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377513 "Authorization: NTLM "),
7514 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297515
bnc691fda62016-08-12 00:43:167516 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7517 // (the credentials for the origin server). The second request continues
7518 // on the same connection.
7519 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557520 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167521 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377522 "Authorization: NTLM "),
7523 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297524 };
7525
7526 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:027527 // The origin server responds with a Type 2 message.
7528 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377529 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7530 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027531 MockRead("Content-Type: text/html\r\n\r\n"),
7532 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297533
Bence Béky1e4ef192017-09-18 19:58:027534 // Lastly we get the desired content.
7535 MockRead("HTTP/1.1 200 OK\r\n"),
7536 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7537 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:297538 };
7539
Ryan Sleevib8d7ea02018-05-07 20:01:017540 StaticSocketDataProvider data1(data_reads1, data_writes1);
7541 StaticSocketDataProvider data2(data_reads2, data_writes2);
7542 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077543 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7544 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7545 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:297546
Bence Béky83eb3512017-09-05 12:56:097547 SSLSocketDataProvider ssl1(ASYNC, OK);
7548 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7549 SSLSocketDataProvider ssl2(ASYNC, OK);
7550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7551 SSLSocketDataProvider ssl3(ASYNC, OK);
7552 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7553
[email protected]49639fa2011-12-20 23:22:417554 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:297555
bnc691fda62016-08-12 00:43:167556 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507557
tfarina428341112016-09-22 13:38:207558 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017559 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297560
7561 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017562 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297563
bnc691fda62016-08-12 00:43:167564 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:297565
bnc691fda62016-08-12 00:43:167566 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527567 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587568 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:297569
[email protected]49639fa2011-12-20 23:22:417570 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:297571
[email protected]0757e7702009-03-27 04:00:227572 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377573 rv = trans.RestartWithAuth(
7574 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
7575 callback2.callback());
robpercival214763f2016-07-01 23:27:017576 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297577
[email protected]10af5fe72011-01-31 16:17:257578 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017579 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297580
bnc691fda62016-08-12 00:43:167581 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417582 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:167583 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017584 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257585 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017586 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:167587 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227588
bnc691fda62016-08-12 00:43:167589 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527590 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587591 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:227592
[email protected]49639fa2011-12-20 23:22:417593 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:227594
7595 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377596 rv = trans.RestartWithAuth(
7597 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7598 callback4.callback());
robpercival214763f2016-07-01 23:27:017599 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257600
7601 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:017602 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257603
bnc691fda62016-08-12 00:43:167604 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257605
[email protected]49639fa2011-12-20 23:22:417606 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:257607
7608 // One more roundtrip
bnc691fda62016-08-12 00:43:167609 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:017610 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227611
7612 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:017613 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227614
bnc691fda62016-08-12 00:43:167615 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587616 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027617 EXPECT_EQ(14, response->headers->GetContentLength());
7618
7619 std::string response_data;
7620 rv = ReadTransaction(&trans, &response_data);
7621 EXPECT_THAT(rv, IsOk());
7622 EXPECT_EQ("Please Login\r\n", response_data);
7623
7624 EXPECT_TRUE(data1.AllReadDataConsumed());
7625 EXPECT_TRUE(data1.AllWriteDataConsumed());
7626 EXPECT_TRUE(data2.AllReadDataConsumed());
7627 EXPECT_TRUE(data2.AllWriteDataConsumed());
7628 EXPECT_TRUE(data3.AllReadDataConsumed());
7629 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:297630}
Bence Béky83eb3512017-09-05 12:56:097631
Bence Béky3238f2e12017-09-22 22:44:497632// Server requests NTLM authentication, which is not supported over HTTP/2.
7633// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:097634TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:097635 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7636 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:097637
Zentaro Kavanagh1890a3d2018-01-29 19:52:557638 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:097639
7640 HttpRequestInfo request;
7641 request.method = "GET";
7642 request.url = GURL(kUrl);
Ramin Halavatib5e433e62018-02-07 07:41:107643 request.traffic_annotation =
7644 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:097645
7646 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:137647 spdy::SpdyHeaderBlock request_headers0(
7648 spdy_util_.ConstructGetHeaderBlock(kUrl));
7649 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:097650 1, std::move(request_headers0), LOWEST, true));
7651
Ryan Hamilton0239aac2018-05-19 00:03:137652 spdy::SpdyHeaderBlock response_headers0;
7653 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:097654 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:137655 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:097656 1, std::move(response_headers0), true));
7657
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377658 // Stream 1 is closed.
7659 spdy_util_.UpdateWithStreamDestruction(1);
7660
7661 // Generate the NTLM messages based on known test data.
7662 std::string negotiate_msg;
7663 std::string challenge_msg;
7664 std::string authenticate_msg;
7665 base::Base64Encode(
7666 base::StringPiece(
7667 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247668 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377669 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557670 base::Base64Encode(
7671 base::StringPiece(
7672 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247673 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557674 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377675 base::Base64Encode(
7676 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097677 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557678 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247679 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557680 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377681 &authenticate_msg);
7682
Bence Béky3238f2e12017-09-22 22:44:497683 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:167684 MockRead reads0[] = {CreateMockRead(resp, 1),
7685 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:097686
7687 // Retry yet again using HTTP/1.1.
7688 MockWrite writes1[] = {
7689 // After restarting with a null identity, this is the
7690 // request we should be issuing -- the final header line contains a Type
7691 // 1 message.
7692 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557693 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097694 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377695 "Authorization: NTLM "),
7696 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097697
7698 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7699 // (the credentials for the origin server). The second request continues
7700 // on the same connection.
7701 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557702 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097703 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377704 "Authorization: NTLM "),
7705 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097706 };
7707
7708 MockRead reads1[] = {
7709 // The origin server responds with a Type 2 message.
7710 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377711 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7712 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:097713 MockRead("Content-Type: text/html\r\n\r\n"),
7714 MockRead("You are not authorized to view this page\r\n"),
7715
7716 // Lastly we get the desired content.
7717 MockRead("HTTP/1.1 200 OK\r\n"),
7718 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027719 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:097720 };
Ryan Sleevib8d7ea02018-05-07 20:01:017721 SequencedSocketData data0(reads0, writes0);
7722 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:097723 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7724 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7725
7726 SSLSocketDataProvider ssl0(ASYNC, OK);
7727 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:167728 ssl0.next_protos_expected_in_ssl_config =
7729 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:097730 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:167731 // When creating the second connection, only HTTP/1.1 should be allowed.
7732 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:097733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7734 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7735
7736 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7737 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7738
7739 TestCompletionCallback callback1;
7740 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
7741 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7742
7743 rv = callback1.WaitForResult();
7744 EXPECT_THAT(rv, IsOk());
7745
7746 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7747
7748 const HttpResponseInfo* response = trans.GetResponseInfo();
7749 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587750 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:097751
7752 TestCompletionCallback callback2;
7753
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377754 rv = trans.RestartWithAuth(
7755 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7756 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:097757 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7758
7759 rv = callback2.WaitForResult();
7760 EXPECT_THAT(rv, IsOk());
7761
7762 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7763
7764 response = trans.GetResponseInfo();
7765 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587766 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:097767
7768 TestCompletionCallback callback3;
7769
7770 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
7771 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7772
7773 rv = callback3.WaitForResult();
7774 EXPECT_THAT(rv, IsOk());
7775
7776 response = trans.GetResponseInfo();
7777 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587778 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027779 EXPECT_EQ(14, response->headers->GetContentLength());
7780
7781 std::string response_data;
7782 rv = ReadTransaction(&trans, &response_data);
7783 EXPECT_THAT(rv, IsOk());
7784 EXPECT_EQ("Please Login\r\n", response_data);
7785
7786 EXPECT_TRUE(data0.AllReadDataConsumed());
7787 EXPECT_TRUE(data0.AllWriteDataConsumed());
7788 EXPECT_TRUE(data1.AllReadDataConsumed());
7789 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:097790}
David Benjamin5cb91132018-04-06 05:54:497791
Matt Menkef2ee07c2019-08-29 02:10:367792#if BUILDFLAG(ENABLE_WEBSOCKETS)
7793
7794// Variant of above test using WebSockets.
7795TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
7796 const GURL kInitialUrl("https://server/");
7797 const GURL kWebSocketUrl("wss://server/");
7798 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7799 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7800
7801 // Initial request establishes an H2 connection, which will then be reused for
7802 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
7803 // it won't create a new one.
7804 spdy::SpdyHeaderBlock initial_request_headers(
7805 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
7806 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
7807 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
7808 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
7809
7810 // Settings frame, indicating WebSockets is supported.
7811 spdy::SettingsMap settings;
7812 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
7813 spdy::SpdySerializedFrame settings_frame(
7814 spdy_util_.ConstructSpdySettings(settings));
7815
7816 // Response headers for first request. Body is never received, but that
7817 // shouldn't matter for the purposes of this test.
7818 spdy::SpdySerializedFrame initial_response(
7819 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7820
7821 // First WebSocket request, which has no credentials.
7822 spdy::SpdyHeaderBlock websocket_request_headers;
7823 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
7824 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
7825 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
7826 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
7827 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
7828 websocket_request_headers["origin"] = "http://server";
7829 websocket_request_headers["sec-websocket-version"] = "13";
7830 websocket_request_headers["sec-websocket-extensions"] =
7831 "permessage-deflate; client_max_window_bits";
7832 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
7833 3, std::move(websocket_request_headers), MEDIUM, false));
7834
7835 // Auth challenge to WebSocket request.
7836 spdy::SpdyHeaderBlock auth_challenge_headers;
7837 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
7838 auth_challenge_headers["www-authenticate"] = "NTLM";
7839 spdy::SpdySerializedFrame websocket_auth_challenge(
7840 spdy_util_.ConstructSpdyResponseHeaders(
7841 3, std::move(auth_challenge_headers), true));
7842
7843 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
7844 CreateMockWrite(settings_ack, 2),
7845 CreateMockWrite(websocket_request, 4),
7846 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
7847 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
7848 CreateMockRead(initial_response, 3),
7849 CreateMockRead(websocket_auth_challenge, 5),
7850 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
7851
7852 // Generate the NTLM messages based on known test data.
7853 std::string negotiate_msg;
7854 std::string challenge_msg;
7855 std::string authenticate_msg;
7856 base::Base64Encode(
7857 base::StringPiece(
7858 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
7859 base::size(ntlm::test::kExpectedNegotiateMsg)),
7860 &negotiate_msg);
7861 base::Base64Encode(
7862 base::StringPiece(
7863 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
7864 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
7865 &challenge_msg);
7866 base::Base64Encode(
7867 base::StringPiece(
7868 reinterpret_cast<const char*>(
7869 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
7870 base::size(
7871 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7872 &authenticate_msg);
7873
7874 // Retry yet again using HTTP/1.1.
7875 MockWrite writes1[] = {
7876 // After restarting with a null identity, this is the
7877 // request we should be issuing -- the final header line contains a Type
7878 // 1 message.
7879 MockWrite("GET / HTTP/1.1\r\n"
7880 "Host: server\r\n"
7881 "Connection: Upgrade\r\n"
7882 "Authorization: NTLM "),
7883 MockWrite(negotiate_msg.c_str()),
7884 MockWrite("\r\n"),
7885 MockWrite("Origin: http://server\r\n"
7886 "Sec-WebSocket-Version: 13\r\n"
7887 "Upgrade: websocket\r\n"
7888 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7889 "Sec-WebSocket-Extensions: permessage-deflate; "
7890 "client_max_window_bits\r\n\r\n"),
7891
7892 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7893 // (the credentials for the origin server). The second request continues
7894 // on the same connection.
7895 MockWrite("GET / HTTP/1.1\r\n"
7896 "Host: server\r\n"
7897 "Connection: Upgrade\r\n"
7898 "Authorization: NTLM "),
7899 MockWrite(authenticate_msg.c_str()),
7900 MockWrite("\r\n"),
7901 MockWrite("Origin: http://server\r\n"
7902 "Sec-WebSocket-Version: 13\r\n"
7903 "Upgrade: websocket\r\n"
7904 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7905 "Sec-WebSocket-Extensions: permessage-deflate; "
7906 "client_max_window_bits\r\n\r\n"),
7907 };
7908
7909 MockRead reads1[] = {
7910 // The origin server responds with a Type 2 message.
7911 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7912 MockRead("WWW-Authenticate: NTLM "),
7913 MockRead(challenge_msg.c_str()),
7914 MockRead("\r\n"),
7915 MockRead("Content-Length: 42\r\n"),
7916 MockRead("Content-Type: text/html\r\n\r\n"),
7917 MockRead("You are not authorized to view this page\r\n"),
7918
7919 // Lastly we get the desired content.
7920 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
7921 "Upgrade: websocket\r\n"
7922 "Connection: Upgrade\r\n"
7923 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
7924 };
7925 SequencedSocketData data0(reads0, writes0);
7926 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7927 SSLSocketDataProvider ssl0(ASYNC, OK);
7928 ssl0.next_proto = kProtoHTTP2;
7929 ssl0.next_protos_expected_in_ssl_config =
7930 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
7931 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7932
7933 StaticSocketDataProvider data1(reads1, writes1);
7934 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7935 SSLSocketDataProvider ssl1(ASYNC, OK);
7936 // When creating the second connection, only HTTP/1.1 should be allowed.
7937 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
7938 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7939
7940 session_deps_.enable_websocket_over_http2 = true;
7941 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7942
7943 HttpRequestInfo initial_request_info;
7944 initial_request_info.method = "GET";
7945 initial_request_info.url = kInitialUrl;
7946 initial_request_info.traffic_annotation =
7947 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7948 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
7949 TestCompletionCallback initial_callback;
7950 int rv = initial_trans.Start(&initial_request_info,
7951 initial_callback.callback(), NetLogWithSource());
7952 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
7953
7954 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
7955 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
7956
7957 HttpRequestInfo websocket_request_info;
7958 websocket_request_info.method = "GET";
7959 websocket_request_info.url = kWebSocketUrl;
7960 websocket_request_info.traffic_annotation =
7961 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7962 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
7963 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
7964 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
7965 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7966 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
7967 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
7968 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
7969
7970 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7971
7972 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
7973 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
7974 &websocket_stream_create_helper);
7975
7976 TestCompletionCallback websocket_callback;
7977 rv = websocket_trans.Start(&websocket_request_info,
7978 websocket_callback.callback(), NetLogWithSource());
7979 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
7980
7981 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
7982
7983 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
7984 ASSERT_TRUE(response);
7985 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
7986
7987 rv = websocket_trans.RestartWithAuth(
7988 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7989 websocket_callback.callback());
7990 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
7991
7992 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
7993
7994 response = websocket_trans.GetResponseInfo();
7995 ASSERT_TRUE(response);
7996 EXPECT_FALSE(response->auth_challenge.has_value());
7997
7998 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
7999 websocket_callback.callback());
8000 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8001
8002 // The server should have been marked as requiring HTTP/1.1. The important
8003 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
8004 // WSS.
8005 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
8006 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8007}
8008
8009#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
8010
David Benjamin5cb91132018-04-06 05:54:498011// Test that, if we have an NTLM proxy and the origin resets the connection, we
8012// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:378013// regression test for https://crbug.com/823387. The version interference probe
8014// has since been removed, but retain the regression test so we can update it if
8015// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:498016TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
8017 // The NTLM test data expects the proxy to be named 'server'. The origin is
8018 // https://origin/.
8019 session_deps_.proxy_resolution_service =
8020 ProxyResolutionService::CreateFixedFromPacResult(
8021 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
8022
David Benjamin151ec6b2019-08-02 19:38:528023 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:498024 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:078025 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:498026
8027 HttpRequestInfo request;
8028 request.method = "GET";
8029 request.url = GURL("https://origin/");
8030 request.traffic_annotation =
8031 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8032
8033 // Ensure load is not disrupted by flags which suppress behaviour specific
8034 // to other auth schemes.
8035 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
8036
8037 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
8038 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8039 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8040
8041 // Generate the NTLM messages based on known test data.
8042 std::string negotiate_msg;
8043 std::string challenge_msg;
8044 std::string authenticate_msg;
8045 base::Base64Encode(
8046 base::StringPiece(
8047 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248048 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:498049 &negotiate_msg);
8050 base::Base64Encode(
8051 base::StringPiece(
8052 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248053 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:498054 &challenge_msg);
8055 base::Base64Encode(
8056 base::StringPiece(
8057 reinterpret_cast<const char*>(
8058 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248059 base::size(
David Benjamin5cb91132018-04-06 05:54:498060 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8061 &authenticate_msg);
8062
8063 MockWrite data_writes[] = {
8064 // The initial CONNECT request.
8065 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8066 "Host: origin:443\r\n"
8067 "Proxy-Connection: keep-alive\r\n\r\n"),
8068
8069 // After restarting with an identity.
8070 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8071 "Host: origin:443\r\n"
8072 "Proxy-Connection: keep-alive\r\n"
8073 "Proxy-Authorization: NTLM "),
8074 MockWrite(negotiate_msg.c_str()),
8075 // End headers.
8076 MockWrite("\r\n\r\n"),
8077
8078 // The second restart.
8079 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8080 "Host: origin:443\r\n"
8081 "Proxy-Connection: keep-alive\r\n"
8082 "Proxy-Authorization: NTLM "),
8083 MockWrite(authenticate_msg.c_str()),
8084 // End headers.
8085 MockWrite("\r\n\r\n"),
8086 };
8087
8088 MockRead data_reads[] = {
8089 // The initial NTLM response.
8090 MockRead("HTTP/1.1 407 Access Denied\r\n"
8091 "Content-Length: 0\r\n"
8092 "Proxy-Authenticate: NTLM\r\n\r\n"),
8093
8094 // The NTLM challenge message.
8095 MockRead("HTTP/1.1 407 Access Denied\r\n"
8096 "Content-Length: 0\r\n"
8097 "Proxy-Authenticate: NTLM "),
8098 MockRead(challenge_msg.c_str()),
8099 // End headers.
8100 MockRead("\r\n\r\n"),
8101
8102 // Finally the tunnel is established.
8103 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
8104 };
8105
Ryan Sleevib8d7ea02018-05-07 20:01:018106 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:498107 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:498108 session_deps_.socket_factory->AddSocketDataProvider(&data);
8109 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:498110
8111 // Start the transaction. The proxy responds with an NTLM authentication
8112 // request.
8113 TestCompletionCallback callback;
8114 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8115 int rv = callback.GetResult(
8116 trans.Start(&request, callback.callback(), NetLogWithSource()));
8117
8118 EXPECT_THAT(rv, IsOk());
8119 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8120 const HttpResponseInfo* response = trans.GetResponseInfo();
8121 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588122 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:498123
David Benjamind61bd532019-04-23 21:11:378124 // Configure credentials and restart. The proxy responds with the challenge
8125 // message.
David Benjamin5cb91132018-04-06 05:54:498126 rv = callback.GetResult(trans.RestartWithAuth(
8127 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8128 callback.callback()));
8129 EXPECT_THAT(rv, IsOk());
8130 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8131 response = trans.GetResponseInfo();
8132 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588133 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:498134
David Benjamind61bd532019-04-23 21:11:378135 // Restart once more. The tunnel will be established and then the SSL
8136 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:498137 rv = callback.GetResult(
8138 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8139 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
8140}
8141
[email protected]ea9dc9a2009-09-05 00:43:328142#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:298143
[email protected]4ddaf2502008-10-23 18:26:198144// Test reading a server response which has only headers, and no body.
8145// After some maximum number of bytes is consumed, the transaction should
8146// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:018147TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:428148 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:198149 request.method = "GET";
bncce36dca22015-04-21 22:11:238150 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108151 request.traffic_annotation =
8152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:198153
danakj1fd259a02016-04-16 03:17:098154 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168155 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278156
[email protected]b75b7b2f2009-10-06 00:54:538157 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:438158 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:538159 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:198160
8161 MockRead data_reads[] = {
8162 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:068163 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:198164 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:068165 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:198166 };
Ryan Sleevib8d7ea02018-05-07 20:01:018167 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078168 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:198169
[email protected]49639fa2011-12-20 23:22:418170 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:198171
tfarina428341112016-09-22 13:38:208172 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018173 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:198174
8175 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018176 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:198177}
[email protected]f4e426b2008-11-05 00:24:498178
8179// Make sure that we don't try to reuse a TCPClientSocket when failing to
8180// establish tunnel.
8181// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:018182TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:278183 HttpRequestInfo request;
8184 request.method = "GET";
bncce36dca22015-04-21 22:11:238185 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108186 request.traffic_annotation =
8187 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278188
[email protected]f4e426b2008-11-05 00:24:498189 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:498190 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
8191 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:018192
danakj1fd259a02016-04-16 03:17:098193 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:498194
bnc87dcefc2017-05-25 12:47:588195 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198196 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:498197
[email protected]f4e426b2008-11-05 00:24:498198 // Since we have proxy, should try to establish tunnel.
8199 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:178200 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8201 "Host: www.example.org:443\r\n"
8202 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:498203 };
8204
[email protected]77848d12008-11-14 00:00:228205 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:498206 // connection. Usually a proxy would return 501 (not implemented),
8207 // or 200 (tunnel established).
8208 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:238209 MockRead("HTTP/1.1 404 Not Found\r\n"),
8210 MockRead("Content-Length: 10\r\n\r\n"),
8211 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:498212 };
8213
Ryan Sleevib8d7ea02018-05-07 20:01:018214 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078215 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:498216
[email protected]49639fa2011-12-20 23:22:418217 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:498218
tfarina428341112016-09-22 13:38:208219 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018220 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:498221
8222 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018223 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:498224
[email protected]b4404c02009-04-10 16:38:528225 // Empty the current queue. This is necessary because idle sockets are
8226 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558227 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528228
[email protected]f4e426b2008-11-05 00:24:498229 // We now check to make sure the TCPClientSocket was not added back to
8230 // the pool.
[email protected]90499482013-06-01 00:39:508231 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498232 trans.reset();
fdoray92e35a72016-06-10 15:54:558233 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:498234 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:508235 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498236}
[email protected]372d34a2008-11-05 21:30:518237
[email protected]1b157c02009-04-21 01:55:408238// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:018239TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:428240 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:408241 request.method = "GET";
bncce36dca22015-04-21 22:11:238242 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108243 request.traffic_annotation =
8244 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:408245
danakj1fd259a02016-04-16 03:17:098246 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278247
bnc691fda62016-08-12 00:43:168248 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278249
[email protected]1b157c02009-04-21 01:55:408250 MockRead data_reads[] = {
8251 // A part of the response body is received with the response headers.
8252 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8253 // The rest of the response body is received in two parts.
8254 MockRead("lo"),
8255 MockRead(" world"),
8256 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068257 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:408258 };
8259
Ryan Sleevib8d7ea02018-05-07 20:01:018260 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078261 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:408262
[email protected]49639fa2011-12-20 23:22:418263 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:408264
tfarina428341112016-09-22 13:38:208265 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018266 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:408267
8268 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018269 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408270
bnc691fda62016-08-12 00:43:168271 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528272 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:408273
wezca1070932016-05-26 20:30:528274 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:408275 std::string status_line = response->headers->GetStatusLine();
8276 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8277
[email protected]90499482013-06-01 00:39:508278 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408279
8280 std::string response_data;
bnc691fda62016-08-12 00:43:168281 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018282 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408283 EXPECT_EQ("hello world", response_data);
8284
8285 // Empty the current queue. This is necessary because idle sockets are
8286 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558287 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:408288
8289 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508290 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408291}
8292
[email protected]76a505b2010-08-25 06:23:008293// Make sure that we recycle a SSL socket after reading all of the response
8294// body.
bncd16676a2016-07-20 16:23:018295TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008296 HttpRequestInfo request;
8297 request.method = "GET";
bncce36dca22015-04-21 22:11:238298 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108299 request.traffic_annotation =
8300 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008301
8302 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238303 MockWrite(
8304 "GET / HTTP/1.1\r\n"
8305 "Host: www.example.org\r\n"
8306 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008307 };
8308
8309 MockRead data_reads[] = {
8310 MockRead("HTTP/1.1 200 OK\r\n"),
8311 MockRead("Content-Length: 11\r\n\r\n"),
8312 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068313 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008314 };
8315
[email protected]8ddf8322012-02-23 18:08:068316 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078317 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:008318
Ryan Sleevib8d7ea02018-05-07 20:01:018319 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078320 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008321
[email protected]49639fa2011-12-20 23:22:418322 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008323
danakj1fd259a02016-04-16 03:17:098324 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168325 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008326
tfarina428341112016-09-22 13:38:208327 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008328
robpercival214763f2016-07-01 23:27:018329 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8330 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008331
bnc691fda62016-08-12 00:43:168332 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528333 ASSERT_TRUE(response);
8334 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008335 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8336
[email protected]90499482013-06-01 00:39:508337 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008338
8339 std::string response_data;
bnc691fda62016-08-12 00:43:168340 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018341 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008342 EXPECT_EQ("hello world", response_data);
8343
8344 // Empty the current queue. This is necessary because idle sockets are
8345 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558346 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008347
8348 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238349 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008350}
8351
8352// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8353// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018354TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008355 HttpRequestInfo request;
8356 request.method = "GET";
bncce36dca22015-04-21 22:11:238357 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108358 request.traffic_annotation =
8359 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008360
8361 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238362 MockWrite(
8363 "GET / HTTP/1.1\r\n"
8364 "Host: www.example.org\r\n"
8365 "Connection: keep-alive\r\n\r\n"),
8366 MockWrite(
8367 "GET / HTTP/1.1\r\n"
8368 "Host: www.example.org\r\n"
8369 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008370 };
8371
8372 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428373 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8374 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008375
[email protected]8ddf8322012-02-23 18:08:068376 SSLSocketDataProvider ssl(ASYNC, OK);
8377 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078378 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8379 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008380
Ryan Sleevib8d7ea02018-05-07 20:01:018381 StaticSocketDataProvider data(data_reads, data_writes);
8382 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078383 session_deps_.socket_factory->AddSocketDataProvider(&data);
8384 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008385
[email protected]49639fa2011-12-20 23:22:418386 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008387
danakj1fd259a02016-04-16 03:17:098388 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588389 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198390 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008391
tfarina428341112016-09-22 13:38:208392 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008393
robpercival214763f2016-07-01 23:27:018394 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8395 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008396
8397 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528398 ASSERT_TRUE(response);
8399 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008400 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8401
[email protected]90499482013-06-01 00:39:508402 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008403
8404 std::string response_data;
8405 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018406 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008407 EXPECT_EQ("hello world", response_data);
8408
8409 // Empty the current queue. This is necessary because idle sockets are
8410 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558411 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008412
8413 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238414 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008415
8416 // Now start the second transaction, which should reuse the previous socket.
8417
bnc87dcefc2017-05-25 12:47:588418 trans =
Jeremy Roman0579ed62017-08-29 15:56:198419 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008420
tfarina428341112016-09-22 13:38:208421 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008422
robpercival214763f2016-07-01 23:27:018423 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8424 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008425
8426 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528427 ASSERT_TRUE(response);
8428 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008429 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8430
[email protected]90499482013-06-01 00:39:508431 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008432
8433 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018434 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008435 EXPECT_EQ("hello world", response_data);
8436
8437 // Empty the current queue. This is necessary because idle sockets are
8438 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558439 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008440
8441 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238442 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008443}
8444
maksim.sisov0adf8592016-07-15 06:25:568445// Grab a socket, use it, and put it back into the pool. Then, make
8446// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018447TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568448 HttpRequestInfo request;
8449 request.method = "GET";
8450 request.url = GURL("http://www.example.org/");
8451 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108452 request.traffic_annotation =
8453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568454
8455 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8456
bnc691fda62016-08-12 00:43:168457 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568458
8459 MockRead data_reads[] = {
8460 // A part of the response body is received with the response headers.
8461 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8462 // The rest of the response body is received in two parts.
8463 MockRead("lo"), MockRead(" world"),
8464 MockRead("junk"), // Should not be read!!
8465 MockRead(SYNCHRONOUS, OK),
8466 };
8467
Ryan Sleevib8d7ea02018-05-07 20:01:018468 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:568469 session_deps_.socket_factory->AddSocketDataProvider(&data);
8470
8471 TestCompletionCallback callback;
8472
tfarina428341112016-09-22 13:38:208473 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568474 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8475
8476 EXPECT_THAT(callback.GetResult(rv), IsOk());
8477
bnc691fda62016-08-12 00:43:168478 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568479 ASSERT_TRUE(response);
8480 EXPECT_TRUE(response->headers);
8481 std::string status_line = response->headers->GetStatusLine();
8482 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8483
8484 // Make memory critical notification and ensure the transaction still has been
8485 // operating right.
8486 base::MemoryPressureListener::NotifyMemoryPressure(
8487 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8488 base::RunLoop().RunUntilIdle();
8489
8490 // Socket should not be flushed as long as it is not idle.
8491 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8492
8493 std::string response_data;
bnc691fda62016-08-12 00:43:168494 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568495 EXPECT_THAT(rv, IsOk());
8496 EXPECT_EQ("hello world", response_data);
8497
8498 // Empty the current queue. This is necessary because idle sockets are
8499 // added to the connection pool asynchronously with a PostTask.
8500 base::RunLoop().RunUntilIdle();
8501
8502 // We now check to make sure the socket was added back to the pool.
8503 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8504
8505 // Idle sockets should be flushed now.
8506 base::MemoryPressureListener::NotifyMemoryPressure(
8507 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8508 base::RunLoop().RunUntilIdle();
8509
8510 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8511}
8512
yucliu48f235d2018-01-11 00:59:558513// Disable idle socket closing on memory pressure.
8514// Grab a socket, use it, and put it back into the pool. Then, make
8515// low memory notification and ensure the socket pool is NOT flushed.
8516TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
8517 HttpRequestInfo request;
8518 request.method = "GET";
8519 request.url = GURL("http://www.example.org/");
8520 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108521 request.traffic_annotation =
8522 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:558523
8524 // Disable idle socket closing on memory pressure.
8525 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
8526 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8527
8528 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8529
8530 MockRead data_reads[] = {
8531 // A part of the response body is received with the response headers.
8532 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8533 // The rest of the response body is received in two parts.
8534 MockRead("lo"), MockRead(" world"),
8535 MockRead("junk"), // Should not be read!!
8536 MockRead(SYNCHRONOUS, OK),
8537 };
8538
Ryan Sleevib8d7ea02018-05-07 20:01:018539 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:558540 session_deps_.socket_factory->AddSocketDataProvider(&data);
8541
8542 TestCompletionCallback callback;
8543
8544 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
8545 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8546
8547 EXPECT_THAT(callback.GetResult(rv), IsOk());
8548
8549 const HttpResponseInfo* response = trans.GetResponseInfo();
8550 ASSERT_TRUE(response);
8551 EXPECT_TRUE(response->headers);
8552 std::string status_line = response->headers->GetStatusLine();
8553 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8554
8555 // Make memory critical notification and ensure the transaction still has been
8556 // operating right.
8557 base::MemoryPressureListener::NotifyMemoryPressure(
8558 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8559 base::RunLoop().RunUntilIdle();
8560
8561 // Socket should not be flushed as long as it is not idle.
8562 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8563
8564 std::string response_data;
8565 rv = ReadTransaction(&trans, &response_data);
8566 EXPECT_THAT(rv, IsOk());
8567 EXPECT_EQ("hello world", response_data);
8568
8569 // Empty the current queue. This is necessary because idle sockets are
8570 // added to the connection pool asynchronously with a PostTask.
8571 base::RunLoop().RunUntilIdle();
8572
8573 // We now check to make sure the socket was added back to the pool.
8574 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8575
8576 // Idle sockets should NOT be flushed on moderate memory pressure.
8577 base::MemoryPressureListener::NotifyMemoryPressure(
8578 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
8579 base::RunLoop().RunUntilIdle();
8580
8581 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8582
8583 // Idle sockets should NOT be flushed on critical memory pressure.
8584 base::MemoryPressureListener::NotifyMemoryPressure(
8585 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8586 base::RunLoop().RunUntilIdle();
8587
8588 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8589}
8590
maksim.sisov0adf8592016-07-15 06:25:568591// Grab an SSL socket, use it, and put it back into the pool. Then, make
8592// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018593TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568594 HttpRequestInfo request;
8595 request.method = "GET";
8596 request.url = GURL("https://www.example.org/");
8597 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108598 request.traffic_annotation =
8599 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568600
8601 MockWrite data_writes[] = {
8602 MockWrite("GET / HTTP/1.1\r\n"
8603 "Host: www.example.org\r\n"
8604 "Connection: keep-alive\r\n\r\n"),
8605 };
8606
8607 MockRead data_reads[] = {
8608 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8609 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
8610
8611 SSLSocketDataProvider ssl(ASYNC, OK);
8612 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8613
Ryan Sleevib8d7ea02018-05-07 20:01:018614 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:568615 session_deps_.socket_factory->AddSocketDataProvider(&data);
8616
8617 TestCompletionCallback callback;
8618
8619 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168620 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568621
Matt Menke9d5e2c92019-02-05 01:42:238622 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina428341112016-09-22 13:38:208623 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568624
8625 EXPECT_THAT(callback.GetResult(rv), IsOk());
8626
bnc691fda62016-08-12 00:43:168627 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568628 ASSERT_TRUE(response);
8629 ASSERT_TRUE(response->headers);
8630 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8631
8632 // Make memory critical notification and ensure the transaction still has been
8633 // operating right.
8634 base::MemoryPressureListener::NotifyMemoryPressure(
8635 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8636 base::RunLoop().RunUntilIdle();
8637
Matt Menke9d5e2c92019-02-05 01:42:238638 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568639
8640 std::string response_data;
bnc691fda62016-08-12 00:43:168641 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568642 EXPECT_THAT(rv, IsOk());
8643 EXPECT_EQ("hello world", response_data);
8644
8645 // Empty the current queue. This is necessary because idle sockets are
8646 // added to the connection pool asynchronously with a PostTask.
8647 base::RunLoop().RunUntilIdle();
8648
8649 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238650 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568651
8652 // Make memory notification once again and ensure idle socket is closed.
8653 base::MemoryPressureListener::NotifyMemoryPressure(
8654 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8655 base::RunLoop().RunUntilIdle();
8656
Matt Menke9d5e2c92019-02-05 01:42:238657 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568658}
8659
[email protected]b4404c02009-04-10 16:38:528660// Make sure that we recycle a socket after a zero-length response.
8661// http://crbug.com/9880
bncd16676a2016-07-20 16:23:018662TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:428663 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:528664 request.method = "GET";
bncce36dca22015-04-21 22:11:238665 request.url = GURL(
8666 "http://www.example.org/csi?v=3&s=web&action=&"
8667 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
8668 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
8669 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e62018-02-07 07:41:108670 request.traffic_annotation =
8671 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:528672
danakj1fd259a02016-04-16 03:17:098673 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278674
[email protected]b4404c02009-04-10 16:38:528675 MockRead data_reads[] = {
8676 MockRead("HTTP/1.1 204 No Content\r\n"
8677 "Content-Length: 0\r\n"
8678 "Content-Type: text/html\r\n\r\n"),
8679 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068680 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:528681 };
8682
Ryan Sleevib8d7ea02018-05-07 20:01:018683 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078684 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:528685
mmenkecc2298e2015-12-07 18:20:188686 // Transaction must be created after the MockReads, so it's destroyed before
8687 // them.
bnc691fda62016-08-12 00:43:168688 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:188689
[email protected]49639fa2011-12-20 23:22:418690 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:528691
tfarina428341112016-09-22 13:38:208692 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018693 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:528694
8695 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018696 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528697
bnc691fda62016-08-12 00:43:168698 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528699 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:528700
wezca1070932016-05-26 20:30:528701 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:528702 std::string status_line = response->headers->GetStatusLine();
8703 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
8704
[email protected]90499482013-06-01 00:39:508705 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528706
8707 std::string response_data;
bnc691fda62016-08-12 00:43:168708 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018709 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528710 EXPECT_EQ("", response_data);
8711
8712 // Empty the current queue. This is necessary because idle sockets are
8713 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558714 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528715
8716 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508717 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528718}
8719
bncd16676a2016-07-20 16:23:018720TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:098721 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:228722 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:198723 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:228724 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:278725
[email protected]1c773ea12009-04-28 19:58:428726 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:518727 // Transaction 1: a GET request that succeeds. The socket is recycled
8728 // after use.
8729 request[0].method = "GET";
8730 request[0].url = GURL("http://www.google.com/");
8731 request[0].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108732 request[0].traffic_annotation =
8733 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518734 // Transaction 2: a POST request. Reuses the socket kept alive from
8735 // transaction 1. The first attempts fails when writing the POST data.
8736 // This causes the transaction to retry with a new socket. The second
8737 // attempt succeeds.
8738 request[1].method = "POST";
8739 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:278740 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:518741 request[1].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108742 request[1].traffic_annotation =
8743 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518744
danakj1fd259a02016-04-16 03:17:098745 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:518746
8747 // The first socket is used for transaction 1 and the first attempt of
8748 // transaction 2.
8749
8750 // The response of transaction 1.
8751 MockRead data_reads1[] = {
8752 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
8753 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068754 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518755 };
8756 // The mock write results of transaction 1 and the first attempt of
8757 // transaction 2.
8758 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:068759 MockWrite(SYNCHRONOUS, 64), // GET
8760 MockWrite(SYNCHRONOUS, 93), // POST
8761 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:518762 };
Ryan Sleevib8d7ea02018-05-07 20:01:018763 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:518764
8765 // The second socket is used for the second attempt of transaction 2.
8766
8767 // The response of transaction 2.
8768 MockRead data_reads2[] = {
8769 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
8770 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:068771 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518772 };
8773 // The mock write results of the second attempt of transaction 2.
8774 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:068775 MockWrite(SYNCHRONOUS, 93), // POST
8776 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:518777 };
Ryan Sleevib8d7ea02018-05-07 20:01:018778 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:518779
[email protected]bb88e1d32013-05-03 23:11:078780 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8781 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:518782
thestig9d3bb0c2015-01-24 00:49:518783 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:518784 "hello world", "welcome"
8785 };
8786
8787 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:168788 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:518789
[email protected]49639fa2011-12-20 23:22:418790 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:518791
tfarina428341112016-09-22 13:38:208792 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018793 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:518794
8795 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018796 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518797
bnc691fda62016-08-12 00:43:168798 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528799 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:518800
wezca1070932016-05-26 20:30:528801 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:518802 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8803
8804 std::string response_data;
bnc691fda62016-08-12 00:43:168805 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018806 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518807 EXPECT_EQ(kExpectedResponseData[i], response_data);
8808 }
8809}
[email protected]f9ee6b52008-11-08 06:46:238810
8811// Test the request-challenge-retry sequence for basic auth when there is
8812// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:168813// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:018814TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:428815 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238816 request.method = "GET";
bncce36dca22015-04-21 22:11:238817 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:418818 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108819 request.traffic_annotation =
8820 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:298821
danakj1fd259a02016-04-16 03:17:098822 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168823 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278824
[email protected]a97cca42009-08-14 01:00:298825 // The password contains an escaped character -- for this test to pass it
8826 // will need to be unescaped by HttpNetworkTransaction.
8827 EXPECT_EQ("b%40r", request.url.password());
8828
[email protected]f9ee6b52008-11-08 06:46:238829 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238830 MockWrite(
8831 "GET / HTTP/1.1\r\n"
8832 "Host: www.example.org\r\n"
8833 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238834 };
8835
8836 MockRead data_reads1[] = {
8837 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8838 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8839 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068840 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238841 };
8842
[email protected]2262e3a2012-05-22 16:08:168843 // After the challenge above, the transaction will be restarted using the
8844 // identity from the url (foo, b@r) to answer the challenge.
8845 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238846 MockWrite(
8847 "GET / HTTP/1.1\r\n"
8848 "Host: www.example.org\r\n"
8849 "Connection: keep-alive\r\n"
8850 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168851 };
8852
8853 MockRead data_reads2[] = {
8854 MockRead("HTTP/1.0 200 OK\r\n"),
8855 MockRead("Content-Length: 100\r\n\r\n"),
8856 MockRead(SYNCHRONOUS, OK),
8857 };
8858
Ryan Sleevib8d7ea02018-05-07 20:01:018859 StaticSocketDataProvider data1(data_reads1, data_writes1);
8860 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078861 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8862 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238863
[email protected]49639fa2011-12-20 23:22:418864 TestCompletionCallback callback1;
tfarina428341112016-09-22 13:38:208865 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018866 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238867 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018868 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168869 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168870
8871 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168872 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018873 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168874 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018875 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168876 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228877
bnc691fda62016-08-12 00:43:168878 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528879 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168880
8881 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:588882 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168883
8884 EXPECT_EQ(100, response->headers->GetContentLength());
8885
8886 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558887 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:168888}
8889
8890// Test the request-challenge-retry sequence for basic auth when there is an
8891// incorrect identity in the URL. The identity from the URL should be used only
8892// once.
bncd16676a2016-07-20 16:23:018893TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:168894 HttpRequestInfo request;
8895 request.method = "GET";
8896 // Note: the URL has a username:password in it. The password "baz" is
8897 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:238898 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:168899
8900 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108901 request.traffic_annotation =
8902 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:168903
danakj1fd259a02016-04-16 03:17:098904 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168905 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:168906
8907 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238908 MockWrite(
8909 "GET / HTTP/1.1\r\n"
8910 "Host: www.example.org\r\n"
8911 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168912 };
8913
8914 MockRead data_reads1[] = {
8915 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8916 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8917 MockRead("Content-Length: 10\r\n\r\n"),
8918 MockRead(SYNCHRONOUS, ERR_FAILED),
8919 };
8920
8921 // After the challenge above, the transaction will be restarted using the
8922 // identity from the url (foo, baz) to answer the challenge.
8923 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238924 MockWrite(
8925 "GET / HTTP/1.1\r\n"
8926 "Host: www.example.org\r\n"
8927 "Connection: keep-alive\r\n"
8928 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168929 };
8930
8931 MockRead data_reads2[] = {
8932 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8933 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8934 MockRead("Content-Length: 10\r\n\r\n"),
8935 MockRead(SYNCHRONOUS, ERR_FAILED),
8936 };
8937
8938 // After the challenge above, the transaction will be restarted using the
8939 // identity supplied by the user (foo, bar) to answer the challenge.
8940 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238941 MockWrite(
8942 "GET / HTTP/1.1\r\n"
8943 "Host: www.example.org\r\n"
8944 "Connection: keep-alive\r\n"
8945 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168946 };
8947
8948 MockRead data_reads3[] = {
8949 MockRead("HTTP/1.0 200 OK\r\n"),
8950 MockRead("Content-Length: 100\r\n\r\n"),
8951 MockRead(SYNCHRONOUS, OK),
8952 };
8953
Ryan Sleevib8d7ea02018-05-07 20:01:018954 StaticSocketDataProvider data1(data_reads1, data_writes1);
8955 StaticSocketDataProvider data2(data_reads2, data_writes2);
8956 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078957 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8958 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8959 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:168960
8961 TestCompletionCallback callback1;
8962
tfarina428341112016-09-22 13:38:208963 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018964 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168965
8966 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018967 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:168968
bnc691fda62016-08-12 00:43:168969 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168970 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168971 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018972 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168973 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018974 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168975 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168976
bnc691fda62016-08-12 00:43:168977 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528978 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588979 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:168980
8981 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168982 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018983 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168984 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018985 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168986 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168987
bnc691fda62016-08-12 00:43:168988 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528989 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168990
8991 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588992 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168993
8994 EXPECT_EQ(100, response->headers->GetContentLength());
8995
[email protected]ea9dc9a2009-09-05 00:43:328996 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558997 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:328998}
8999
[email protected]2217aa22013-10-11 03:03:549000
9001// Test the request-challenge-retry sequence for basic auth when there is a
9002// correct identity in the URL, but its use is being suppressed. The identity
9003// from the URL should never be used.
bncd16676a2016-07-20 16:23:019004TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:549005 HttpRequestInfo request;
9006 request.method = "GET";
bncce36dca22015-04-21 22:11:239007 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:549008 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e62018-02-07 07:41:109009 request.traffic_annotation =
9010 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:549011
danakj1fd259a02016-04-16 03:17:099012 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169013 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:549014
9015 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239016 MockWrite(
9017 "GET / HTTP/1.1\r\n"
9018 "Host: www.example.org\r\n"
9019 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549020 };
9021
9022 MockRead data_reads1[] = {
9023 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9024 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9025 MockRead("Content-Length: 10\r\n\r\n"),
9026 MockRead(SYNCHRONOUS, ERR_FAILED),
9027 };
9028
9029 // After the challenge above, the transaction will be restarted using the
9030 // identity supplied by the user, not the one in the URL, to answer the
9031 // challenge.
9032 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239033 MockWrite(
9034 "GET / HTTP/1.1\r\n"
9035 "Host: www.example.org\r\n"
9036 "Connection: keep-alive\r\n"
9037 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549038 };
9039
9040 MockRead data_reads3[] = {
9041 MockRead("HTTP/1.0 200 OK\r\n"),
9042 MockRead("Content-Length: 100\r\n\r\n"),
9043 MockRead(SYNCHRONOUS, OK),
9044 };
9045
Ryan Sleevib8d7ea02018-05-07 20:01:019046 StaticSocketDataProvider data1(data_reads1, data_writes1);
9047 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:549048 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9049 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9050
9051 TestCompletionCallback callback1;
tfarina428341112016-09-22 13:38:209052 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019053 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549054 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019055 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169056 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549057
bnc691fda62016-08-12 00:43:169058 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529059 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589060 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:549061
9062 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169063 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019064 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549065 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019066 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169067 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549068
bnc691fda62016-08-12 00:43:169069 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529070 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:549071
9072 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589073 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:549074 EXPECT_EQ(100, response->headers->GetContentLength());
9075
9076 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559077 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:549078}
9079
[email protected]f9ee6b52008-11-08 06:46:239080// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:019081TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:099082 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:239083
9084 // Transaction 1: authenticate (foo, bar) on MyRealm1
9085 {
[email protected]1c773ea12009-04-28 19:58:429086 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239087 request.method = "GET";
bncce36dca22015-04-21 22:11:239088 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:109089 request.traffic_annotation =
9090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239091
bnc691fda62016-08-12 00:43:169092 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279093
[email protected]f9ee6b52008-11-08 06:46:239094 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239095 MockWrite(
9096 "GET /x/y/z HTTP/1.1\r\n"
9097 "Host: www.example.org\r\n"
9098 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239099 };
9100
9101 MockRead data_reads1[] = {
9102 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9103 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9104 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069105 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239106 };
9107
9108 // Resend with authorization (username=foo, password=bar)
9109 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239110 MockWrite(
9111 "GET /x/y/z HTTP/1.1\r\n"
9112 "Host: www.example.org\r\n"
9113 "Connection: keep-alive\r\n"
9114 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239115 };
9116
9117 // Sever accepts the authorization.
9118 MockRead data_reads2[] = {
9119 MockRead("HTTP/1.0 200 OK\r\n"),
9120 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069121 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239122 };
9123
Ryan Sleevib8d7ea02018-05-07 20:01:019124 StaticSocketDataProvider data1(data_reads1, data_writes1);
9125 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079126 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9127 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239128
[email protected]49639fa2011-12-20 23:22:419129 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239130
tfarina428341112016-09-22 13:38:209131 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019132 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239133
9134 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019135 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239136
bnc691fda62016-08-12 00:43:169137 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529138 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589139 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239140
[email protected]49639fa2011-12-20 23:22:419141 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239142
bnc691fda62016-08-12 00:43:169143 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9144 callback2.callback());
robpercival214763f2016-07-01 23:27:019145 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239146
9147 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019148 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239149
bnc691fda62016-08-12 00:43:169150 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529151 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589152 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239153 EXPECT_EQ(100, response->headers->GetContentLength());
9154 }
9155
9156 // ------------------------------------------------------------------------
9157
9158 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
9159 {
[email protected]1c773ea12009-04-28 19:58:429160 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239161 request.method = "GET";
9162 // Note that Transaction 1 was at /x/y/z, so this is in the same
9163 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:239164 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109165 request.traffic_annotation =
9166 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239167
bnc691fda62016-08-12 00:43:169168 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279169
[email protected]f9ee6b52008-11-08 06:46:239170 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239171 MockWrite(
9172 "GET /x/y/a/b HTTP/1.1\r\n"
9173 "Host: www.example.org\r\n"
9174 "Connection: keep-alive\r\n"
9175 // Send preemptive authorization for MyRealm1
9176 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239177 };
9178
9179 // The server didn't like the preemptive authorization, and
9180 // challenges us for a different realm (MyRealm2).
9181 MockRead data_reads1[] = {
9182 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9183 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
9184 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069185 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239186 };
9187
9188 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
9189 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239190 MockWrite(
9191 "GET /x/y/a/b HTTP/1.1\r\n"
9192 "Host: www.example.org\r\n"
9193 "Connection: keep-alive\r\n"
9194 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239195 };
9196
9197 // Sever accepts the authorization.
9198 MockRead data_reads2[] = {
9199 MockRead("HTTP/1.0 200 OK\r\n"),
9200 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069201 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239202 };
9203
Ryan Sleevib8d7ea02018-05-07 20:01:019204 StaticSocketDataProvider data1(data_reads1, data_writes1);
9205 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079206 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9207 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239208
[email protected]49639fa2011-12-20 23:22:419209 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239210
tfarina428341112016-09-22 13:38:209211 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019212 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239213
9214 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019215 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239216
bnc691fda62016-08-12 00:43:169217 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529218 ASSERT_TRUE(response);
9219 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:049220 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:439221 EXPECT_EQ("http://www.example.org",
9222 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049223 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:199224 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:239225
[email protected]49639fa2011-12-20 23:22:419226 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239227
bnc691fda62016-08-12 00:43:169228 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
9229 callback2.callback());
robpercival214763f2016-07-01 23:27:019230 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239231
9232 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019233 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239234
bnc691fda62016-08-12 00:43:169235 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529236 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589237 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239238 EXPECT_EQ(100, response->headers->GetContentLength());
9239 }
9240
9241 // ------------------------------------------------------------------------
9242
9243 // Transaction 3: Resend a request in MyRealm's protection space --
9244 // succeed with preemptive authorization.
9245 {
[email protected]1c773ea12009-04-28 19:58:429246 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239247 request.method = "GET";
bncce36dca22015-04-21 22:11:239248 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e62018-02-07 07:41:109249 request.traffic_annotation =
9250 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239251
bnc691fda62016-08-12 00:43:169252 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279253
[email protected]f9ee6b52008-11-08 06:46:239254 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239255 MockWrite(
9256 "GET /x/y/z2 HTTP/1.1\r\n"
9257 "Host: www.example.org\r\n"
9258 "Connection: keep-alive\r\n"
9259 // The authorization for MyRealm1 gets sent preemptively
9260 // (since the url is in the same protection space)
9261 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239262 };
9263
9264 // Sever accepts the preemptive authorization
9265 MockRead data_reads1[] = {
9266 MockRead("HTTP/1.0 200 OK\r\n"),
9267 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069268 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239269 };
9270
Ryan Sleevib8d7ea02018-05-07 20:01:019271 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079272 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:239273
[email protected]49639fa2011-12-20 23:22:419274 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239275
tfarina428341112016-09-22 13:38:209276 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019277 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239278
9279 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019280 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239281
bnc691fda62016-08-12 00:43:169282 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529283 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:239284
Emily Starkf2c9bbd2019-04-09 17:08:589285 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239286 EXPECT_EQ(100, response->headers->GetContentLength());
9287 }
9288
9289 // ------------------------------------------------------------------------
9290
9291 // Transaction 4: request another URL in MyRealm (however the
9292 // url is not known to belong to the protection space, so no pre-auth).
9293 {
[email protected]1c773ea12009-04-28 19:58:429294 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239295 request.method = "GET";
bncce36dca22015-04-21 22:11:239296 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e62018-02-07 07:41:109297 request.traffic_annotation =
9298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239299
bnc691fda62016-08-12 00:43:169300 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279301
[email protected]f9ee6b52008-11-08 06:46:239302 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239303 MockWrite(
9304 "GET /x/1 HTTP/1.1\r\n"
9305 "Host: www.example.org\r\n"
9306 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239307 };
9308
9309 MockRead data_reads1[] = {
9310 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9311 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9312 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069313 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239314 };
9315
9316 // Resend with authorization from MyRealm's cache.
9317 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239318 MockWrite(
9319 "GET /x/1 HTTP/1.1\r\n"
9320 "Host: www.example.org\r\n"
9321 "Connection: keep-alive\r\n"
9322 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239323 };
9324
9325 // Sever accepts the authorization.
9326 MockRead data_reads2[] = {
9327 MockRead("HTTP/1.0 200 OK\r\n"),
9328 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069329 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239330 };
9331
Ryan Sleevib8d7ea02018-05-07 20:01:019332 StaticSocketDataProvider data1(data_reads1, data_writes1);
9333 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079334 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9335 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239336
[email protected]49639fa2011-12-20 23:22:419337 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239338
tfarina428341112016-09-22 13:38:209339 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019340 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239341
9342 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019343 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239344
bnc691fda62016-08-12 00:43:169345 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419346 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169347 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019348 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229349 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019350 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169351 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229352
bnc691fda62016-08-12 00:43:169353 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529354 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589355 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239356 EXPECT_EQ(100, response->headers->GetContentLength());
9357 }
9358
9359 // ------------------------------------------------------------------------
9360
9361 // Transaction 5: request a URL in MyRealm, but the server rejects the
9362 // cached identity. Should invalidate and re-prompt.
9363 {
[email protected]1c773ea12009-04-28 19:58:429364 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239365 request.method = "GET";
bncce36dca22015-04-21 22:11:239366 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e62018-02-07 07:41:109367 request.traffic_annotation =
9368 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239369
bnc691fda62016-08-12 00:43:169370 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279371
[email protected]f9ee6b52008-11-08 06:46:239372 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239373 MockWrite(
9374 "GET /p/q/t HTTP/1.1\r\n"
9375 "Host: www.example.org\r\n"
9376 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239377 };
9378
9379 MockRead data_reads1[] = {
9380 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9381 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9382 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069383 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239384 };
9385
9386 // Resend with authorization from cache for MyRealm.
9387 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239388 MockWrite(
9389 "GET /p/q/t HTTP/1.1\r\n"
9390 "Host: www.example.org\r\n"
9391 "Connection: keep-alive\r\n"
9392 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239393 };
9394
9395 // Sever rejects the authorization.
9396 MockRead data_reads2[] = {
9397 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9398 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9399 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069400 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239401 };
9402
9403 // At this point we should prompt for new credentials for MyRealm.
9404 // Restart with username=foo3, password=foo4.
9405 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239406 MockWrite(
9407 "GET /p/q/t HTTP/1.1\r\n"
9408 "Host: www.example.org\r\n"
9409 "Connection: keep-alive\r\n"
9410 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239411 };
9412
9413 // Sever accepts the authorization.
9414 MockRead data_reads3[] = {
9415 MockRead("HTTP/1.0 200 OK\r\n"),
9416 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069417 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239418 };
9419
Ryan Sleevib8d7ea02018-05-07 20:01:019420 StaticSocketDataProvider data1(data_reads1, data_writes1);
9421 StaticSocketDataProvider data2(data_reads2, data_writes2);
9422 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079423 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9424 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9425 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239426
[email protected]49639fa2011-12-20 23:22:419427 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239428
tfarina428341112016-09-22 13:38:209429 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019430 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239431
9432 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019433 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239434
bnc691fda62016-08-12 00:43:169435 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419436 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169437 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019438 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229439 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019440 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169441 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229442
bnc691fda62016-08-12 00:43:169443 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529444 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589445 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239446
[email protected]49639fa2011-12-20 23:22:419447 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239448
bnc691fda62016-08-12 00:43:169449 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9450 callback3.callback());
robpercival214763f2016-07-01 23:27:019451 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239452
[email protected]0757e7702009-03-27 04:00:229453 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019454 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239455
bnc691fda62016-08-12 00:43:169456 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529457 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589458 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239459 EXPECT_EQ(100, response->headers->GetContentLength());
9460 }
9461}
[email protected]89ceba9a2009-03-21 03:46:069462
[email protected]3c32c5f2010-05-18 15:18:129463// Tests that nonce count increments when multiple auth attempts
9464// are started with the same nonce.
bncd16676a2016-07-20 16:23:019465TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:449466 HttpAuthHandlerDigest::Factory* digest_factory =
9467 new HttpAuthHandlerDigest::Factory();
9468 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
9469 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
9470 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:079471 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:099472 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:129473
9474 // Transaction 1: authenticate (foo, bar) on MyRealm1
9475 {
[email protected]3c32c5f2010-05-18 15:18:129476 HttpRequestInfo request;
9477 request.method = "GET";
bncce36dca22015-04-21 22:11:239478 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:109479 request.traffic_annotation =
9480 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129481
bnc691fda62016-08-12 00:43:169482 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279483
[email protected]3c32c5f2010-05-18 15:18:129484 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239485 MockWrite(
9486 "GET /x/y/z HTTP/1.1\r\n"
9487 "Host: www.example.org\r\n"
9488 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129489 };
9490
9491 MockRead data_reads1[] = {
9492 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9493 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
9494 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069495 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129496 };
9497
9498 // Resend with authorization (username=foo, password=bar)
9499 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239500 MockWrite(
9501 "GET /x/y/z HTTP/1.1\r\n"
9502 "Host: www.example.org\r\n"
9503 "Connection: keep-alive\r\n"
9504 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9505 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
9506 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
9507 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129508 };
9509
9510 // Sever accepts the authorization.
9511 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:089512 MockRead("HTTP/1.0 200 OK\r\n"),
9513 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129514 };
9515
Ryan Sleevib8d7ea02018-05-07 20:01:019516 StaticSocketDataProvider data1(data_reads1, data_writes1);
9517 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079518 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9519 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:129520
[email protected]49639fa2011-12-20 23:22:419521 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129522
tfarina428341112016-09-22 13:38:209523 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019524 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129525
9526 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019527 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129528
bnc691fda62016-08-12 00:43:169529 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529530 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589531 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:129532
[email protected]49639fa2011-12-20 23:22:419533 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:129534
bnc691fda62016-08-12 00:43:169535 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9536 callback2.callback());
robpercival214763f2016-07-01 23:27:019537 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129538
9539 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019540 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129541
bnc691fda62016-08-12 00:43:169542 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529543 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589544 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129545 }
9546
9547 // ------------------------------------------------------------------------
9548
9549 // Transaction 2: Request another resource in digestive's protection space.
9550 // This will preemptively add an Authorization header which should have an
9551 // "nc" value of 2 (as compared to 1 in the first use.
9552 {
[email protected]3c32c5f2010-05-18 15:18:129553 HttpRequestInfo request;
9554 request.method = "GET";
9555 // Note that Transaction 1 was at /x/y/z, so this is in the same
9556 // protection space as digest.
bncce36dca22015-04-21 22:11:239557 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109558 request.traffic_annotation =
9559 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129560
bnc691fda62016-08-12 00:43:169561 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279562
[email protected]3c32c5f2010-05-18 15:18:129563 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239564 MockWrite(
9565 "GET /x/y/a/b HTTP/1.1\r\n"
9566 "Host: www.example.org\r\n"
9567 "Connection: keep-alive\r\n"
9568 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9569 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
9570 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
9571 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129572 };
9573
9574 // Sever accepts the authorization.
9575 MockRead data_reads1[] = {
9576 MockRead("HTTP/1.0 200 OK\r\n"),
9577 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069578 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129579 };
9580
Ryan Sleevib8d7ea02018-05-07 20:01:019581 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079582 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:129583
[email protected]49639fa2011-12-20 23:22:419584 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129585
tfarina428341112016-09-22 13:38:209586 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019587 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129588
9589 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019590 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129591
bnc691fda62016-08-12 00:43:169592 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529593 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589594 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129595 }
9596}
9597
[email protected]89ceba9a2009-03-21 03:46:069598// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:019599TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:069600 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:099601 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169602 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:069603
9604 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:449605 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:169606 trans.read_buf_len_ = 15;
9607 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:069608
9609 // Setup state in response_
bnc691fda62016-08-12 00:43:169610 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:589611 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:089612 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:579613 response->response_time = base::Time::Now();
9614 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:069615
9616 { // Setup state for response_.vary_data
9617 HttpRequestInfo request;
9618 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
9619 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:279620 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:439621 request.extra_headers.SetHeader("Foo", "1");
9622 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:509623 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:069624 }
9625
9626 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:169627 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:069628
9629 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:169630 EXPECT_FALSE(trans.read_buf_);
9631 EXPECT_EQ(0, trans.read_buf_len_);
9632 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:589633 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:529634 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:049635 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:089636 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:579637 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:069638}
9639
[email protected]bacff652009-03-31 17:50:339640// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:019641TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:339642 HttpRequestInfo request;
9643 request.method = "GET";
bncce36dca22015-04-21 22:11:239644 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109645 request.traffic_annotation =
9646 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339647
danakj1fd259a02016-04-16 03:17:099648 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169649 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279650
[email protected]bacff652009-03-31 17:50:339651 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239652 MockWrite(
9653 "GET / HTTP/1.1\r\n"
9654 "Host: www.example.org\r\n"
9655 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339656 };
9657
9658 MockRead data_reads[] = {
9659 MockRead("HTTP/1.0 200 OK\r\n"),
9660 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9661 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069662 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339663 };
9664
[email protected]5ecc992a42009-11-11 01:41:599665 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:019666 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069667 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9668 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339669
[email protected]bb88e1d32013-05-03 23:11:079670 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9671 session_deps_.socket_factory->AddSocketDataProvider(&data);
9672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9673 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339674
[email protected]49639fa2011-12-20 23:22:419675 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339676
tfarina428341112016-09-22 13:38:209677 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019678 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339679
9680 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019681 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339682
bnc691fda62016-08-12 00:43:169683 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019684 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339685
9686 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019687 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339688
bnc691fda62016-08-12 00:43:169689 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339690
wezca1070932016-05-26 20:30:529691 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339692 EXPECT_EQ(100, response->headers->GetContentLength());
9693}
9694
9695// Test HTTPS connections to a site with a bad certificate, going through a
9696// proxy
bncd16676a2016-07-20 16:23:019697TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499698 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9699 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339700
9701 HttpRequestInfo request;
9702 request.method = "GET";
bncce36dca22015-04-21 22:11:239703 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109704 request.traffic_annotation =
9705 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339706
9707 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:179708 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9709 "Host: www.example.org:443\r\n"
9710 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339711 };
9712
9713 MockRead proxy_reads[] = {
9714 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069715 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:339716 };
9717
9718 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179719 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9720 "Host: www.example.org:443\r\n"
9721 "Proxy-Connection: keep-alive\r\n\r\n"),
9722 MockWrite("GET / HTTP/1.1\r\n"
9723 "Host: www.example.org\r\n"
9724 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339725 };
9726
9727 MockRead data_reads[] = {
9728 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9729 MockRead("HTTP/1.0 200 OK\r\n"),
9730 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9731 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069732 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339733 };
9734
Ryan Sleevib8d7ea02018-05-07 20:01:019735 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
9736 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069737 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9738 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339739
[email protected]bb88e1d32013-05-03 23:11:079740 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9741 session_deps_.socket_factory->AddSocketDataProvider(&data);
9742 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9743 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339744
[email protected]49639fa2011-12-20 23:22:419745 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339746
9747 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:079748 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:339749
danakj1fd259a02016-04-16 03:17:099750 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169751 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:339752
tfarina428341112016-09-22 13:38:209753 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019754 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339755
9756 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019757 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339758
bnc691fda62016-08-12 00:43:169759 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019760 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339761
9762 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019763 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339764
bnc691fda62016-08-12 00:43:169765 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339766
wezca1070932016-05-26 20:30:529767 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339768 EXPECT_EQ(100, response->headers->GetContentLength());
9769 }
9770}
9771
[email protected]2df19bb2010-08-25 20:13:469772
9773// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:019774TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599775 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499776 ProxyResolutionService::CreateFixedFromPacResult(
9777 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519778 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079779 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:469780
9781 HttpRequestInfo request;
9782 request.method = "GET";
bncce36dca22015-04-21 22:11:239783 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109784 request.traffic_annotation =
9785 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:469786
9787 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179788 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9789 "Host: www.example.org:443\r\n"
9790 "Proxy-Connection: keep-alive\r\n\r\n"),
9791 MockWrite("GET / HTTP/1.1\r\n"
9792 "Host: www.example.org\r\n"
9793 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:469794 };
9795
9796 MockRead data_reads[] = {
9797 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9798 MockRead("HTTP/1.1 200 OK\r\n"),
9799 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9800 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069801 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:469802 };
9803
Ryan Sleevib8d7ea02018-05-07 20:01:019804 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069805 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9806 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:469807
[email protected]bb88e1d32013-05-03 23:11:079808 session_deps_.socket_factory->AddSocketDataProvider(&data);
9809 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9810 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:469811
[email protected]49639fa2011-12-20 23:22:419812 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:469813
danakj1fd259a02016-04-16 03:17:099814 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169815 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:469816
tfarina428341112016-09-22 13:38:209817 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019818 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:469819
9820 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019821 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169822 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:469823
wezca1070932016-05-26 20:30:529824 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:469825
tbansal2ecbbc72016-10-06 17:15:479826 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:469827 EXPECT_TRUE(response->headers->IsKeepAlive());
9828 EXPECT_EQ(200, response->headers->response_code());
9829 EXPECT_EQ(100, response->headers->GetContentLength());
9830 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:209831
9832 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:169833 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:209834 TestLoadTimingNotReusedWithPac(load_timing_info,
9835 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:469836}
9837
Eric Roman695a7872019-04-16 21:53:299838// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:019839TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599840 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499841 ProxyResolutionService::CreateFixedFromPacResult(
9842 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519843 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079844 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:299845
Matt Menkeecfecfc72019-02-05 19:15:289846 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9847 session_deps_.host_resolver->set_ondemand_mode(true);
9848
[email protected]511f6f52010-12-17 03:58:299849 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:129850 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:299851 request.method = "GET";
bncce36dca22015-04-21 22:11:239852 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109853 request.traffic_annotation =
9854 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299855
9856 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:289857 MockWrite(ASYNC, 0,
9858 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:179859 "Host: www.example.org:443\r\n"
9860 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299861 };
9862
9863 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289864 // Pause on first read.
9865 MockRead(ASYNC, ERR_IO_PENDING, 1),
9866 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
9867 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
9868 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299869 };
9870
Matt Menkeecfecfc72019-02-05 19:15:289871 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069872 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299873
[email protected]bb88e1d32013-05-03 23:11:079874 session_deps_.socket_factory->AddSocketDataProvider(&data);
9875 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299876
[email protected]49639fa2011-12-20 23:22:419877 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299878
danakj1fd259a02016-04-16 03:17:099879 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169880 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299881
tfarina428341112016-09-22 13:38:209882 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019883 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289884 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
9885
9886 // Host resolution takes |kTimeIncrement|.
9887 FastForwardBy(kTimeIncrement);
9888 // Resolving the current request with |ResolveNow| will cause the pending
9889 // request to instantly complete, and the async connect will start as well.
9890 session_deps_.host_resolver->ResolveOnlyRequestNow();
9891
9892 // Connecting takes |kTimeIncrement|.
9893 FastForwardBy(kTimeIncrement);
9894 data.RunUntilPaused();
9895
9896 // The server takes |kTimeIncrement| to respond.
9897 FastForwardBy(kTimeIncrement);
9898 data.Resume();
[email protected]511f6f52010-12-17 03:58:299899
9900 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599901 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299902}
9903
Eric Roman74103c72019-02-21 00:23:129904// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
9905TEST_F(HttpNetworkTransactionTest,
9906 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
9907 base::HistogramTester histograms;
9908 session_deps_.proxy_resolution_service =
9909 ProxyResolutionService::CreateFixedFromPacResult(
9910 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9911 TestNetLog net_log;
9912 session_deps_.net_log = &net_log;
9913
9914 HttpRequestInfo request;
9915 request.method = "GET";
9916 request.url = GURL("https://www.example.org/");
9917 request.traffic_annotation =
9918 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9919
9920 MockWrite data_writes[] = {
9921 MockWrite(ASYNC, 0,
9922 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9923 "Host: www.example.org:443\r\n"
9924 "Proxy-Connection: keep-alive\r\n\r\n"),
9925 };
9926
9927 MockRead data_reads[] = {
9928 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9929 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9930 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9931 };
9932
9933 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9934 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9935
9936 session_deps_.socket_factory->AddSocketDataProvider(&data);
9937 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9938
9939 TestCompletionCallback callback;
9940
9941 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9942 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9943
9944 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9945 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9946
9947 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599948 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129949}
9950
9951// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
9952// request for main frames.
9953TEST_F(HttpNetworkTransactionTest,
9954 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
9955 base::HistogramTester histograms;
9956 session_deps_.proxy_resolution_service =
9957 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
9958 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9959 TestNetLog net_log;
9960 session_deps_.net_log = &net_log;
9961
9962 HttpRequestInfo request;
9963 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
9964 request.method = "GET";
9965 request.url = GURL("https://www.example.org/");
9966 request.traffic_annotation =
9967 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9968
9969 MockWrite data_writes[] = {
9970 MockWrite(ASYNC, 0,
9971 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9972 "Host: www.example.org:443\r\n"
9973 "Proxy-Connection: keep-alive\r\n\r\n"),
9974 };
9975
9976 MockRead data_reads[] = {
9977 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9978 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9979 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9980 };
9981
9982 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9983 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9984
9985 session_deps_.socket_factory->AddSocketDataProvider(&data);
9986 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9987
9988 TestCompletionCallback callback;
9989
9990 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9991 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9992
9993 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9994 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9995
9996 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599997 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129998}
9999
Eric Roman695a7872019-04-16 21:53:2910000// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:1210001// frames.
bncd16676a2016-07-20 16:23:0110002TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:1210003 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:4910004 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10005 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:2810006 TestNetLog net_log;
10007 session_deps_.net_log = &net_log;
10008
Matt Menkeecfecfc72019-02-05 19:15:2810009 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10010 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:2910011
10012 HttpRequestInfo request;
10013 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:1210014 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:2310015 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010016 request.traffic_annotation =
10017 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910018
Ryan Hamilton0239aac2018-05-19 00:03:1310019 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410020 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10021 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310022 spdy::SpdySerializedFrame goaway(
10023 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910024 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110025 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:2810026 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:2910027 };
10028
10029 static const char* const kExtraHeaders[] = {
10030 "location",
10031 "http://login.example.com/",
10032 };
Ryan Hamilton0239aac2018-05-19 00:03:1310033 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410034 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:2910035 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810036 // Pause on first read.
10037 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
10038 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910039 };
10040
Matt Menkeecfecfc72019-02-05 19:15:2810041 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610042 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610043 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910044
[email protected]bb88e1d32013-05-03 23:11:0710045 session_deps_.socket_factory->AddSocketDataProvider(&data);
10046 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910047
[email protected]49639fa2011-12-20 23:22:4110048 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910049
danakj1fd259a02016-04-16 03:17:0910050 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610051 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910052
tfarina428341112016-09-22 13:38:2010053 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810055 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:2910056
Matt Menkeecfecfc72019-02-05 19:15:2810057 // Host resolution takes |kTimeIncrement|.
10058 FastForwardBy(kTimeIncrement);
10059 // Resolving the current request with |ResolveNow| will cause the pending
10060 // request to instantly complete, and the async connect will start as well.
10061 session_deps_.host_resolver->ResolveOnlyRequestNow();
10062
10063 // Connecting takes |kTimeIncrement|.
10064 FastForwardBy(kTimeIncrement);
10065 data.RunUntilPaused();
10066
10067 FastForwardBy(kTimeIncrement);
10068 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910069 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910070 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910071}
10072
[email protected]4eddbc732012-08-09 05:40:1710073// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110074TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910075 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10076 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910077
10078 HttpRequestInfo request;
10079 request.method = "GET";
bncce36dca22015-04-21 22:11:2310080 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010081 request.traffic_annotation =
10082 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910083
10084 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710085 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10086 "Host: www.example.org:443\r\n"
10087 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910088 };
10089
10090 MockRead data_reads[] = {
10091 MockRead("HTTP/1.1 404 Not Found\r\n"),
10092 MockRead("Content-Length: 23\r\n\r\n"),
10093 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:0610094 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:2910095 };
10096
Ryan Sleevib8d7ea02018-05-07 20:01:0110097 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610098 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910099
[email protected]bb88e1d32013-05-03 23:11:0710100 session_deps_.socket_factory->AddSocketDataProvider(&data);
10101 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910102
[email protected]49639fa2011-12-20 23:22:4110103 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910104
danakj1fd259a02016-04-16 03:17:0910105 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610106 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910107
tfarina428341112016-09-22 13:38:2010108 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110109 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910110
10111 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110112 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910113
ttuttle960fcbf2016-04-19 13:26:3210114 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910115}
10116
[email protected]4eddbc732012-08-09 05:40:1710117// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110118TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910119 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10120 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910121
10122 HttpRequestInfo request;
10123 request.method = "GET";
bncce36dca22015-04-21 22:11:2310124 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010125 request.traffic_annotation =
10126 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910127
Ryan Hamilton0239aac2018-05-19 00:03:1310128 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410129 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10130 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310131 spdy::SpdySerializedFrame rst(
10132 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910133 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110134 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:2910135 };
10136
10137 static const char* const kExtraHeaders[] = {
10138 "location",
10139 "http://login.example.com/",
10140 };
Ryan Hamilton0239aac2018-05-19 00:03:1310141 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410142 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1310143 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:1910144 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:2910145 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110146 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1310147 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910148 };
10149
Ryan Sleevib8d7ea02018-05-07 20:01:0110150 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610151 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610152 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910153
[email protected]bb88e1d32013-05-03 23:11:0710154 session_deps_.socket_factory->AddSocketDataProvider(&data);
10155 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910156
[email protected]49639fa2011-12-20 23:22:4110157 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910158
danakj1fd259a02016-04-16 03:17:0910159 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610160 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910161
tfarina428341112016-09-22 13:38:2010162 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110163 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910164
10165 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110166 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910167
ttuttle960fcbf2016-04-19 13:26:3210168 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910169}
10170
[email protected]0c5fb722012-02-28 11:50:3510171// Test the request-challenge-retry sequence for basic auth, through
10172// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0110173TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3510174 HttpRequestInfo request;
10175 request.method = "GET";
bncce36dca22015-04-21 22:11:2310176 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3510177 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:2910178 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:1010179 request.traffic_annotation =
10180 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3510181
10182 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5910183 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910184 ProxyResolutionService::CreateFixedFromPacResult(
10185 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110186 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710187 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0910188 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3510189
10190 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1310191 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410192 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10193 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310194 spdy::SpdySerializedFrame rst(
10195 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3810196 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3510197
bnc691fda62016-08-12 00:43:1610198 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3510199 // be issuing -- the final header line contains the credentials.
10200 const char* const kAuthCredentials[] = {
10201 "proxy-authorization", "Basic Zm9vOmJhcg==",
10202 };
Ryan Hamilton0239aac2018-05-19 00:03:1310203 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410204 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
10205 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2310206 HostPortPair("www.example.org", 443)));
10207 // fetch https://www.example.org/ via HTTP
10208 const char get[] =
10209 "GET / HTTP/1.1\r\n"
10210 "Host: www.example.org\r\n"
10211 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1310212 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1910213 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3510214
10215 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110216 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
10217 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3510218 };
10219
10220 // The proxy responds to the connect with a 407, using a persistent
10221 // connection.
thestig9d3bb0c2015-01-24 00:49:5110222 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3510223 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3510224 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
10225 };
Ryan Hamilton0239aac2018-05-19 00:03:1310226 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410227 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3510228
Ryan Hamilton0239aac2018-05-19 00:03:1310229 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3510230 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3510231 const char resp[] = "HTTP/1.1 200 OK\r\n"
10232 "Content-Length: 5\r\n\r\n";
10233
Ryan Hamilton0239aac2018-05-19 00:03:1310234 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1910235 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1310236 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1910237 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3510238 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110239 CreateMockRead(conn_auth_resp, 1, ASYNC),
10240 CreateMockRead(conn_resp, 4, ASYNC),
10241 CreateMockRead(wrapped_get_resp, 6, ASYNC),
10242 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1310243 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3510244 };
10245
Ryan Sleevib8d7ea02018-05-07 20:01:0110246 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710247 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3510248 // Negotiate SPDY to the proxy
10249 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610250 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710251 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3510252 // Vanilla SSL to the server
10253 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710254 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3510255
10256 TestCompletionCallback callback1;
10257
bnc87dcefc2017-05-25 12:47:5810258 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910259 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3510260
10261 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110262 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510263
10264 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110265 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5410266 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3510267 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0010268 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10269 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510270 ExpectLogContainsSomewhere(
10271 entries, pos,
mikecirone8b85c432016-09-08 19:11:0010272 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10273 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510274
10275 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210276 ASSERT_TRUE(response);
10277 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3510278 EXPECT_EQ(407, response->headers->response_code());
10279 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5810280 EXPECT_TRUE(response->auth_challenge.has_value());
10281 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3510282
10283 TestCompletionCallback callback2;
10284
10285 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
10286 callback2.callback());
robpercival214763f2016-07-01 23:27:0110287 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510288
10289 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110290 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3510291
10292 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210293 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3510294
10295 EXPECT_TRUE(response->headers->IsKeepAlive());
10296 EXPECT_EQ(200, response->headers->response_code());
10297 EXPECT_EQ(5, response->headers->GetContentLength());
10298 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10299
10300 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810301 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510302
[email protected]029c83b62013-01-24 05:28:2010303 LoadTimingInfo load_timing_info;
10304 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10305 TestLoadTimingNotReusedWithPac(load_timing_info,
10306 CONNECT_TIMING_HAS_SSL_TIMES);
10307
[email protected]0c5fb722012-02-28 11:50:3510308 trans.reset();
10309 session->CloseAllConnections();
10310}
10311
[email protected]7c6f7ba2012-04-03 04:09:2910312// Test that an explicitly trusted SPDY proxy can push a resource from an
10313// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0110314TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1510315 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910316 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510317 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10318 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2910319 HttpRequestInfo request;
10320 HttpRequestInfo push_request;
Ramin Halavatib5e433e62018-02-07 07:41:1010321 request.traffic_annotation =
10322 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910323
[email protected]7c6f7ba2012-04-03 04:09:2910324 request.method = "GET";
bncce36dca22015-04-21 22:11:2310325 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910326 push_request.method = "GET";
10327 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e62018-02-07 07:41:1010328 push_request.traffic_annotation =
10329 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910330
tbansal28e68f82016-02-04 02:56:1510331 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910332 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910333 ProxyResolutionService::CreateFixedFromPacResult(
10334 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110335 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710336 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010337
Eric Roman3d8546a2018-09-10 17:00:5210338 session_deps_.proxy_resolution_service->SetProxyDelegate(
10339 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010340
danakj1fd259a02016-04-16 03:17:0910341 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910342
Ryan Hamilton0239aac2018-05-19 00:03:1310343 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510344 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310345 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510346 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910347
10348 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110349 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510350 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910351 };
10352
Ryan Hamilton0239aac2018-05-19 00:03:1310353 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510354 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610355
Ryan Hamilton0239aac2018-05-19 00:03:1310356 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510357 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910358
Ryan Hamilton0239aac2018-05-19 00:03:1310359 spdy::SpdySerializedFrame stream1_body(
10360 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910361
Ryan Hamilton0239aac2018-05-19 00:03:1310362 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910363 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910364
10365 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610366 CreateMockRead(stream2_syn, 1, ASYNC),
10367 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510368 CreateMockRead(stream1_body, 4, ASYNC),
10369 CreateMockRead(stream2_body, 5, ASYNC),
10370 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910371 };
10372
Ryan Sleevib8d7ea02018-05-07 20:01:0110373 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710374 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910375 // Negotiate SPDY to the proxy
10376 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610377 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710378 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910379
bnc87dcefc2017-05-25 12:47:5810380 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910381 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910382 TestCompletionCallback callback;
10383 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110384 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910385
10386 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110387 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910388 const HttpResponseInfo* response = trans->GetResponseInfo();
10389
bnc87dcefc2017-05-25 12:47:5810390 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910391 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010392 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110393 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910394
10395 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110396 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910397 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10398
wezca1070932016-05-26 20:30:5210399 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910400 EXPECT_TRUE(response->headers->IsKeepAlive());
10401
10402 EXPECT_EQ(200, response->headers->response_code());
10403 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10404
10405 std::string response_data;
10406 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110407 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910408 EXPECT_EQ("hello!", response_data);
10409
[email protected]029c83b62013-01-24 05:28:2010410 LoadTimingInfo load_timing_info;
10411 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10412 TestLoadTimingNotReusedWithPac(load_timing_info,
10413 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10414
[email protected]7c6f7ba2012-04-03 04:09:2910415 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210416 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910417 EXPECT_EQ(200, push_response->headers->response_code());
10418
10419 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110420 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910421 EXPECT_EQ("pushed", response_data);
10422
[email protected]029c83b62013-01-24 05:28:2010423 LoadTimingInfo push_load_timing_info;
10424 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10425 TestLoadTimingReusedWithPac(push_load_timing_info);
10426 // The transactions should share a socket ID, despite being for different
10427 // origins.
10428 EXPECT_EQ(load_timing_info.socket_log_id,
10429 push_load_timing_info.socket_log_id);
10430
[email protected]7c6f7ba2012-04-03 04:09:2910431 trans.reset();
10432 push_trans.reset();
10433 session->CloseAllConnections();
10434}
10435
[email protected]8c843192012-04-05 07:15:0010436// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110437TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510438 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910439 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510440 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10441 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010442 HttpRequestInfo request;
10443
10444 request.method = "GET";
bncce36dca22015-04-21 22:11:2310445 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010446 request.traffic_annotation =
10447 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010448
Ramin Halavatica8d5252018-03-12 05:33:4910449 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10450 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110451 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710452 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010453
10454 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210455 session_deps_.proxy_resolution_service->SetProxyDelegate(
10456 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010457
danakj1fd259a02016-04-16 03:17:0910458 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010459
Ryan Hamilton0239aac2018-05-19 00:03:1310460 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510461 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010462
Ryan Hamilton0239aac2018-05-19 00:03:1310463 spdy::SpdySerializedFrame push_rst(
10464 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0010465
10466 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110467 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0010468 };
10469
Ryan Hamilton0239aac2018-05-19 00:03:1310470 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510471 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0010472
Ryan Hamilton0239aac2018-05-19 00:03:1310473 spdy::SpdySerializedFrame stream1_body(
10474 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0010475
Ryan Hamilton0239aac2018-05-19 00:03:1310476 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510477 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0010478
10479 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110480 CreateMockRead(stream1_reply, 1, ASYNC),
10481 CreateMockRead(stream2_syn, 2, ASYNC),
10482 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5910483 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0010484 };
10485
Ryan Sleevib8d7ea02018-05-07 20:01:0110486 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710487 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0010488 // Negotiate SPDY to the proxy
10489 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610490 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710491 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0010492
bnc87dcefc2017-05-25 12:47:5810493 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910494 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0010495 TestCompletionCallback callback;
10496 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110497 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0010498
10499 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110500 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010501 const HttpResponseInfo* response = trans->GetResponseInfo();
10502
wezca1070932016-05-26 20:30:5210503 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0010504 EXPECT_TRUE(response->headers->IsKeepAlive());
10505
10506 EXPECT_EQ(200, response->headers->response_code());
10507 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10508
10509 std::string response_data;
10510 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110511 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010512 EXPECT_EQ("hello!", response_data);
10513
10514 trans.reset();
10515 session->CloseAllConnections();
10516}
10517
tbansal8ef1d3e2016-02-03 04:05:4210518// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
10519// resources.
bncd16676a2016-07-20 16:23:0110520TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510521 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910522 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510523 proxy_delegate->set_trusted_spdy_proxy(
10524 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
10525
tbansal8ef1d3e2016-02-03 04:05:4210526 HttpRequestInfo request;
10527
10528 request.method = "GET";
10529 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010530 request.traffic_annotation =
10531 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210532
10533 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4910534 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10535 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210536 BoundTestNetLog log;
10537 session_deps_.net_log = log.bound().net_log();
10538
10539 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210540 session_deps_.proxy_resolution_service->SetProxyDelegate(
10541 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4210542
danakj1fd259a02016-04-16 03:17:0910543 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4210544
Ryan Hamilton0239aac2018-05-19 00:03:1310545 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510546 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310547 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510548 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4210549
10550 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110551 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510552 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4210553 };
10554
Ryan Hamilton0239aac2018-05-19 00:03:1310555 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1510556 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210557
Ryan Hamilton0239aac2018-05-19 00:03:1310558 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3310559 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4910560
Ryan Hamilton0239aac2018-05-19 00:03:1310561 spdy::SpdySerializedFrame stream1_body(
10562 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210563
Ryan Hamilton0239aac2018-05-19 00:03:1310564 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1510565 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210566
Ryan Hamilton0239aac2018-05-19 00:03:1310567 spdy::SpdySerializedFrame stream2_body(
10568 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210569
10570 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110571 CreateMockRead(stream1_reply, 1, ASYNC),
10572 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510573 CreateMockRead(stream1_body, 4, ASYNC),
10574 CreateMockRead(stream2_body, 5, ASYNC),
10575 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4210576 };
10577
Ryan Sleevib8d7ea02018-05-07 20:01:0110578 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4210579 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10580 // Negotiate SPDY to the proxy
10581 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610582 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4210583 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
10584
bnc87dcefc2017-05-25 12:47:5810585 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910586 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4210587 TestCompletionCallback callback;
10588 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110589 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4210590
10591 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110592 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210593 const HttpResponseInfo* response = trans->GetResponseInfo();
10594
wezca1070932016-05-26 20:30:5210595 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4210596 EXPECT_TRUE(response->headers->IsKeepAlive());
10597
10598 EXPECT_EQ(200, response->headers->response_code());
10599 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10600
10601 std::string response_data;
10602 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110603 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210604 EXPECT_EQ("hello!", response_data);
10605
10606 trans.reset();
10607 session->CloseAllConnections();
10608}
10609
[email protected]2df19bb2010-08-25 20:13:4610610// Test HTTPS connections to a site with a bad certificate, going through an
10611// HTTPS proxy
bncd16676a2016-07-20 16:23:0110612TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910613 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10614 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610615
10616 HttpRequestInfo request;
10617 request.method = "GET";
bncce36dca22015-04-21 22:11:2310618 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010619 request.traffic_annotation =
10620 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610621
10622 // Attempt to fetch the URL from a server with a bad cert
10623 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710624 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10625 "Host: www.example.org:443\r\n"
10626 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610627 };
10628
10629 MockRead bad_cert_reads[] = {
10630 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610631 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4610632 };
10633
10634 // Attempt to fetch the URL with a good cert
10635 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710636 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10637 "Host: www.example.org:443\r\n"
10638 "Proxy-Connection: keep-alive\r\n\r\n"),
10639 MockWrite("GET / HTTP/1.1\r\n"
10640 "Host: www.example.org\r\n"
10641 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610642 };
10643
10644 MockRead good_cert_reads[] = {
10645 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10646 MockRead("HTTP/1.0 200 OK\r\n"),
10647 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10648 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610649 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610650 };
10651
Ryan Sleevib8d7ea02018-05-07 20:01:0110652 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
10653 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0610654 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10655 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4610656
10657 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0710658 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10659 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10660 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4610661
10662 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0710663 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10664 session_deps_.socket_factory->AddSocketDataProvider(&data);
10665 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4610666
[email protected]49639fa2011-12-20 23:22:4110667 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610668
danakj1fd259a02016-04-16 03:17:0910669 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610670 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610671
tfarina428341112016-09-22 13:38:2010672 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110673 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610674
10675 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110676 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4610677
bnc691fda62016-08-12 00:43:1610678 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110679 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610680
10681 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110682 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4610683
bnc691fda62016-08-12 00:43:1610684 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610685
wezca1070932016-05-26 20:30:5210686 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610687 EXPECT_EQ(100, response->headers->GetContentLength());
10688}
10689
bncd16676a2016-07-20 16:23:0110690TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4210691 HttpRequestInfo request;
10692 request.method = "GET";
bncce36dca22015-04-21 22:11:2310693 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310694 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10695 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e62018-02-07 07:41:1010696 request.traffic_annotation =
10697 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210698
danakj1fd259a02016-04-16 03:17:0910699 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610700 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710701
[email protected]1c773ea12009-04-28 19:58:4210702 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310703 MockWrite(
10704 "GET / HTTP/1.1\r\n"
10705 "Host: www.example.org\r\n"
10706 "Connection: keep-alive\r\n"
10707 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210708 };
10709
10710 // Lastly, the server responds with the actual content.
10711 MockRead data_reads[] = {
10712 MockRead("HTTP/1.0 200 OK\r\n"),
10713 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10714 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610715 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210716 };
10717
Ryan Sleevib8d7ea02018-05-07 20:01:0110718 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710719 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210720
[email protected]49639fa2011-12-20 23:22:4110721 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210722
tfarina428341112016-09-22 13:38:2010723 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110724 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210725
10726 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110727 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210728}
10729
bncd16676a2016-07-20 16:23:0110730TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0010731 // Test user agent values, used both for the request header of the original
10732 // request, and the value returned by the HttpUserAgentSettings. nullptr means
10733 // no request header / no HttpUserAgentSettings object.
10734 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2910735
Matt Menked732ea42019-03-08 12:05:0010736 for (const char* setting_user_agent : kTestUserAgents) {
10737 if (!setting_user_agent) {
10738 session_deps_.http_user_agent_settings.reset();
10739 } else {
10740 session_deps_.http_user_agent_settings =
10741 std::make_unique<StaticHttpUserAgentSettings>(
10742 std::string() /* accept-language */, setting_user_agent);
10743 }
10744 session_deps_.proxy_resolution_service =
10745 ProxyResolutionService::CreateFixed("myproxy:70",
10746 TRAFFIC_ANNOTATION_FOR_TESTS);
10747 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10748 for (const char* request_user_agent : kTestUserAgents) {
10749 HttpRequestInfo request;
10750 request.method = "GET";
10751 request.url = GURL("https://www.example.org/");
10752 if (request_user_agent) {
10753 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10754 request_user_agent);
10755 }
10756 request.traffic_annotation =
10757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710758
Matt Menked732ea42019-03-08 12:05:0010759 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2910760
Matt Menked732ea42019-03-08 12:05:0010761 std::string expected_request;
10762 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
10763 expected_request =
10764 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10765 "Host: www.example.org:443\r\n"
10766 "Proxy-Connection: keep-alive\r\n\r\n";
10767 } else {
10768 expected_request = base::StringPrintf(
10769 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10770 "Host: www.example.org:443\r\n"
10771 "Proxy-Connection: keep-alive\r\n"
10772 "User-Agent: %s\r\n\r\n",
10773 setting_user_agent);
10774 }
10775 MockWrite data_writes[] = {
10776 MockWrite(expected_request.c_str()),
10777 };
10778 MockRead data_reads[] = {
10779 // Return an error, so the transaction stops here (this test isn't
10780 // interested in the rest).
10781 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10782 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10783 MockRead("Proxy-Connection: close\r\n\r\n"),
10784 };
[email protected]da81f132010-08-18 23:39:2910785
Matt Menked732ea42019-03-08 12:05:0010786 StaticSocketDataProvider data(data_reads, data_writes);
10787 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2910788
Matt Menked732ea42019-03-08 12:05:0010789 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2910790
Matt Menked732ea42019-03-08 12:05:0010791 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10792 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10793
10794 rv = callback.WaitForResult();
10795 EXPECT_THAT(rv, IsOk());
10796 }
10797 }
[email protected]da81f132010-08-18 23:39:2910798}
10799
bncd16676a2016-07-20 16:23:0110800TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4210801 HttpRequestInfo request;
10802 request.method = "GET";
bncce36dca22015-04-21 22:11:2310803 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1610804 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
10805 "http://the.previous.site.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1010806 request.traffic_annotation =
10807 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210808
danakj1fd259a02016-04-16 03:17:0910809 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610810 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710811
[email protected]1c773ea12009-04-28 19:58:4210812 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310813 MockWrite(
10814 "GET / HTTP/1.1\r\n"
10815 "Host: www.example.org\r\n"
10816 "Connection: keep-alive\r\n"
10817 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210818 };
10819
10820 // Lastly, the server responds with the actual content.
10821 MockRead data_reads[] = {
10822 MockRead("HTTP/1.0 200 OK\r\n"),
10823 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10824 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610825 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210826 };
10827
Ryan Sleevib8d7ea02018-05-07 20:01:0110828 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710829 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210830
[email protected]49639fa2011-12-20 23:22:4110831 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210832
tfarina428341112016-09-22 13:38:2010833 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110834 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210835
10836 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110837 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210838}
10839
bncd16676a2016-07-20 16:23:0110840TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210841 HttpRequestInfo request;
10842 request.method = "POST";
bncce36dca22015-04-21 22:11:2310843 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010844 request.traffic_annotation =
10845 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210846
danakj1fd259a02016-04-16 03:17:0910847 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610848 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710849
[email protected]1c773ea12009-04-28 19:58:4210850 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310851 MockWrite(
10852 "POST / HTTP/1.1\r\n"
10853 "Host: www.example.org\r\n"
10854 "Connection: keep-alive\r\n"
10855 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210856 };
10857
10858 // Lastly, the server responds with the actual content.
10859 MockRead data_reads[] = {
10860 MockRead("HTTP/1.0 200 OK\r\n"),
10861 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10862 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610863 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210864 };
10865
Ryan Sleevib8d7ea02018-05-07 20:01:0110866 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710867 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210868
[email protected]49639fa2011-12-20 23:22:4110869 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210870
tfarina428341112016-09-22 13:38:2010871 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110872 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210873
10874 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110875 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210876}
10877
bncd16676a2016-07-20 16:23:0110878TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210879 HttpRequestInfo request;
10880 request.method = "PUT";
bncce36dca22015-04-21 22:11:2310881 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010882 request.traffic_annotation =
10883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210884
danakj1fd259a02016-04-16 03:17:0910885 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610886 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710887
[email protected]1c773ea12009-04-28 19:58:4210888 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310889 MockWrite(
10890 "PUT / HTTP/1.1\r\n"
10891 "Host: www.example.org\r\n"
10892 "Connection: keep-alive\r\n"
10893 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210894 };
10895
10896 // Lastly, the server responds with the actual content.
10897 MockRead data_reads[] = {
10898 MockRead("HTTP/1.0 200 OK\r\n"),
10899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10900 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610901 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210902 };
10903
Ryan Sleevib8d7ea02018-05-07 20:01:0110904 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710905 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210906
[email protected]49639fa2011-12-20 23:22:4110907 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210908
tfarina428341112016-09-22 13:38:2010909 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110910 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210911
10912 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110913 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210914}
10915
bncd16676a2016-07-20 16:23:0110916TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210917 HttpRequestInfo request;
10918 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2310919 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010920 request.traffic_annotation =
10921 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210922
danakj1fd259a02016-04-16 03:17:0910923 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610924 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710925
[email protected]1c773ea12009-04-28 19:58:4210926 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1310927 MockWrite("HEAD / HTTP/1.1\r\n"
10928 "Host: www.example.org\r\n"
10929 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210930 };
10931
10932 // Lastly, the server responds with the actual content.
10933 MockRead data_reads[] = {
10934 MockRead("HTTP/1.0 200 OK\r\n"),
10935 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10936 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610937 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210938 };
10939
Ryan Sleevib8d7ea02018-05-07 20:01:0110940 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710941 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210942
[email protected]49639fa2011-12-20 23:22:4110943 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210944
tfarina428341112016-09-22 13:38:2010945 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110946 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210947
10948 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110949 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210950}
10951
bncd16676a2016-07-20 16:23:0110952TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4210953 HttpRequestInfo request;
10954 request.method = "GET";
bncce36dca22015-04-21 22:11:2310955 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210956 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010957 request.traffic_annotation =
10958 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210959
danakj1fd259a02016-04-16 03:17:0910960 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610961 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710962
[email protected]1c773ea12009-04-28 19:58:4210963 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310964 MockWrite(
10965 "GET / HTTP/1.1\r\n"
10966 "Host: www.example.org\r\n"
10967 "Connection: keep-alive\r\n"
10968 "Pragma: no-cache\r\n"
10969 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210970 };
10971
10972 // Lastly, the server responds with the actual content.
10973 MockRead data_reads[] = {
10974 MockRead("HTTP/1.0 200 OK\r\n"),
10975 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10976 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610977 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210978 };
10979
Ryan Sleevib8d7ea02018-05-07 20:01:0110980 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710981 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210982
[email protected]49639fa2011-12-20 23:22:4110983 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210984
tfarina428341112016-09-22 13:38:2010985 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110986 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210987
10988 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110989 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210990}
10991
bncd16676a2016-07-20 16:23:0110992TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4210993 HttpRequestInfo request;
10994 request.method = "GET";
bncce36dca22015-04-21 22:11:2310995 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210996 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010997 request.traffic_annotation =
10998 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210999
danakj1fd259a02016-04-16 03:17:0911000 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611001 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711002
[email protected]1c773ea12009-04-28 19:58:4211003 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311004 MockWrite(
11005 "GET / HTTP/1.1\r\n"
11006 "Host: www.example.org\r\n"
11007 "Connection: keep-alive\r\n"
11008 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211009 };
11010
11011 // Lastly, the server responds with the actual content.
11012 MockRead data_reads[] = {
11013 MockRead("HTTP/1.0 200 OK\r\n"),
11014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11015 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611016 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211017 };
11018
Ryan Sleevib8d7ea02018-05-07 20:01:0111019 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711020 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211021
[email protected]49639fa2011-12-20 23:22:4111022 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211023
tfarina428341112016-09-22 13:38:2011024 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111025 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211026
11027 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111028 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211029}
11030
bncd16676a2016-07-20 16:23:0111031TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4211032 HttpRequestInfo request;
11033 request.method = "GET";
bncce36dca22015-04-21 22:11:2311034 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311035 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e62018-02-07 07:41:1011036 request.traffic_annotation =
11037 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211038
danakj1fd259a02016-04-16 03:17:0911039 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611040 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711041
[email protected]1c773ea12009-04-28 19:58:4211042 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311043 MockWrite(
11044 "GET / HTTP/1.1\r\n"
11045 "Host: www.example.org\r\n"
11046 "Connection: keep-alive\r\n"
11047 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211048 };
11049
11050 // Lastly, the server responds with the actual content.
11051 MockRead data_reads[] = {
11052 MockRead("HTTP/1.0 200 OK\r\n"),
11053 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11054 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611055 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211056 };
11057
Ryan Sleevib8d7ea02018-05-07 20:01:0111058 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711059 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211060
[email protected]49639fa2011-12-20 23:22:4111061 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211062
tfarina428341112016-09-22 13:38:2011063 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111064 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211065
11066 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111067 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211068}
11069
bncd16676a2016-07-20 16:23:0111070TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4711071 HttpRequestInfo request;
11072 request.method = "GET";
bncce36dca22015-04-21 22:11:2311073 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311074 request.extra_headers.SetHeader("referer", "www.foo.com");
11075 request.extra_headers.SetHeader("hEllo", "Kitty");
11076 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1011077 request.traffic_annotation =
11078 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4711079
danakj1fd259a02016-04-16 03:17:0911080 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611081 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711082
[email protected]270c6412010-03-29 22:02:4711083 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311084 MockWrite(
11085 "GET / HTTP/1.1\r\n"
11086 "Host: www.example.org\r\n"
11087 "Connection: keep-alive\r\n"
11088 "referer: www.foo.com\r\n"
11089 "hEllo: Kitty\r\n"
11090 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4711091 };
11092
11093 // Lastly, the server responds with the actual content.
11094 MockRead data_reads[] = {
11095 MockRead("HTTP/1.0 200 OK\r\n"),
11096 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11097 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611098 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4711099 };
11100
Ryan Sleevib8d7ea02018-05-07 20:01:0111101 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711102 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4711103
[email protected]49639fa2011-12-20 23:22:4111104 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4711105
tfarina428341112016-09-22 13:38:2011106 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111107 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4711108
11109 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111110 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4711111}
11112
bncd16676a2016-07-20 16:23:0111113TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711114 HttpRequestInfo request;
11115 request.method = "GET";
bncce36dca22015-04-21 22:11:2311116 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011117 request.traffic_annotation =
11118 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711119
Lily Houghton8c2f97d2018-01-22 05:06:5911120 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911121 ProxyResolutionService::CreateFixedFromPacResult(
11122 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111123 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711124 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211125
danakj1fd259a02016-04-16 03:17:0911126 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611127 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211128
[email protected]3cd17242009-06-23 02:59:0211129 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11130 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11131
11132 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411133 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11134 MockWrite("GET / HTTP/1.1\r\n"
11135 "Host: www.example.org\r\n"
11136 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211137
11138 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411139 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11140 MockRead("HTTP/1.0 200 OK\r\n"),
11141 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11142 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211143
Ryan Sleevib8d7ea02018-05-07 20:01:0111144 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711145 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211146
[email protected]49639fa2011-12-20 23:22:4111147 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211148
tfarina428341112016-09-22 13:38:2011149 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111150 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211151
11152 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111153 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211154
bnc691fda62016-08-12 00:43:1611155 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211156 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0211157
tbansal2ecbbc72016-10-06 17:15:4711158 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2011159 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611160 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011161 TestLoadTimingNotReusedWithPac(load_timing_info,
11162 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11163
[email protected]3cd17242009-06-23 02:59:0211164 std::string response_text;
bnc691fda62016-08-12 00:43:1611165 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111166 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211167 EXPECT_EQ("Payload", response_text);
11168}
11169
bncd16676a2016-07-20 16:23:0111170TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711171 HttpRequestInfo request;
11172 request.method = "GET";
bncce36dca22015-04-21 22:11:2311173 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011174 request.traffic_annotation =
11175 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711176
Lily Houghton8c2f97d2018-01-22 05:06:5911177 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911178 ProxyResolutionService::CreateFixedFromPacResult(
11179 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111180 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711181 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211182
danakj1fd259a02016-04-16 03:17:0911183 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611184 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211185
[email protected]3cd17242009-06-23 02:59:0211186 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
11187 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11188
11189 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311190 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2411191 base::size(write_buffer)),
11192 MockWrite("GET / HTTP/1.1\r\n"
11193 "Host: www.example.org\r\n"
11194 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211195
11196 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411197 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
11198 base::size(read_buffer)),
11199 MockRead("HTTP/1.0 200 OK\r\n"),
11200 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11201 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511202
Ryan Sleevib8d7ea02018-05-07 20:01:0111203 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711204 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511205
[email protected]8ddf8322012-02-23 18:08:0611206 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711207 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3511208
[email protected]49639fa2011-12-20 23:22:4111209 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511210
tfarina428341112016-09-22 13:38:2011211 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111212 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511213
11214 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111215 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511216
[email protected]029c83b62013-01-24 05:28:2011217 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611218 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011219 TestLoadTimingNotReusedWithPac(load_timing_info,
11220 CONNECT_TIMING_HAS_SSL_TIMES);
11221
bnc691fda62016-08-12 00:43:1611222 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211223 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711224 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511225
11226 std::string response_text;
bnc691fda62016-08-12 00:43:1611227 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111228 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511229 EXPECT_EQ("Payload", response_text);
11230}
11231
bncd16676a2016-07-20 16:23:0111232TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2011233 HttpRequestInfo request;
11234 request.method = "GET";
bncce36dca22015-04-21 22:11:2311235 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011236 request.traffic_annotation =
11237 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2011238
Ramin Halavatica8d5252018-03-12 05:33:4911239 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11240 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111241 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711242 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2011243
danakj1fd259a02016-04-16 03:17:0911244 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611245 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2011246
11247 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11248 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11249
11250 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411251 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11252 MockWrite("GET / HTTP/1.1\r\n"
11253 "Host: www.example.org\r\n"
11254 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2011255
11256 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411257 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11258 MockRead("HTTP/1.0 200 OK\r\n"),
11259 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11260 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2011261
Ryan Sleevib8d7ea02018-05-07 20:01:0111262 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711263 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2011264
11265 TestCompletionCallback callback;
11266
tfarina428341112016-09-22 13:38:2011267 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111268 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2011269
11270 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111271 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011272
bnc691fda62016-08-12 00:43:1611273 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211274 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2011275
11276 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611277 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011278 TestLoadTimingNotReused(load_timing_info,
11279 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11280
11281 std::string response_text;
bnc691fda62016-08-12 00:43:1611282 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111283 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011284 EXPECT_EQ("Payload", response_text);
11285}
11286
bncd16676a2016-07-20 16:23:0111287TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711288 HttpRequestInfo request;
11289 request.method = "GET";
bncce36dca22015-04-21 22:11:2311290 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011291 request.traffic_annotation =
11292 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711293
Lily Houghton8c2f97d2018-01-22 05:06:5911294 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911295 ProxyResolutionService::CreateFixedFromPacResult(
11296 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111297 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711298 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511299
danakj1fd259a02016-04-16 03:17:0911300 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611301 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511302
[email protected]e0c27be2009-07-15 13:09:3511303 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11304 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711305 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311306 0x05, // Version
11307 0x01, // Command (CONNECT)
11308 0x00, // Reserved.
11309 0x03, // Address type (DOMAINNAME).
11310 0x0F, // Length of domain (15)
11311 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11312 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3711313 };
[email protected]e0c27be2009-07-15 13:09:3511314 const char kSOCKS5OkResponse[] =
11315 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
11316
11317 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411318 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
11319 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
11320 MockWrite("GET / HTTP/1.1\r\n"
11321 "Host: www.example.org\r\n"
11322 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511323
11324 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411325 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11326 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11327 MockRead("HTTP/1.0 200 OK\r\n"),
11328 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11329 MockRead("Payload"),
11330 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511331
Ryan Sleevib8d7ea02018-05-07 20:01:0111332 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711333 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511334
[email protected]49639fa2011-12-20 23:22:4111335 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511336
tfarina428341112016-09-22 13:38:2011337 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111338 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511339
11340 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111341 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511342
bnc691fda62016-08-12 00:43:1611343 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211344 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711345 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511346
[email protected]029c83b62013-01-24 05:28:2011347 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611348 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011349 TestLoadTimingNotReusedWithPac(load_timing_info,
11350 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11351
[email protected]e0c27be2009-07-15 13:09:3511352 std::string response_text;
bnc691fda62016-08-12 00:43:1611353 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111354 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511355 EXPECT_EQ("Payload", response_text);
11356}
11357
bncd16676a2016-07-20 16:23:0111358TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711359 HttpRequestInfo request;
11360 request.method = "GET";
bncce36dca22015-04-21 22:11:2311361 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011362 request.traffic_annotation =
11363 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711364
Lily Houghton8c2f97d2018-01-22 05:06:5911365 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911366 ProxyResolutionService::CreateFixedFromPacResult(
11367 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111368 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711369 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511370
danakj1fd259a02016-04-16 03:17:0911371 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611372 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511373
[email protected]e0c27be2009-07-15 13:09:3511374 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11375 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711376 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311377 0x05, // Version
11378 0x01, // Command (CONNECT)
11379 0x00, // Reserved.
11380 0x03, // Address type (DOMAINNAME).
11381 0x0F, // Length of domain (15)
11382 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11383 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711384 };
11385
[email protected]e0c27be2009-07-15 13:09:3511386 const char kSOCKS5OkResponse[] =
11387 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11388
11389 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411390 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311391 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411392 base::size(kSOCKS5OkRequest)),
11393 MockWrite("GET / HTTP/1.1\r\n"
11394 "Host: www.example.org\r\n"
11395 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511396
11397 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411398 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11399 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11400 MockRead("HTTP/1.0 200 OK\r\n"),
11401 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11402 MockRead("Payload"),
11403 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211404
Ryan Sleevib8d7ea02018-05-07 20:01:0111405 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711406 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211407
[email protected]8ddf8322012-02-23 18:08:0611408 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711409 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211410
[email protected]49639fa2011-12-20 23:22:4111411 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211412
tfarina428341112016-09-22 13:38:2011413 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111414 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211415
11416 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111417 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211418
bnc691fda62016-08-12 00:43:1611419 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211420 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711421 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211422
[email protected]029c83b62013-01-24 05:28:2011423 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611424 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011425 TestLoadTimingNotReusedWithPac(load_timing_info,
11426 CONNECT_TIMING_HAS_SSL_TIMES);
11427
[email protected]3cd17242009-06-23 02:59:0211428 std::string response_text;
bnc691fda62016-08-12 00:43:1611429 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111430 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211431 EXPECT_EQ("Payload", response_text);
11432}
11433
[email protected]448d4ca52012-03-04 04:12:2311434namespace {
11435
Matt Menkef6edce752019-03-19 17:21:5611436// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611437
Matt Menkef6edce752019-03-19 17:21:5611438struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611439 std::string proxy_server;
11440 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611441 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811442 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611443};
11444
Matt Menkef6edce752019-03-19 17:21:5611445std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711446 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911447 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611448
bnc525e175a2016-06-20 12:36:4011449 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311450 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111451 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211452 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111453 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211454 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0711455 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611456
11457 return session;
11458}
11459
Matt Menkef6edce752019-03-19 17:21:5611460int GroupIdTransactionHelper(const std::string& url,
11461 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611462 HttpRequestInfo request;
11463 request.method = "GET";
11464 request.url = GURL(url);
Ramin Halavatib5e433e62018-02-07 07:41:1011465 request.traffic_annotation =
11466 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0611467
bnc691fda62016-08-12 00:43:1611468 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2711469
[email protected]49639fa2011-12-20 23:22:4111470 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0611471
11472 // We do not complete this request, the dtor will clean the transaction up.
tfarina428341112016-09-22 13:38:2011473 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0611474}
11475
[email protected]448d4ca52012-03-04 04:12:2311476} // namespace
11477
Matt Menkef6edce752019-03-19 17:21:5611478TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
11479 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311480 {
Matt Menkef6edce752019-03-19 17:21:5611481 "", // unused
11482 "http://www.example.org/direct",
11483 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11484 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411485 PrivacyMode::PRIVACY_MODE_DISABLED,
11486 NetworkIsolationKey(),
11487 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611488 false,
bncce36dca22015-04-21 22:11:2311489 },
11490 {
Matt Menkef6edce752019-03-19 17:21:5611491 "", // unused
11492 "http://[2001:1418:13:1::25]/direct",
11493 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
11494 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411495 PrivacyMode::PRIVACY_MODE_DISABLED,
11496 NetworkIsolationKey(),
11497 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611498 false,
bncce36dca22015-04-21 22:11:2311499 },
[email protected]04e5be32009-06-26 20:00:3111500
bncce36dca22015-04-21 22:11:2311501 // SSL Tests
11502 {
Matt Menkef6edce752019-03-19 17:21:5611503 "", // unused
11504 "https://www.example.org/direct_ssl",
11505 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11506 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411507 PrivacyMode::PRIVACY_MODE_DISABLED,
11508 NetworkIsolationKey(),
11509 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611510 true,
bncce36dca22015-04-21 22:11:2311511 },
11512 {
Matt Menkef6edce752019-03-19 17:21:5611513 "", // unused
11514 "https://[2001:1418:13:1::25]/direct",
11515 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
11516 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411517 PrivacyMode::PRIVACY_MODE_DISABLED,
11518 NetworkIsolationKey(),
11519 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611520 true,
bncce36dca22015-04-21 22:11:2311521 },
11522 {
Matt Menkef6edce752019-03-19 17:21:5611523 "", // unused
11524 "https://host.with.alternate/direct",
11525 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11526 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411527 PrivacyMode::PRIVACY_MODE_DISABLED,
11528 NetworkIsolationKey(),
11529 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611530 true,
bncce36dca22015-04-21 22:11:2311531 },
[email protected]2d731a32010-04-29 01:04:0611532 };
[email protected]2ff8b312010-04-26 22:20:5411533
Avi Drissman4365a4782018-12-28 19:26:2411534 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911535 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911536 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11537 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911538 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611539 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611540
mmenkee65e7af2015-10-13 17:16:4211541 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5611542 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611543 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911544 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011545 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
11546 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4811547 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611548
11549 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611550 GroupIdTransactionHelper(tests[i].url, session.get()));
11551 EXPECT_EQ(tests[i].expected_group_id,
11552 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2311553 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0611554 }
[email protected]2d731a32010-04-29 01:04:0611555}
11556
Matt Menkef6edce752019-03-19 17:21:5611557TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
11558 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311559 {
Matt Menke4802de62019-03-08 22:47:5011560 "http_proxy",
11561 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611562 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11563 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411564 PrivacyMode::PRIVACY_MODE_DISABLED,
11565 NetworkIsolationKey(),
11566 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011567 false,
bncce36dca22015-04-21 22:11:2311568 },
[email protected]2d731a32010-04-29 01:04:0611569
bncce36dca22015-04-21 22:11:2311570 // SSL Tests
11571 {
Matt Menke4802de62019-03-08 22:47:5011572 "http_proxy",
11573 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5611574 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11575 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411576 PrivacyMode::PRIVACY_MODE_DISABLED,
11577 NetworkIsolationKey(),
11578 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011579 true,
bncce36dca22015-04-21 22:11:2311580 },
[email protected]af3490e2010-10-16 21:02:2911581
bncce36dca22015-04-21 22:11:2311582 {
Matt Menke4802de62019-03-08 22:47:5011583 "http_proxy",
11584 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611585 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11586 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411587 PrivacyMode::PRIVACY_MODE_DISABLED,
11588 NetworkIsolationKey(),
11589 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011590 true,
bncce36dca22015-04-21 22:11:2311591 },
[email protected]2d731a32010-04-29 01:04:0611592 };
11593
Avi Drissman4365a4782018-12-28 19:26:2411594 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911595 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911596 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11597 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911598 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611599 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611600
mmenkee65e7af2015-10-13 17:16:4211601 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0611602
Matt Menkee8648fa2019-01-17 16:47:0711603 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
11604 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5611605 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3611606 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911607 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011608 mock_pool_manager->SetSocketPool(proxy_server,
11609 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4811610 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611611
11612 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611613 GroupIdTransactionHelper(tests[i].url, session.get()));
11614 EXPECT_EQ(tests[i].expected_group_id,
11615 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0611616 }
[email protected]2d731a32010-04-29 01:04:0611617}
11618
Matt Menkef6edce752019-03-19 17:21:5611619TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
11620 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311621 {
Matt Menke4802de62019-03-08 22:47:5011622 "socks4://socks_proxy:1080",
11623 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5611624 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11625 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411626 PrivacyMode::PRIVACY_MODE_DISABLED,
11627 NetworkIsolationKey(),
11628 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011629 false,
bncce36dca22015-04-21 22:11:2311630 },
11631 {
Matt Menke4802de62019-03-08 22:47:5011632 "socks5://socks_proxy:1080",
11633 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5611634 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11635 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411636 PrivacyMode::PRIVACY_MODE_DISABLED,
11637 NetworkIsolationKey(),
11638 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011639 false,
bncce36dca22015-04-21 22:11:2311640 },
[email protected]2d731a32010-04-29 01:04:0611641
bncce36dca22015-04-21 22:11:2311642 // SSL Tests
11643 {
Matt Menke4802de62019-03-08 22:47:5011644 "socks4://socks_proxy:1080",
11645 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5611646 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11647 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411648 PrivacyMode::PRIVACY_MODE_DISABLED,
11649 NetworkIsolationKey(),
11650 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011651 true,
bncce36dca22015-04-21 22:11:2311652 },
11653 {
Matt Menke4802de62019-03-08 22:47:5011654 "socks5://socks_proxy:1080",
11655 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5611656 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11657 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411658 PrivacyMode::PRIVACY_MODE_DISABLED,
11659 NetworkIsolationKey(),
11660 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011661 true,
bncce36dca22015-04-21 22:11:2311662 },
[email protected]af3490e2010-10-16 21:02:2911663
bncce36dca22015-04-21 22:11:2311664 {
Matt Menke4802de62019-03-08 22:47:5011665 "socks4://socks_proxy:1080",
11666 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611667 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11668 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411669 PrivacyMode::PRIVACY_MODE_DISABLED,
11670 NetworkIsolationKey(),
11671 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011672 true,
bncce36dca22015-04-21 22:11:2311673 },
[email protected]04e5be32009-06-26 20:00:3111674 };
11675
Avi Drissman4365a4782018-12-28 19:26:2411676 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911677 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911678 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11679 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911680 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611681 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0211682
mmenkee65e7af2015-10-13 17:16:4211683 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3111684
Matt Menkee8648fa2019-01-17 16:47:0711685 ProxyServer proxy_server(
11686 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
11687 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5611688 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611689 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911690 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011691 mock_pool_manager->SetSocketPool(proxy_server,
11692 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4811693 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3111694
bnc691fda62016-08-12 00:43:1611695 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3111696
[email protected]2d731a32010-04-29 01:04:0611697 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611698 GroupIdTransactionHelper(tests[i].url, session.get()));
11699 EXPECT_EQ(tests[i].expected_group_id,
11700 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3111701 }
11702}
11703
bncd16676a2016-07-20 16:23:0111704TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2711705 HttpRequestInfo request;
11706 request.method = "GET";
bncce36dca22015-04-21 22:11:2311707 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011708 request.traffic_annotation =
11709 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711710
Ramin Halavatica8d5252018-03-12 05:33:4911711 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11712 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3211713
[email protected]69719062010-01-05 20:09:2111714 // This simulates failure resolving all hostnames; that means we will fail
11715 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0711716 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3211717
danakj1fd259a02016-04-16 03:17:0911718 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611719 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2511720
[email protected]49639fa2011-12-20 23:22:4111721 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2511722
tfarina428341112016-09-22 13:38:2011723 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111724 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2511725
[email protected]9172a982009-06-06 00:30:2511726 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111727 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2511728}
11729
[email protected]0877e3d2009-10-17 22:29:5711730// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0111731TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5711732 HttpRequestInfo request;
11733 request.method = "GET";
11734 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011735 request.traffic_annotation =
11736 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711737
11738 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0611739 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711740 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111741 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0711742 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911743 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711744
[email protected]49639fa2011-12-20 23:22:4111745 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711746
bnc691fda62016-08-12 00:43:1611747 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711748
tfarina428341112016-09-22 13:38:2011749 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111750 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711751
11752 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111753 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5911754
11755 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611756 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911757 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711758}
11759
zmo9528c9f42015-08-04 22:12:0811760// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0111761TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5711762 HttpRequestInfo request;
11763 request.method = "GET";
11764 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011765 request.traffic_annotation =
11766 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711767
11768 MockRead data_reads[] = {
11769 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0611770 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711771 };
11772
Ryan Sleevib8d7ea02018-05-07 20:01:0111773 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711774 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911775 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711776
[email protected]49639fa2011-12-20 23:22:4111777 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711778
bnc691fda62016-08-12 00:43:1611779 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711780
tfarina428341112016-09-22 13:38:2011781 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111782 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711783
11784 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111785 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811786
bnc691fda62016-08-12 00:43:1611787 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211788 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0811789
wezca1070932016-05-26 20:30:5211790 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0811791 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11792
11793 std::string response_data;
bnc691fda62016-08-12 00:43:1611794 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111795 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811796 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5911797
11798 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611799 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911800 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711801}
11802
11803// Make sure that a dropped connection while draining the body for auth
11804// restart does the right thing.
bncd16676a2016-07-20 16:23:0111805TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5711806 HttpRequestInfo request;
11807 request.method = "GET";
bncce36dca22015-04-21 22:11:2311808 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011809 request.traffic_annotation =
11810 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711811
11812 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311813 MockWrite(
11814 "GET / HTTP/1.1\r\n"
11815 "Host: www.example.org\r\n"
11816 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711817 };
11818
11819 MockRead data_reads1[] = {
11820 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
11821 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11822 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11823 MockRead("Content-Length: 14\r\n\r\n"),
11824 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0611825 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711826 };
11827
Ryan Sleevib8d7ea02018-05-07 20:01:0111828 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0711829 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5711830
bnc691fda62016-08-12 00:43:1611831 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5711832 // be issuing -- the final header line contains the credentials.
11833 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311834 MockWrite(
11835 "GET / HTTP/1.1\r\n"
11836 "Host: www.example.org\r\n"
11837 "Connection: keep-alive\r\n"
11838 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711839 };
11840
11841 // Lastly, the server responds with the actual content.
11842 MockRead data_reads2[] = {
11843 MockRead("HTTP/1.1 200 OK\r\n"),
11844 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11845 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611846 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711847 };
11848
Ryan Sleevib8d7ea02018-05-07 20:01:0111849 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0711850 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0911851 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711852
[email protected]49639fa2011-12-20 23:22:4111853 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5711854
bnc691fda62016-08-12 00:43:1611855 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011856
tfarina428341112016-09-22 13:38:2011857 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711859
11860 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111861 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711862
bnc691fda62016-08-12 00:43:1611863 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211864 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811865 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5711866
[email protected]49639fa2011-12-20 23:22:4111867 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5711868
bnc691fda62016-08-12 00:43:1611869 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0111870 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711871
11872 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111873 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711874
bnc691fda62016-08-12 00:43:1611875 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211876 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811877 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5711878 EXPECT_EQ(100, response->headers->GetContentLength());
11879}
11880
11881// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0111882TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4911883 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11884 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711885
11886 HttpRequestInfo request;
11887 request.method = "GET";
bncce36dca22015-04-21 22:11:2311888 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011889 request.traffic_annotation =
11890 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711891
11892 MockRead proxy_reads[] = {
11893 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0611894 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5711895 };
11896
Ryan Sleevib8d7ea02018-05-07 20:01:0111897 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0611898 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5711899
[email protected]bb88e1d32013-05-03 23:11:0711900 session_deps_.socket_factory->AddSocketDataProvider(&data);
11901 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5711902
[email protected]49639fa2011-12-20 23:22:4111903 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711904
[email protected]bb88e1d32013-05-03 23:11:0711905 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5711906
danakj1fd259a02016-04-16 03:17:0911907 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611908 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711909
tfarina428341112016-09-22 13:38:2011910 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111911 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711912
11913 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111914 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5711915}
11916
bncd16676a2016-07-20 16:23:0111917TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4611918 HttpRequestInfo request;
11919 request.method = "GET";
bncce36dca22015-04-21 22:11:2311920 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011921 request.traffic_annotation =
11922 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4611923
danakj1fd259a02016-04-16 03:17:0911924 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611925 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711926
[email protected]e22e1362009-11-23 21:31:1211927 MockRead data_reads[] = {
11928 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611929 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1211930 };
[email protected]9492e4a2010-02-24 00:58:4611931
Ryan Sleevib8d7ea02018-05-07 20:01:0111932 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711933 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4611934
[email protected]49639fa2011-12-20 23:22:4111935 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4611936
tfarina428341112016-09-22 13:38:2011937 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111938 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4611939
robpercival214763f2016-07-01 23:27:0111940 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4611941
bnc691fda62016-08-12 00:43:1611942 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211943 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4611944
wezca1070932016-05-26 20:30:5211945 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4611946 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11947
11948 std::string response_data;
bnc691fda62016-08-12 00:43:1611949 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111950 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1211951}
11952
bncd16676a2016-07-20 16:23:0111953TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1511954 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5211955 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1411956 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2111957 UploadFileElementReader::ScopedOverridingContentLengthForTests
11958 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3311959
danakj1fd259a02016-04-16 03:17:0911960 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911961 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411962 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0711963 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211964 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711965
11966 HttpRequestInfo request;
11967 request.method = "POST";
bncce36dca22015-04-21 22:11:2311968 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711969 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011970 request.traffic_annotation =
11971 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711972
danakj1fd259a02016-04-16 03:17:0911973 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611974 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3311975
11976 MockRead data_reads[] = {
11977 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11978 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0611979 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3311980 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111981 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711982 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3311983
[email protected]49639fa2011-12-20 23:22:4111984 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3311985
tfarina428341112016-09-22 13:38:2011986 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111987 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3311988
11989 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111990 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3311991
bnc691fda62016-08-12 00:43:1611992 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211993 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3311994
maksim.sisove869bf52016-06-23 17:11:5211995 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3311996
[email protected]dd3aa792013-07-16 19:10:2311997 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3311998}
11999
bncd16676a2016-07-20 16:23:0112000TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1512001 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5212002 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3612003 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4812004 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
12005 base::WriteFile(temp_file, temp_file_content.c_str(),
12006 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1112007 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3612008
danakj1fd259a02016-04-16 03:17:0912009 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912010 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412011 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0712012 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212013 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712014
12015 HttpRequestInfo request;
12016 request.method = "POST";
bncce36dca22015-04-21 22:11:2312017 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712018 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012019 request.traffic_annotation =
12020 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712021
[email protected]999dd8c2013-11-12 06:45:5412022 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0912023 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612024 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3612025
Ryan Sleevib8d7ea02018-05-07 20:01:0112026 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0712027 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3612028
[email protected]49639fa2011-12-20 23:22:4112029 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3612030
tfarina428341112016-09-22 13:38:2012031 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112032 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3612033
12034 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112035 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3612036
[email protected]dd3aa792013-07-16 19:10:2312037 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3612038}
12039
bncd16676a2016-07-20 16:23:0112040TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0312041 class FakeUploadElementReader : public UploadElementReader {
12042 public:
Chris Watkins7a41d3552017-12-01 02:13:2712043 FakeUploadElementReader() = default;
12044 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0312045
Matt Menkecc1d3a902018-02-05 18:27:3312046 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0312047
12048 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3312049 int Init(CompletionOnceCallback callback) override {
12050 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0312051 return ERR_IO_PENDING;
12052 }
avibf0746c2015-12-09 19:53:1412053 uint64_t GetContentLength() const override { return 0; }
12054 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2012055 int Read(IOBuffer* buf,
12056 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3312057 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0312058 return ERR_FAILED;
12059 }
12060
12061 private:
Matt Menkecc1d3a902018-02-05 18:27:3312062 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0312063 };
12064
12065 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0912066 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
12067 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2212068 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0312069
12070 HttpRequestInfo request;
12071 request.method = "POST";
bncce36dca22015-04-21 22:11:2312072 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0312073 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012074 request.traffic_annotation =
12075 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0312076
danakj1fd259a02016-04-16 03:17:0912077 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812078 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912079 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0312080
12081 StaticSocketDataProvider data;
12082 session_deps_.socket_factory->AddSocketDataProvider(&data);
12083
12084 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:2012085 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112086 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5512087 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0312088
12089 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3312090 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
12091 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0312092
12093 // Return Init()'s result after the transaction gets destroyed.
12094 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3312095 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0312096}
12097
[email protected]aeefc9e82010-02-19 16:18:2712098// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0112099TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2712100 HttpRequestInfo request;
12101 request.method = "GET";
bncce36dca22015-04-21 22:11:2312102 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012103 request.traffic_annotation =
12104 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2712105
12106 // First transaction will request a resource and receive a Basic challenge
12107 // with realm="first_realm".
12108 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312109 MockWrite(
12110 "GET / HTTP/1.1\r\n"
12111 "Host: www.example.org\r\n"
12112 "Connection: keep-alive\r\n"
12113 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712114 };
12115 MockRead data_reads1[] = {
12116 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12117 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12118 "\r\n"),
12119 };
12120
bnc691fda62016-08-12 00:43:1612121 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2712122 // for first_realm. The server will reject and provide a challenge with
12123 // second_realm.
12124 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312125 MockWrite(
12126 "GET / HTTP/1.1\r\n"
12127 "Host: www.example.org\r\n"
12128 "Connection: keep-alive\r\n"
12129 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
12130 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712131 };
12132 MockRead data_reads2[] = {
12133 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12134 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
12135 "\r\n"),
12136 };
12137
12138 // This again fails, and goes back to first_realm. Make sure that the
12139 // entry is removed from cache.
12140 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2312141 MockWrite(
12142 "GET / HTTP/1.1\r\n"
12143 "Host: www.example.org\r\n"
12144 "Connection: keep-alive\r\n"
12145 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
12146 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712147 };
12148 MockRead data_reads3[] = {
12149 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12150 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12151 "\r\n"),
12152 };
12153
12154 // Try one last time (with the correct password) and get the resource.
12155 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2312156 MockWrite(
12157 "GET / HTTP/1.1\r\n"
12158 "Host: www.example.org\r\n"
12159 "Connection: keep-alive\r\n"
12160 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
12161 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712162 };
12163 MockRead data_reads4[] = {
12164 MockRead("HTTP/1.1 200 OK\r\n"
12165 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5012166 "Content-Length: 5\r\n"
12167 "\r\n"
12168 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2712169 };
12170
Ryan Sleevib8d7ea02018-05-07 20:01:0112171 StaticSocketDataProvider data1(data_reads1, data_writes1);
12172 StaticSocketDataProvider data2(data_reads2, data_writes2);
12173 StaticSocketDataProvider data3(data_reads3, data_writes3);
12174 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0712175 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12176 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12177 session_deps_.socket_factory->AddSocketDataProvider(&data3);
12178 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2712179
[email protected]49639fa2011-12-20 23:22:4112180 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2712181
danakj1fd259a02016-04-16 03:17:0912182 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612183 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012184
[email protected]aeefc9e82010-02-19 16:18:2712185 // Issue the first request with Authorize headers. There should be a
12186 // password prompt for first_realm waiting to be filled in after the
12187 // transaction completes.
tfarina428341112016-09-22 13:38:2012188 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112189 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712190 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112191 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612192 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212193 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812194 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212195 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412196 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312197 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412198 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912199 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712200
12201 // Issue the second request with an incorrect password. There should be a
12202 // password prompt for second_realm waiting to be filled in after the
12203 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4112204 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1612205 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
12206 callback2.callback());
robpercival214763f2016-07-01 23:27:0112207 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712208 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112209 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612210 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212211 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812212 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212213 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412214 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312215 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412216 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912217 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712218
12219 // Issue the third request with another incorrect password. There should be
12220 // a password prompt for first_realm waiting to be filled in. If the password
12221 // prompt is not present, it indicates that the HttpAuthCacheEntry for
12222 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4112223 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1612224 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
12225 callback3.callback());
robpercival214763f2016-07-01 23:27:0112226 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712227 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0112228 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612229 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212230 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812231 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212232 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412233 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312234 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412235 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912236 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712237
12238 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4112239 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1612240 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
12241 callback4.callback());
robpercival214763f2016-07-01 23:27:0112242 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712243 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0112244 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612245 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212246 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812247 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2712248}
12249
Bence Béky230ac612017-08-30 19:17:0812250// Regression test for https://crbug.com/754395.
12251TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
12252 MockRead data_reads[] = {
12253 MockRead("HTTP/1.1 200 OK\r\n"),
12254 MockRead(kAlternativeServiceHttpHeader),
12255 MockRead("\r\n"),
12256 MockRead("hello world"),
12257 MockRead(SYNCHRONOUS, OK),
12258 };
12259
12260 HttpRequestInfo request;
12261 request.method = "GET";
12262 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012263 request.traffic_annotation =
12264 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0812265
Ryan Sleevib8d7ea02018-05-07 20:01:0112266 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0812267 session_deps_.socket_factory->AddSocketDataProvider(&data);
12268
12269 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912270 ssl.ssl_info.cert =
12271 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12272 ASSERT_TRUE(ssl.ssl_info.cert);
12273 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0812274 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12275
12276 TestCompletionCallback callback;
12277
12278 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12279 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12280
12281 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12282 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12283
12284 url::SchemeHostPort test_server(request.url);
12285 HttpServerProperties* http_server_properties =
12286 session->http_server_properties();
12287 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912288 http_server_properties
12289 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12290 .empty());
Bence Béky230ac612017-08-30 19:17:0812291
12292 EXPECT_THAT(callback.WaitForResult(), IsOk());
12293
12294 const HttpResponseInfo* response = trans.GetResponseInfo();
12295 ASSERT_TRUE(response);
12296 ASSERT_TRUE(response->headers);
12297 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12298 EXPECT_FALSE(response->was_fetched_via_spdy);
12299 EXPECT_FALSE(response->was_alpn_negotiated);
12300
12301 std::string response_data;
12302 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12303 EXPECT_EQ("hello world", response_data);
12304
12305 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912306 http_server_properties
12307 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12308 .empty());
Bence Béky230ac612017-08-30 19:17:0812309}
12310
bncd16676a2016-07-20 16:23:0112311TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5212312 MockRead data_reads[] = {
12313 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312314 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212315 MockRead("\r\n"),
12316 MockRead("hello world"),
12317 MockRead(SYNCHRONOUS, OK),
12318 };
12319
12320 HttpRequestInfo request;
12321 request.method = "GET";
bncb26024382016-06-29 02:39:4512322 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012323 request.traffic_annotation =
12324 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212325
Ryan Sleevib8d7ea02018-05-07 20:01:0112326 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212327 session_deps_.socket_factory->AddSocketDataProvider(&data);
12328
bncb26024382016-06-29 02:39:4512329 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912330 ssl.ssl_info.cert =
12331 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12332 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12334
bncc958faa2015-07-31 18:14:5212335 TestCompletionCallback callback;
12336
danakj1fd259a02016-04-16 03:17:0912337 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612338 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212339
tfarina428341112016-09-22 13:38:2012340 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112341 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212342
bncb26024382016-06-29 02:39:4512343 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012344 HttpServerProperties* http_server_properties =
12345 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412346 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912347 http_server_properties
12348 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12349 .empty());
bncc958faa2015-07-31 18:14:5212350
robpercival214763f2016-07-01 23:27:0112351 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212352
bnc691fda62016-08-12 00:43:1612353 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212354 ASSERT_TRUE(response);
12355 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212356 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12357 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212358 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212359
12360 std::string response_data;
bnc691fda62016-08-12 00:43:1612361 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212362 EXPECT_EQ("hello world", response_data);
12363
zhongyic4de03032017-05-19 04:07:3412364 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912365 http_server_properties->GetAlternativeServiceInfos(test_server,
12366 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412367 ASSERT_EQ(1u, alternative_service_info_vector.size());
12368 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12369 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412370 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212371}
12372
Matt Menke3233d8f22019-08-20 21:01:4912373TEST_F(HttpNetworkTransactionTest,
12374 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
12375 base::test::ScopedFeatureList feature_list;
12376 feature_list.InitWithFeatures(
12377 // enabled_features
12378 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
12379 // Need to partition connections by NetworkIsolationKey for
12380 // SpdySessionKeys to include NetworkIsolationKeys.
12381 features::kPartitionConnectionsByNetworkIsolationKey},
12382 // disabled_features
12383 {});
12384 // Since HttpServerProperties caches the feature value, have to create a new
12385 // one.
12386 session_deps_.http_server_properties =
12387 std::make_unique<HttpServerProperties>();
12388
12389 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
12390 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
12391 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
12392 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
12393
12394 MockRead data_reads[] = {
12395 MockRead("HTTP/1.1 200 OK\r\n"),
12396 MockRead(kAlternativeServiceHttpHeader),
12397 MockRead("\r\n"),
12398 MockRead("hello world"),
12399 MockRead(SYNCHRONOUS, OK),
12400 };
12401
12402 HttpRequestInfo request;
12403 request.method = "GET";
12404 request.url = GURL("https://www.example.org/");
12405 request.traffic_annotation =
12406 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12407 request.network_isolation_key = kNetworkIsolationKey1;
12408
12409 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12410 session_deps_.socket_factory->AddSocketDataProvider(&data);
12411
12412 SSLSocketDataProvider ssl(ASYNC, OK);
12413 ssl.ssl_info.cert =
12414 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12415 ASSERT_TRUE(ssl.ssl_info.cert);
12416 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12417
12418 TestCompletionCallback callback;
12419
12420 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12421 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12422
12423 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12424 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12425
12426 url::SchemeHostPort test_server(request.url);
12427 HttpServerProperties* http_server_properties =
12428 session->http_server_properties();
12429 EXPECT_TRUE(
12430 http_server_properties
12431 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
12432 .empty());
12433
12434 EXPECT_THAT(callback.WaitForResult(), IsOk());
12435
12436 const HttpResponseInfo* response = trans.GetResponseInfo();
12437 ASSERT_TRUE(response);
12438 ASSERT_TRUE(response->headers);
12439 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12440 EXPECT_FALSE(response->was_fetched_via_spdy);
12441 EXPECT_FALSE(response->was_alpn_negotiated);
12442
12443 std::string response_data;
12444 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12445 EXPECT_EQ("hello world", response_data);
12446
12447 AlternativeServiceInfoVector alternative_service_info_vector =
12448 http_server_properties->GetAlternativeServiceInfos(test_server,
12449 kNetworkIsolationKey1);
12450 ASSERT_EQ(1u, alternative_service_info_vector.size());
12451 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12452 EXPECT_EQ(alternative_service,
12453 alternative_service_info_vector[0].alternative_service());
12454
12455 // Make sure the alternative service information is only associated with
12456 // kNetworkIsolationKey1.
12457 EXPECT_TRUE(
12458 http_server_properties
12459 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12460 .empty());
12461 EXPECT_TRUE(
12462 http_server_properties
12463 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
12464 .empty());
12465}
12466
bnce3dd56f2016-06-01 10:37:1112467// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0112468TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112469 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1112470 MockRead data_reads[] = {
12471 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312472 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1112473 MockRead("\r\n"),
12474 MockRead("hello world"),
12475 MockRead(SYNCHRONOUS, OK),
12476 };
12477
12478 HttpRequestInfo request;
12479 request.method = "GET";
12480 request.url = GURL("http://www.example.org/");
12481 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012482 request.traffic_annotation =
12483 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112484
Ryan Sleevib8d7ea02018-05-07 20:01:0112485 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112486 session_deps_.socket_factory->AddSocketDataProvider(&data);
12487
12488 TestCompletionCallback callback;
12489
12490 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612491 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112492
12493 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012494 HttpServerProperties* http_server_properties =
12495 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412496 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912497 http_server_properties
12498 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12499 .empty());
bnce3dd56f2016-06-01 10:37:1112500
tfarina428341112016-09-22 13:38:2012501 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112502 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12503 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1112504
bnc691fda62016-08-12 00:43:1612505 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1112506 ASSERT_TRUE(response);
12507 ASSERT_TRUE(response->headers);
12508 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12509 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212510 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1112511
12512 std::string response_data;
bnc691fda62016-08-12 00:43:1612513 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1112514 EXPECT_EQ("hello world", response_data);
12515
zhongyic4de03032017-05-19 04:07:3412516 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912517 http_server_properties
12518 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12519 .empty());
bnce3dd56f2016-06-01 10:37:1112520}
12521
bnca86731e2017-04-17 12:31:2812522// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2512523// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0112524TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2512525 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2812526 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4512527
bnc8bef8da22016-05-30 01:28:2512528 HttpRequestInfo request;
12529 request.method = "GET";
bncb26024382016-06-29 02:39:4512530 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2512531 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012532 request.traffic_annotation =
12533 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2512534
12535 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12536 StaticSocketDataProvider first_data;
12537 first_data.set_connect_data(mock_connect);
12538 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512539 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612540 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512541 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2512542
12543 MockRead data_reads[] = {
12544 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12545 MockRead(ASYNC, OK),
12546 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112547 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2512548 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12549
12550 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12551
bnc525e175a2016-06-20 12:36:4012552 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2512553 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112554 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
12555 444);
bnc8bef8da22016-05-30 01:28:2512556 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112557 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712558 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12559 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2512560
bnc691fda62016-08-12 00:43:1612561 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2512562 TestCompletionCallback callback;
12563
tfarina428341112016-09-22 13:38:2012564 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2512565 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112566 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2512567}
12568
bnce3dd56f2016-06-01 10:37:1112569// Regression test for https://crbug.com/615497:
12570// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0112571TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112572 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1112573 HttpRequestInfo request;
12574 request.method = "GET";
12575 request.url = GURL("http://www.example.org/");
12576 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012577 request.traffic_annotation =
12578 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112579
12580 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12581 StaticSocketDataProvider first_data;
12582 first_data.set_connect_data(mock_connect);
12583 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
12584
12585 MockRead data_reads[] = {
12586 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12587 MockRead(ASYNC, OK),
12588 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112589 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112590 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12591
12592 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12593
bnc525e175a2016-06-20 12:36:4012594 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1112595 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112596 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1112597 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112598 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712599 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12600 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1112601
bnc691fda62016-08-12 00:43:1612602 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112603 TestCompletionCallback callback;
12604
tfarina428341112016-09-22 13:38:2012605 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1112606 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112607 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1112608}
12609
bncd16676a2016-07-20 16:23:0112610TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0812611 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0912612 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012613 HttpServerProperties* http_server_properties =
12614 session->http_server_properties();
bncb26024382016-06-29 02:39:4512615 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2112616 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0812617 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112618 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712619 test_server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212620 session->params().quic_params.supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4912621 EXPECT_EQ(1u,
12622 http_server_properties
12623 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12624 .size());
bnc4f575852015-10-14 18:35:0812625
12626 // Send a clear header.
12627 MockRead data_reads[] = {
12628 MockRead("HTTP/1.1 200 OK\r\n"),
12629 MockRead("Alt-Svc: clear\r\n"),
12630 MockRead("\r\n"),
12631 MockRead("hello world"),
12632 MockRead(SYNCHRONOUS, OK),
12633 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112634 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0812635 session_deps_.socket_factory->AddSocketDataProvider(&data);
12636
bncb26024382016-06-29 02:39:4512637 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912638 ssl.ssl_info.cert =
12639 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12640 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512641 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12642
bnc4f575852015-10-14 18:35:0812643 HttpRequestInfo request;
12644 request.method = "GET";
bncb26024382016-06-29 02:39:4512645 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012646 request.traffic_annotation =
12647 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0812648
12649 TestCompletionCallback callback;
12650
bnc691fda62016-08-12 00:43:1612651 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0812652
tfarina428341112016-09-22 13:38:2012653 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112654 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0812655
bnc691fda62016-08-12 00:43:1612656 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212657 ASSERT_TRUE(response);
12658 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0812659 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12660 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212661 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0812662
12663 std::string response_data;
bnc691fda62016-08-12 00:43:1612664 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0812665 EXPECT_EQ("hello world", response_data);
12666
zhongyic4de03032017-05-19 04:07:3412667 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912668 http_server_properties
12669 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12670 .empty());
bnc4f575852015-10-14 18:35:0812671}
12672
bncd16676a2016-07-20 16:23:0112673TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5212674 MockRead data_reads[] = {
12675 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312676 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
12677 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5212678 MockRead("hello world"),
12679 MockRead(SYNCHRONOUS, OK),
12680 };
12681
12682 HttpRequestInfo request;
12683 request.method = "GET";
bncb26024382016-06-29 02:39:4512684 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012685 request.traffic_annotation =
12686 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212687
Ryan Sleevib8d7ea02018-05-07 20:01:0112688 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212689 session_deps_.socket_factory->AddSocketDataProvider(&data);
12690
bncb26024382016-06-29 02:39:4512691 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912692 ssl.ssl_info.cert =
12693 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12694 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512695 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12696
bncc958faa2015-07-31 18:14:5212697 TestCompletionCallback callback;
12698
danakj1fd259a02016-04-16 03:17:0912699 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612700 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212701
tfarina428341112016-09-22 13:38:2012702 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112703 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212704
bncb26024382016-06-29 02:39:4512705 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4012706 HttpServerProperties* http_server_properties =
12707 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412708 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912709 http_server_properties
12710 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12711 .empty());
bncc958faa2015-07-31 18:14:5212712
robpercival214763f2016-07-01 23:27:0112713 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212714
bnc691fda62016-08-12 00:43:1612715 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212716 ASSERT_TRUE(response);
12717 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212718 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12719 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212720 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212721
12722 std::string response_data;
bnc691fda62016-08-12 00:43:1612723 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212724 EXPECT_EQ("hello world", response_data);
12725
zhongyic4de03032017-05-19 04:07:3412726 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912727 http_server_properties->GetAlternativeServiceInfos(test_server,
12728 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412729 ASSERT_EQ(2u, alternative_service_info_vector.size());
12730
12731 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
12732 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412733 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412734 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
12735 1234);
12736 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5412737 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5212738}
12739
bncd16676a2016-07-20 16:23:0112740TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612741 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212742 HostPortPair alternative("alternative.example.org", 443);
12743 std::string origin_url = "https://origin.example.org:443";
12744 std::string alternative_url = "https://alternative.example.org:443";
12745
12746 // Negotiate HTTP/1.1 with alternative.example.org.
12747 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612748 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212749 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12750
12751 // HTTP/1.1 data for request.
12752 MockWrite http_writes[] = {
12753 MockWrite("GET / HTTP/1.1\r\n"
12754 "Host: alternative.example.org\r\n"
12755 "Connection: keep-alive\r\n\r\n"),
12756 };
12757
12758 MockRead http_reads[] = {
12759 MockRead("HTTP/1.1 200 OK\r\n"
12760 "Content-Type: text/html; charset=iso-8859-1\r\n"
12761 "Content-Length: 40\r\n\r\n"
12762 "first HTTP/1.1 response from alternative"),
12763 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112764 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212765 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12766
12767 StaticSocketDataProvider data_refused;
12768 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12769 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12770
zhongyi3d4a55e72016-04-22 20:36:4612771 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0912772 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012773 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212774 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112775 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0212776 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112777 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712778 server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212779 HttpNetworkSession::Params().quic_params.supported_versions);
zhongyi48704c182015-12-07 07:52:0212780 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0512781 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
12782 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0212783
zhongyi48704c182015-12-07 07:52:0212784 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612785 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212786 request.method = "GET";
12787 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012788 request.traffic_annotation =
12789 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12790
zhongyi48704c182015-12-07 07:52:0212791 TestCompletionCallback callback;
12792 NetErrorDetails details;
12793 EXPECT_FALSE(details.quic_broken);
12794
tfarina428341112016-09-22 13:38:2012795 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612796 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212797 EXPECT_TRUE(details.quic_broken);
12798}
12799
bncd16676a2016-07-20 16:23:0112800TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612801 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212802 HostPortPair alternative1("alternative1.example.org", 443);
12803 HostPortPair alternative2("alternative2.example.org", 443);
12804 std::string origin_url = "https://origin.example.org:443";
12805 std::string alternative_url1 = "https://alternative1.example.org:443";
12806 std::string alternative_url2 = "https://alternative2.example.org:443";
12807
12808 // Negotiate HTTP/1.1 with alternative1.example.org.
12809 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612810 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212811 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12812
12813 // HTTP/1.1 data for request.
12814 MockWrite http_writes[] = {
12815 MockWrite("GET / HTTP/1.1\r\n"
12816 "Host: alternative1.example.org\r\n"
12817 "Connection: keep-alive\r\n\r\n"),
12818 };
12819
12820 MockRead http_reads[] = {
12821 MockRead("HTTP/1.1 200 OK\r\n"
12822 "Content-Type: text/html; charset=iso-8859-1\r\n"
12823 "Content-Length: 40\r\n\r\n"
12824 "first HTTP/1.1 response from alternative1"),
12825 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112826 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212827 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12828
12829 StaticSocketDataProvider data_refused;
12830 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12831 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12832
danakj1fd259a02016-04-16 03:17:0912833 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012834 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212835 session->http_server_properties();
12836
zhongyi3d4a55e72016-04-22 20:36:4612837 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0212838 AlternativeServiceInfoVector alternative_service_info_vector;
12839 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12840
bnc3472afd2016-11-17 15:27:2112841 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2112842 alternative_service_info_vector.push_back(
12843 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12844 alternative_service1, expiration,
Nick Harper72ade192019-07-17 03:30:4212845 session->params().quic_params.supported_versions));
bnc3472afd2016-11-17 15:27:2112846 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2112847 alternative_service_info_vector.push_back(
12848 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12849 alternative_service2, expiration,
Nick Harper72ade192019-07-17 03:30:4212850 session->params().quic_params.supported_versions));
zhongyi48704c182015-12-07 07:52:0212851
12852 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4912853 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0212854
12855 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0512856 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
12857 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4912858 EXPECT_EQ(2u, http_server_properties
12859 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
12860 .size());
zhongyi48704c182015-12-07 07:52:0212861
zhongyi48704c182015-12-07 07:52:0212862 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612863 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212864 request.method = "GET";
12865 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012866 request.traffic_annotation =
12867 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12868
zhongyi48704c182015-12-07 07:52:0212869 TestCompletionCallback callback;
12870 NetErrorDetails details;
12871 EXPECT_FALSE(details.quic_broken);
12872
tfarina428341112016-09-22 13:38:2012873 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612874 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212875 EXPECT_FALSE(details.quic_broken);
12876}
12877
bncd16676a2016-07-20 16:23:0112878TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4212879 HttpRequestInfo request;
12880 request.method = "GET";
bncb26024382016-06-29 02:39:4512881 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012882 request.traffic_annotation =
12883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4212884
[email protected]d973e99a2012-02-17 21:02:3612885 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4212886 StaticSocketDataProvider first_data;
12887 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712888 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512889 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612890 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4212892
12893 MockRead data_reads[] = {
12894 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12895 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612896 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4212897 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112898 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712899 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4212900
danakj1fd259a02016-04-16 03:17:0912901 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4212902
bnc525e175a2016-06-20 12:36:4012903 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312904 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4612905 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1112906 // Port must be < 1024, or the header will be ignored (since initial port was
12907 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2112908 // Port is ignored by MockConnect anyway.
12909 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12910 666);
bnc7dc7e1b42015-07-28 14:43:1212911 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112912 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712913 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4212914
bnc691fda62016-08-12 00:43:1612915 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112916 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4212917
tfarina428341112016-09-22 13:38:2012918 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12920 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4212921
bnc691fda62016-08-12 00:43:1612922 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212923 ASSERT_TRUE(response);
12924 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4212925 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12926
12927 std::string response_data;
bnc691fda62016-08-12 00:43:1612928 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4212929 EXPECT_EQ("hello world", response_data);
12930
zhongyic4de03032017-05-19 04:07:3412931 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912932 http_server_properties->GetAlternativeServiceInfos(server,
12933 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412934 ASSERT_EQ(1u, alternative_service_info_vector.size());
12935 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412936 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0512937 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
12938 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4212939}
12940
bnc55ff9da2015-08-19 18:42:3512941// Ensure that we are not allowed to redirect traffic via an alternate protocol
12942// to an unrestricted (port >= 1024) when the original traffic was on a
12943// restricted port (port < 1024). Ensure that we can redirect in all other
12944// cases.
bncd16676a2016-07-20 16:23:0112945TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1112946 HttpRequestInfo restricted_port_request;
12947 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512948 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112949 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012950 restricted_port_request.traffic_annotation =
12951 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112952
[email protected]d973e99a2012-02-17 21:02:3612953 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112954 StaticSocketDataProvider first_data;
12955 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712956 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112957
12958 MockRead data_reads[] = {
12959 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12960 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612961 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112962 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112963 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712964 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512965 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612966 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512967 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112968
danakj1fd259a02016-04-16 03:17:0912969 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112970
bnc525e175a2016-06-20 12:36:4012971 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312972 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112973 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112974 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12975 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212976 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112977 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712978 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12979 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112980
bnc691fda62016-08-12 00:43:1612981 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112982 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112983
tfarina428341112016-09-22 13:38:2012984 int rv = trans.Start(&restricted_port_request, callback.callback(),
12985 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112986 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112987 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0112988 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1912989}
[email protected]3912662a32011-10-04 00:51:1112990
bnc55ff9da2015-08-19 18:42:3512991// Ensure that we are allowed to redirect traffic via an alternate protocol to
12992// an unrestricted (port >= 1024) when the original traffic was on a restricted
12993// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0112994TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0712995 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1912996
12997 HttpRequestInfo restricted_port_request;
12998 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512999 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1913000 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013001 restricted_port_request.traffic_annotation =
13002 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1913003
13004 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13005 StaticSocketDataProvider first_data;
13006 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713007 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1913008
13009 MockRead data_reads[] = {
13010 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13011 MockRead("hello world"),
13012 MockRead(ASYNC, OK),
13013 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113014 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713015 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513016 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613017 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513018 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1913019
danakj1fd259a02016-04-16 03:17:0913020 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1913021
bnc525e175a2016-06-20 12:36:4013022 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1913023 session->http_server_properties();
13024 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113025 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13026 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213027 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113028 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713029 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13030 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1913031
bnc691fda62016-08-12 00:43:1613032 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1913033 TestCompletionCallback callback;
13034
tfarina428341112016-09-22 13:38:2013035 EXPECT_EQ(ERR_IO_PENDING,
13036 trans.Start(&restricted_port_request, callback.callback(),
13037 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1913038 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0113039 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113040}
13041
bnc55ff9da2015-08-19 18:42:3513042// Ensure that we are not allowed to redirect traffic via an alternate protocol
13043// to an unrestricted (port >= 1024) when the original traffic was on a
13044// restricted port (port < 1024). Ensure that we can redirect in all other
13045// cases.
bncd16676a2016-07-20 16:23:0113046TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1113047 HttpRequestInfo restricted_port_request;
13048 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513049 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113050 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013051 restricted_port_request.traffic_annotation =
13052 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113053
[email protected]d973e99a2012-02-17 21:02:3613054 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113055 StaticSocketDataProvider first_data;
13056 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713057 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113058
13059 MockRead data_reads[] = {
13060 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13061 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613062 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113063 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113064 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713065 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113066
bncb26024382016-06-29 02:39:4513067 SSLSocketDataProvider ssl(ASYNC, OK);
13068 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13069
danakj1fd259a02016-04-16 03:17:0913070 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113071
bnc525e175a2016-06-20 12:36:4013072 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313073 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113074 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113075 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13076 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213077 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113078 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713079 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13080 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113081
bnc691fda62016-08-12 00:43:1613082 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113083 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113084
tfarina428341112016-09-22 13:38:2013085 int rv = trans.Start(&restricted_port_request, callback.callback(),
13086 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113087 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113088 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113089 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113090}
13091
bnc55ff9da2015-08-19 18:42:3513092// Ensure that we are not allowed to redirect traffic via an alternate protocol
13093// to an unrestricted (port >= 1024) when the original traffic was on a
13094// restricted port (port < 1024). Ensure that we can redirect in all other
13095// cases.
bncd16676a2016-07-20 16:23:0113096TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1113097 HttpRequestInfo unrestricted_port_request;
13098 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513099 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113100 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013101 unrestricted_port_request.traffic_annotation =
13102 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113103
[email protected]d973e99a2012-02-17 21:02:3613104 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113105 StaticSocketDataProvider first_data;
13106 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713107 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113108
13109 MockRead data_reads[] = {
13110 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13111 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613112 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113113 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113114 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713115 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513116 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613117 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513118 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113119
danakj1fd259a02016-04-16 03:17:0913120 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113121
bnc525e175a2016-06-20 12:36:4013122 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313123 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113124 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113125 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13126 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213127 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113128 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713129 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13130 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113131
bnc691fda62016-08-12 00:43:1613132 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113133 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113134
bnc691fda62016-08-12 00:43:1613135 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina428341112016-09-22 13:38:2013136 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113137 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113138 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113139 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113140}
13141
bnc55ff9da2015-08-19 18:42:3513142// Ensure that we are not allowed to redirect traffic via an alternate protocol
13143// to an unrestricted (port >= 1024) when the original traffic was on a
13144// restricted port (port < 1024). Ensure that we can redirect in all other
13145// cases.
bncd16676a2016-07-20 16:23:0113146TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1113147 HttpRequestInfo unrestricted_port_request;
13148 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513149 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113150 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013151 unrestricted_port_request.traffic_annotation =
13152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113153
[email protected]d973e99a2012-02-17 21:02:3613154 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113155 StaticSocketDataProvider first_data;
13156 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713157 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113158
13159 MockRead data_reads[] = {
13160 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13161 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613162 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113163 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113164 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713165 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113166
bncb26024382016-06-29 02:39:4513167 SSLSocketDataProvider ssl(ASYNC, OK);
13168 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13169
danakj1fd259a02016-04-16 03:17:0913170 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113171
bnc525e175a2016-06-20 12:36:4013172 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313173 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2213174 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2113175 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13176 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213177 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113178 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713179 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13180 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113181
bnc691fda62016-08-12 00:43:1613182 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113183 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113184
bnc691fda62016-08-12 00:43:1613185 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina428341112016-09-22 13:38:2013186 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113187 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113188 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0113189 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113190}
13191
bnc55ff9da2015-08-19 18:42:3513192// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2113193// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
13194// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0113195TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0213196 HttpRequestInfo request;
13197 request.method = "GET";
bncce36dca22015-04-21 22:11:2313198 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013199 request.traffic_annotation =
13200 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0213201
13202 // The alternate protocol request will error out before we attempt to connect,
13203 // so only the standard HTTP request will try to connect.
13204 MockRead data_reads[] = {
13205 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13206 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613207 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0213208 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113209 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713210 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0213211
danakj1fd259a02016-04-16 03:17:0913212 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0213213
bnc525e175a2016-06-20 12:36:4013214 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0213215 session->http_server_properties();
13216 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2113217 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13218 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1213219 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113220 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713221 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13222 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0213223
bnc691fda62016-08-12 00:43:1613224 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0213225 TestCompletionCallback callback;
13226
tfarina428341112016-09-22 13:38:2013227 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113228 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0213229 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0113230 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213231
bnc691fda62016-08-12 00:43:1613232 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213233 ASSERT_TRUE(response);
13234 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0213235 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13236
13237 std::string response_data;
bnc691fda62016-08-12 00:43:1613238 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213239 EXPECT_EQ("hello world", response_data);
13240}
13241
bncd16676a2016-07-20 16:23:0113242TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5413243 HttpRequestInfo request;
13244 request.method = "GET";
bncb26024382016-06-29 02:39:4513245 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013246 request.traffic_annotation =
13247 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413248
13249 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213250 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313251 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213252 MockRead("\r\n"),
13253 MockRead("hello world"),
13254 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13255 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5413256
Ryan Sleevib8d7ea02018-05-07 20:01:0113257 StaticSocketDataProvider first_transaction(data_reads,
13258 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713259 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513260 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613261 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513262 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413263
bnc032658ba2016-09-26 18:17:1513264 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413265
Ryan Hamilton0239aac2018-05-19 00:03:1313266 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513267 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113268 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413269
Raul Tambre94493c652019-03-11 17:18:3513270 spdy::SpdySerializedFrame resp(
13271 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313272 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413273 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113274 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413275 };
13276
Ryan Sleevib8d7ea02018-05-07 20:01:0113277 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713278 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413279
[email protected]d973e99a2012-02-17 21:02:3613280 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113281 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513282 hanging_non_alternate_protocol_socket.set_connect_data(
13283 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713284 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513285 &hanging_non_alternate_protocol_socket);
13286
[email protected]49639fa2011-12-20 23:22:4113287 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413288
danakj1fd259a02016-04-16 03:17:0913289 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813290 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913291 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413292
tfarina428341112016-09-22 13:38:2013293 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113294 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13295 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413296
13297 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213298 ASSERT_TRUE(response);
13299 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413300 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13301
13302 std::string response_data;
robpercival214763f2016-07-01 23:27:0113303 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413304 EXPECT_EQ("hello world", response_data);
13305
bnc87dcefc2017-05-25 12:47:5813306 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913307 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413308
tfarina428341112016-09-22 13:38:2013309 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113310 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13311 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413312
13313 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213314 ASSERT_TRUE(response);
13315 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213316 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313317 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213318 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413319
robpercival214763f2016-07-01 23:27:0113320 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413321 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5413322}
13323
bncd16676a2016-07-20 16:23:0113324TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5513325 HttpRequestInfo request;
13326 request.method = "GET";
bncb26024382016-06-29 02:39:4513327 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013328 request.traffic_annotation =
13329 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513330
bncb26024382016-06-29 02:39:4513331 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5513332 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213333 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313334 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213335 MockRead("\r\n"),
13336 MockRead("hello world"),
13337 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13338 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513339 };
13340
Ryan Sleevib8d7ea02018-05-07 20:01:0113341 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4513342 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5513343
bncb26024382016-06-29 02:39:4513344 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913345 ssl_http11.ssl_info.cert =
13346 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13347 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4513348 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
13349
13350 // Second transaction starts an alternative and a non-alternative Job.
13351 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3613352 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113353 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1813354 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1813355 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
13356
Ryan Sleevib8d7ea02018-05-07 20:01:0113357 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1813358 hanging_socket2.set_connect_data(never_finishing_connect);
13359 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5513360
bncb26024382016-06-29 02:39:4513361 // Third transaction starts an alternative and a non-alternative job.
13362 // The non-alternative job hangs, but the alternative one succeeds.
13363 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1313364 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4513365 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1313366 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4513367 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5513368 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113369 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5513370 };
Raul Tambre94493c652019-03-11 17:18:3513371 spdy::SpdySerializedFrame resp1(
13372 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313373 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3513374 spdy::SpdySerializedFrame resp2(
13375 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1313376 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5513377 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113378 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
13379 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1313380 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5513381 };
13382
Ryan Sleevib8d7ea02018-05-07 20:01:0113383 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713384 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5513385
bnc032658ba2016-09-26 18:17:1513386 AddSSLSocketData();
bncb26024382016-06-29 02:39:4513387
Ryan Sleevib8d7ea02018-05-07 20:01:0113388 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1813389 hanging_socket3.set_connect_data(never_finishing_connect);
13390 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5513391
danakj1fd259a02016-04-16 03:17:0913392 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4113393 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5013394 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513395
tfarina428341112016-09-22 13:38:2013396 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113397 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13398 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513399
13400 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5213401 ASSERT_TRUE(response);
13402 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513403 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13404
13405 std::string response_data;
robpercival214763f2016-07-01 23:27:0113406 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513407 EXPECT_EQ("hello world", response_data);
13408
[email protected]49639fa2011-12-20 23:22:4113409 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5013410 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:2013411 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113412 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513413
[email protected]49639fa2011-12-20 23:22:4113414 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5013415 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:2013416 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113417 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513418
robpercival214763f2016-07-01 23:27:0113419 EXPECT_THAT(callback2.WaitForResult(), IsOk());
13420 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513421
13422 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5213423 ASSERT_TRUE(response);
13424 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213425 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513426 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213427 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113428 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513429 EXPECT_EQ("hello!", response_data);
13430
13431 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5213432 ASSERT_TRUE(response);
13433 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213434 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513435 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213436 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113437 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513438 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5513439}
13440
bncd16676a2016-07-20 16:23:0113441TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5313442 session_deps_.host_resolver->set_synchronous_mode(true);
13443
[email protected]2d6728692011-03-12 01:39:5513444 HttpRequestInfo request;
13445 request.method = "GET";
bncb26024382016-06-29 02:39:4513446 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013447 request.traffic_annotation =
13448 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513449
13450 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213451 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313452 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213453 MockRead("\r\n"),
13454 MockRead("hello world"),
13455 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13456 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513457 };
13458
Ryan Sleevib8d7ea02018-05-07 20:01:0113459 StaticSocketDataProvider first_transaction(data_reads,
13460 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713461 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513462
[email protected]8ddf8322012-02-23 18:08:0613463 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913464 ssl.ssl_info.cert =
13465 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13466 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0713467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513468
[email protected]d973e99a2012-02-17 21:02:3613469 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113470 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513471 hanging_alternate_protocol_socket.set_connect_data(
13472 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713473 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513474 &hanging_alternate_protocol_socket);
13475
bncb26024382016-06-29 02:39:4513476 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0113477 StaticSocketDataProvider second_transaction(data_reads,
13478 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1813479 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4513480 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513481
[email protected]49639fa2011-12-20 23:22:4113482 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5513483
danakj1fd259a02016-04-16 03:17:0913484 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813485 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913486 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513487
tfarina428341112016-09-22 13:38:2013488 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113489 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13490 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513491
13492 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213493 ASSERT_TRUE(response);
13494 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513495 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13496
13497 std::string response_data;
robpercival214763f2016-07-01 23:27:0113498 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513499 EXPECT_EQ("hello world", response_data);
13500
bnc87dcefc2017-05-25 12:47:5813501 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913502 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513503
tfarina428341112016-09-22 13:38:2013504 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113505 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13506 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513507
13508 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213509 ASSERT_TRUE(response);
13510 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513511 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13512 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213513 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5513514
robpercival214763f2016-07-01 23:27:0113515 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513516 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5513517}
13518
bnc2e884782016-08-11 19:45:1913519// Test that proxy is resolved using the origin url,
13520// regardless of the alternative server.
13521TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
13522 // Configure proxy to bypass www.example.org, which is the origin URL.
13523 ProxyConfig proxy_config;
13524 proxy_config.proxy_rules().ParseFromString("myproxy:70");
13525 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4913526 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
13527 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1913528
13529 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1913530 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1913531 &capturing_proxy_resolver);
13532
13533 TestNetLog net_log;
13534
Bence Béky53a5aef2018-03-29 21:54:1213535 session_deps_.proxy_resolution_service =
13536 std::make_unique<ProxyResolutionService>(
13537 std::move(proxy_config_service), std::move(proxy_resolver_factory),
13538 &net_log);
bnc2e884782016-08-11 19:45:1913539
13540 session_deps_.net_log = &net_log;
13541
13542 // Configure alternative service with a hostname that is not bypassed by the
13543 // proxy.
13544 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13545 HttpServerProperties* http_server_properties =
13546 session->http_server_properties();
13547 url::SchemeHostPort server("https", "www.example.org", 443);
13548 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2113549 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1913550 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113551 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713552 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1913553
13554 // Non-alternative job should hang.
13555 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113556 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1913557 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
13558 session_deps_.socket_factory->AddSocketDataProvider(
13559 &hanging_alternate_protocol_socket);
13560
bnc032658ba2016-09-26 18:17:1513561 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1913562
13563 HttpRequestInfo request;
13564 request.method = "GET";
13565 request.url = GURL("https://www.example.org/");
13566 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013567 request.traffic_annotation =
13568 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1913569
Ryan Hamilton0239aac2018-05-19 00:03:1313570 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1913571 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
13572
13573 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
13574
Ryan Hamilton0239aac2018-05-19 00:03:1313575 spdy::SpdySerializedFrame resp(
13576 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
13577 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1913578 MockRead spdy_reads[] = {
13579 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
13580 };
13581
Ryan Sleevib8d7ea02018-05-07 20:01:0113582 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1913583 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
13584
13585 TestCompletionCallback callback;
13586
13587 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13588
tfarina428341112016-09-22 13:38:2013589 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1913590 EXPECT_THAT(callback.GetResult(rv), IsOk());
13591
13592 const HttpResponseInfo* response = trans.GetResponseInfo();
13593 ASSERT_TRUE(response);
13594 ASSERT_TRUE(response->headers);
13595 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
13596 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213597 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1913598
13599 std::string response_data;
13600 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13601 EXPECT_EQ("hello!", response_data);
13602
13603 // Origin host bypasses proxy, no resolution should have happened.
13604 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
13605}
13606
bncd16676a2016-07-20 16:23:0113607TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1113608 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4213609 proxy_config.set_auto_detect(true);
13610 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1113611
sammc5dd160c2015-04-02 02:43:1313612 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4913613 session_deps_.proxy_resolution_service =
13614 std::make_unique<ProxyResolutionService>(
13615 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
13616 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
13617 std::make_unique<CapturingProxyResolverFactory>(
13618 &capturing_proxy_resolver),
13619 nullptr);
vishal.b62985ca92015-04-17 08:45:5113620 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0713621 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1113622
13623 HttpRequestInfo request;
13624 request.method = "GET";
bncb26024382016-06-29 02:39:4513625 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013626 request.traffic_annotation =
13627 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1113628
13629 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213630 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313631 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213632 MockRead("\r\n"),
13633 MockRead("hello world"),
13634 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13635 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1113636 };
13637
Ryan Sleevib8d7ea02018-05-07 20:01:0113638 StaticSocketDataProvider first_transaction(data_reads,
13639 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713640 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513641 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613642 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513643 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1113644
bnc032658ba2016-09-26 18:17:1513645 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1113646
Ryan Hamilton0239aac2018-05-19 00:03:1313647 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513648 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1113649 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313650 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2513651 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13652 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1313653 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4113654 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1113655 };
13656
[email protected]d911f1b2010-05-05 22:39:4213657 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
13658
Raul Tambre94493c652019-03-11 17:18:3513659 spdy::SpdySerializedFrame resp(
13660 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313661 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1113662 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113663 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
13664 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1113665 };
13666
Ryan Sleevib8d7ea02018-05-07 20:01:0113667 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713668 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1113669
[email protected]d973e99a2012-02-17 21:02:3613670 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113671 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513672 hanging_non_alternate_protocol_socket.set_connect_data(
13673 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713674 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513675 &hanging_non_alternate_protocol_socket);
13676
[email protected]49639fa2011-12-20 23:22:4113677 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1113678
danakj1fd259a02016-04-16 03:17:0913679 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813680 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913681 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113682
tfarina428341112016-09-22 13:38:2013683 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4113684 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13685 EXPECT_THAT(callback.WaitForResult(), IsOk());
13686
13687 const HttpResponseInfo* response = trans->GetResponseInfo();
13688 ASSERT_TRUE(response);
13689 ASSERT_TRUE(response->headers);
13690 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
13691 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213692 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4113693
13694 std::string response_data;
13695 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
13696 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1113697
bnc87dcefc2017-05-25 12:47:5813698 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913699 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113700
tfarina428341112016-09-22 13:38:2013701 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113702 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13703 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1113704
mmenkea2dcd3bf2016-08-16 21:49:4113705 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213706 ASSERT_TRUE(response);
13707 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213708 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313709 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213710 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1113711
robpercival214763f2016-07-01 23:27:0113712 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1113713 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4513714 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
13715 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313716 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2313717 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313718 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1113719
[email protected]029c83b62013-01-24 05:28:2013720 LoadTimingInfo load_timing_info;
13721 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
13722 TestLoadTimingNotReusedWithPac(load_timing_info,
13723 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1113724}
[email protected]631f1322010-04-30 17:59:1113725
bncd16676a2016-07-20 16:23:0113726TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4813727 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5413728 HttpRequestInfo request;
13729 request.method = "GET";
bncb26024382016-06-29 02:39:4513730 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013731 request.traffic_annotation =
13732 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413733
13734 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213735 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313736 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213737 MockRead("\r\n"),
13738 MockRead("hello world"),
13739 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5413740 };
13741
Ryan Sleevib8d7ea02018-05-07 20:01:0113742 StaticSocketDataProvider first_transaction(data_reads,
13743 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713744 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513745 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613746 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513747 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413748
bnc032658ba2016-09-26 18:17:1513749 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413750
Ryan Hamilton0239aac2018-05-19 00:03:1313751 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513752 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113753 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413754
Raul Tambre94493c652019-03-11 17:18:3513755 spdy::SpdySerializedFrame resp(
13756 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313757 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413758 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113759 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413760 };
13761
Ryan Sleevib8d7ea02018-05-07 20:01:0113762 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713763 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413764
[email protected]83039bb2011-12-09 18:43:5513765 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413766
danakj1fd259a02016-04-16 03:17:0913767 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5413768
bnc87dcefc2017-05-25 12:47:5813769 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913770 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413771
tfarina428341112016-09-22 13:38:2013772 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113773 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13774 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413775
13776 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213777 ASSERT_TRUE(response);
13778 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413779 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13780
13781 std::string response_data;
robpercival214763f2016-07-01 23:27:0113782 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413783 EXPECT_EQ("hello world", response_data);
13784
13785 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2513786 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4013787 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1113788 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3413789 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
13790 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2713791 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5213792 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3813793
bnc87dcefc2017-05-25 12:47:5813794 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913795 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413796
tfarina428341112016-09-22 13:38:2013797 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113798 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13799 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413800
13801 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213802 ASSERT_TRUE(response);
13803 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213804 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313805 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213806 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413807
robpercival214763f2016-07-01 23:27:0113808 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413809 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4213810}
13811
[email protected]044de0642010-06-17 10:42:1513812// GenerateAuthToken is a mighty big test.
13813// It tests all permutation of GenerateAuthToken behavior:
13814// - Synchronous and Asynchronous completion.
13815// - OK or error on completion.
13816// - Direct connection, non-authenticating proxy, and authenticating proxy.
13817// - HTTP or HTTPS backend (to include proxy tunneling).
13818// - Non-authenticating and authenticating backend.
13819//
[email protected]fe3b7dc2012-02-03 19:52:0913820// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1513821// problems generating an auth token for an authenticating proxy, we don't
13822// need to test all permutations of the backend server).
13823//
13824// The test proceeds by going over each of the configuration cases, and
13825// potentially running up to three rounds in each of the tests. The TestConfig
13826// specifies both the configuration for the test as well as the expectations
13827// for the results.
bncd16676a2016-07-20 16:23:0113828TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5013829 static const char kServer[] = "http://www.example.com";
13830 static const char kSecureServer[] = "https://www.example.com";
13831 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1513832
13833 enum AuthTiming {
13834 AUTH_NONE,
13835 AUTH_SYNC,
13836 AUTH_ASYNC,
13837 };
13838
13839 const MockWrite kGet(
13840 "GET / HTTP/1.1\r\n"
13841 "Host: www.example.com\r\n"
13842 "Connection: keep-alive\r\n\r\n");
13843 const MockWrite kGetProxy(
13844 "GET http://www.example.com/ HTTP/1.1\r\n"
13845 "Host: www.example.com\r\n"
13846 "Proxy-Connection: keep-alive\r\n\r\n");
13847 const MockWrite kGetAuth(
13848 "GET / HTTP/1.1\r\n"
13849 "Host: www.example.com\r\n"
13850 "Connection: keep-alive\r\n"
13851 "Authorization: auth_token\r\n\r\n");
13852 const MockWrite kGetProxyAuth(
13853 "GET http://www.example.com/ HTTP/1.1\r\n"
13854 "Host: www.example.com\r\n"
13855 "Proxy-Connection: keep-alive\r\n"
13856 "Proxy-Authorization: auth_token\r\n\r\n");
13857 const MockWrite kGetAuthThroughProxy(
13858 "GET http://www.example.com/ HTTP/1.1\r\n"
13859 "Host: www.example.com\r\n"
13860 "Proxy-Connection: keep-alive\r\n"
13861 "Authorization: auth_token\r\n\r\n");
13862 const MockWrite kGetAuthWithProxyAuth(
13863 "GET http://www.example.com/ HTTP/1.1\r\n"
13864 "Host: www.example.com\r\n"
13865 "Proxy-Connection: keep-alive\r\n"
13866 "Proxy-Authorization: auth_token\r\n"
13867 "Authorization: auth_token\r\n\r\n");
13868 const MockWrite kConnect(
13869 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713870 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513871 "Proxy-Connection: keep-alive\r\n\r\n");
13872 const MockWrite kConnectProxyAuth(
13873 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713874 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513875 "Proxy-Connection: keep-alive\r\n"
13876 "Proxy-Authorization: auth_token\r\n\r\n");
13877
13878 const MockRead kSuccess(
13879 "HTTP/1.1 200 OK\r\n"
13880 "Content-Type: text/html; charset=iso-8859-1\r\n"
13881 "Content-Length: 3\r\n\r\n"
13882 "Yes");
13883 const MockRead kFailure(
13884 "Should not be called.");
13885 const MockRead kServerChallenge(
13886 "HTTP/1.1 401 Unauthorized\r\n"
13887 "WWW-Authenticate: Mock realm=server\r\n"
13888 "Content-Type: text/html; charset=iso-8859-1\r\n"
13889 "Content-Length: 14\r\n\r\n"
13890 "Unauthorized\r\n");
13891 const MockRead kProxyChallenge(
13892 "HTTP/1.1 407 Unauthorized\r\n"
13893 "Proxy-Authenticate: Mock realm=proxy\r\n"
13894 "Proxy-Connection: close\r\n"
13895 "Content-Type: text/html; charset=iso-8859-1\r\n"
13896 "Content-Length: 14\r\n\r\n"
13897 "Unauthorized\r\n");
13898 const MockRead kProxyConnected(
13899 "HTTP/1.1 200 Connection Established\r\n\r\n");
13900
13901 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
13902 // no constructors, but the C++ compiler on Windows warns about
13903 // unspecified data in compound literals. So, moved to using constructors,
13904 // and TestRound's created with the default constructor should not be used.
13905 struct TestRound {
13906 TestRound()
Raul Tambre94493c652019-03-11 17:18:3513907 : expected_rv(ERR_UNEXPECTED),
13908 extra_write(nullptr),
13909 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4313910 TestRound(const MockWrite& write_arg,
13911 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1513912 int expected_rv_arg)
13913 : write(write_arg),
13914 read(read_arg),
13915 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3513916 extra_write(nullptr),
13917 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1513918 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
13919 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0113920 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1513921 : write(write_arg),
13922 read(read_arg),
13923 expected_rv(expected_rv_arg),
13924 extra_write(extra_write_arg),
13925 extra_read(extra_read_arg) {
13926 }
13927 MockWrite write;
13928 MockRead read;
13929 int expected_rv;
13930 const MockWrite* extra_write;
13931 const MockRead* extra_read;
13932 };
13933
13934 static const int kNoSSL = 500;
13935
13936 struct TestConfig {
asanka463ca4262016-11-16 02:34:3113937 int line_number;
thestig9d3bb0c2015-01-24 00:49:5113938 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1513939 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3113940 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5113941 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1513942 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3113943 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1513944 int num_auth_rounds;
13945 int first_ssl_round;
asankae2257db2016-10-11 22:03:1613946 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1513947 } test_configs[] = {
asankac93076192016-10-03 15:46:0213948 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113949 {__LINE__,
13950 nullptr,
asankac93076192016-10-03 15:46:0213951 AUTH_NONE,
13952 OK,
13953 kServer,
13954 AUTH_NONE,
13955 OK,
13956 1,
13957 kNoSSL,
13958 {TestRound(kGet, kSuccess, OK)}},
13959 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113960 {__LINE__,
13961 nullptr,
asankac93076192016-10-03 15:46:0213962 AUTH_NONE,
13963 OK,
13964 kServer,
13965 AUTH_SYNC,
13966 OK,
13967 2,
13968 kNoSSL,
13969 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513970 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113971 {__LINE__,
13972 nullptr,
asankac93076192016-10-03 15:46:0213973 AUTH_NONE,
13974 OK,
13975 kServer,
13976 AUTH_SYNC,
13977 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613978 3,
13979 kNoSSL,
13980 {TestRound(kGet, kServerChallenge, OK),
13981 TestRound(kGet, kServerChallenge, OK),
13982 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113983 {__LINE__,
13984 nullptr,
asankae2257db2016-10-11 22:03:1613985 AUTH_NONE,
13986 OK,
13987 kServer,
13988 AUTH_SYNC,
13989 ERR_UNSUPPORTED_AUTH_SCHEME,
13990 2,
13991 kNoSSL,
13992 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113993 {__LINE__,
13994 nullptr,
asankae2257db2016-10-11 22:03:1613995 AUTH_NONE,
13996 OK,
13997 kServer,
13998 AUTH_SYNC,
13999 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
14000 2,
14001 kNoSSL,
14002 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114003 {__LINE__,
14004 kProxy,
asankae2257db2016-10-11 22:03:1614005 AUTH_SYNC,
14006 ERR_FAILED,
14007 kServer,
14008 AUTH_NONE,
14009 OK,
14010 2,
14011 kNoSSL,
14012 {TestRound(kGetProxy, kProxyChallenge, OK),
14013 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114014 {__LINE__,
14015 kProxy,
asankae2257db2016-10-11 22:03:1614016 AUTH_ASYNC,
14017 ERR_FAILED,
14018 kServer,
14019 AUTH_NONE,
14020 OK,
14021 2,
14022 kNoSSL,
14023 {TestRound(kGetProxy, kProxyChallenge, OK),
14024 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114025 {__LINE__,
14026 nullptr,
asankae2257db2016-10-11 22:03:1614027 AUTH_NONE,
14028 OK,
14029 kServer,
14030 AUTH_SYNC,
14031 ERR_FAILED,
asankac93076192016-10-03 15:46:0214032 2,
14033 kNoSSL,
14034 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614035 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114036 {__LINE__,
14037 nullptr,
asankae2257db2016-10-11 22:03:1614038 AUTH_NONE,
14039 OK,
14040 kServer,
14041 AUTH_ASYNC,
14042 ERR_FAILED,
14043 2,
14044 kNoSSL,
14045 {TestRound(kGet, kServerChallenge, OK),
14046 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114047 {__LINE__,
14048 nullptr,
asankac93076192016-10-03 15:46:0214049 AUTH_NONE,
14050 OK,
14051 kServer,
14052 AUTH_ASYNC,
14053 OK,
14054 2,
14055 kNoSSL,
14056 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514057 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114058 {__LINE__,
14059 nullptr,
asankac93076192016-10-03 15:46:0214060 AUTH_NONE,
14061 OK,
14062 kServer,
14063 AUTH_ASYNC,
14064 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614065 3,
asankac93076192016-10-03 15:46:0214066 kNoSSL,
14067 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614068 // The second round uses a HttpAuthHandlerMock that always succeeds.
14069 TestRound(kGet, kServerChallenge, OK),
14070 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214071 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114072 {__LINE__,
14073 kProxy,
asankac93076192016-10-03 15:46:0214074 AUTH_NONE,
14075 OK,
14076 kServer,
14077 AUTH_NONE,
14078 OK,
14079 1,
14080 kNoSSL,
14081 {TestRound(kGetProxy, kSuccess, OK)}},
14082 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114083 {__LINE__,
14084 kProxy,
asankac93076192016-10-03 15:46:0214085 AUTH_NONE,
14086 OK,
14087 kServer,
14088 AUTH_SYNC,
14089 OK,
14090 2,
14091 kNoSSL,
14092 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514093 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114094 {__LINE__,
14095 kProxy,
asankac93076192016-10-03 15:46:0214096 AUTH_NONE,
14097 OK,
14098 kServer,
14099 AUTH_SYNC,
14100 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614101 3,
asankac93076192016-10-03 15:46:0214102 kNoSSL,
14103 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614104 TestRound(kGetProxy, kServerChallenge, OK),
14105 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114106 {__LINE__,
14107 kProxy,
asankac93076192016-10-03 15:46:0214108 AUTH_NONE,
14109 OK,
14110 kServer,
14111 AUTH_ASYNC,
14112 OK,
14113 2,
14114 kNoSSL,
14115 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514116 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114117 {__LINE__,
14118 kProxy,
asankac93076192016-10-03 15:46:0214119 AUTH_NONE,
14120 OK,
14121 kServer,
14122 AUTH_ASYNC,
14123 ERR_INVALID_AUTH_CREDENTIALS,
14124 2,
14125 kNoSSL,
14126 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614127 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214128 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114129 {__LINE__,
14130 kProxy,
asankac93076192016-10-03 15:46:0214131 AUTH_SYNC,
14132 OK,
14133 kServer,
14134 AUTH_NONE,
14135 OK,
14136 2,
14137 kNoSSL,
14138 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514139 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114140 {__LINE__,
14141 kProxy,
asankac93076192016-10-03 15:46:0214142 AUTH_SYNC,
14143 ERR_INVALID_AUTH_CREDENTIALS,
14144 kServer,
14145 AUTH_NONE,
14146 OK,
14147 2,
14148 kNoSSL,
14149 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614150 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114151 {__LINE__,
14152 kProxy,
asankac93076192016-10-03 15:46:0214153 AUTH_ASYNC,
14154 OK,
14155 kServer,
14156 AUTH_NONE,
14157 OK,
14158 2,
14159 kNoSSL,
14160 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514161 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114162 {__LINE__,
14163 kProxy,
asankac93076192016-10-03 15:46:0214164 AUTH_ASYNC,
14165 ERR_INVALID_AUTH_CREDENTIALS,
14166 kServer,
14167 AUTH_NONE,
14168 OK,
14169 2,
14170 kNoSSL,
14171 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614172 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114173 {__LINE__,
14174 kProxy,
14175 AUTH_ASYNC,
14176 ERR_INVALID_AUTH_CREDENTIALS,
14177 kServer,
14178 AUTH_NONE,
14179 OK,
14180 3,
14181 kNoSSL,
14182 {TestRound(kGetProxy, kProxyChallenge, OK),
14183 TestRound(kGetProxy, kProxyChallenge, OK),
14184 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214185 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114186 {__LINE__,
14187 kProxy,
asankac93076192016-10-03 15:46:0214188 AUTH_SYNC,
14189 OK,
14190 kServer,
14191 AUTH_SYNC,
14192 OK,
14193 3,
14194 kNoSSL,
14195 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514196 TestRound(kGetProxyAuth, kServerChallenge, OK),
14197 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114198 {__LINE__,
14199 kProxy,
asankac93076192016-10-03 15:46:0214200 AUTH_SYNC,
14201 OK,
14202 kServer,
14203 AUTH_SYNC,
14204 ERR_INVALID_AUTH_CREDENTIALS,
14205 3,
14206 kNoSSL,
14207 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514208 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614209 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114210 {__LINE__,
14211 kProxy,
asankac93076192016-10-03 15:46:0214212 AUTH_ASYNC,
14213 OK,
14214 kServer,
14215 AUTH_SYNC,
14216 OK,
14217 3,
14218 kNoSSL,
14219 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514220 TestRound(kGetProxyAuth, kServerChallenge, OK),
14221 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114222 {__LINE__,
14223 kProxy,
asankac93076192016-10-03 15:46:0214224 AUTH_ASYNC,
14225 OK,
14226 kServer,
14227 AUTH_SYNC,
14228 ERR_INVALID_AUTH_CREDENTIALS,
14229 3,
14230 kNoSSL,
14231 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514232 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614233 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114234 {__LINE__,
14235 kProxy,
asankac93076192016-10-03 15:46:0214236 AUTH_SYNC,
14237 OK,
14238 kServer,
14239 AUTH_ASYNC,
14240 OK,
14241 3,
14242 kNoSSL,
14243 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514244 TestRound(kGetProxyAuth, kServerChallenge, OK),
14245 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114246 {__LINE__,
14247 kProxy,
14248 AUTH_SYNC,
14249 ERR_INVALID_AUTH_CREDENTIALS,
14250 kServer,
14251 AUTH_ASYNC,
14252 OK,
14253 4,
14254 kNoSSL,
14255 {TestRound(kGetProxy, kProxyChallenge, OK),
14256 TestRound(kGetProxy, kProxyChallenge, OK),
14257 TestRound(kGetProxyAuth, kServerChallenge, OK),
14258 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
14259 {__LINE__,
14260 kProxy,
asankac93076192016-10-03 15:46:0214261 AUTH_SYNC,
14262 OK,
14263 kServer,
14264 AUTH_ASYNC,
14265 ERR_INVALID_AUTH_CREDENTIALS,
14266 3,
14267 kNoSSL,
14268 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514269 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614270 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114271 {__LINE__,
14272 kProxy,
asankac93076192016-10-03 15:46:0214273 AUTH_ASYNC,
14274 OK,
14275 kServer,
14276 AUTH_ASYNC,
14277 OK,
14278 3,
14279 kNoSSL,
14280 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514281 TestRound(kGetProxyAuth, kServerChallenge, OK),
14282 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114283 {__LINE__,
14284 kProxy,
asankac93076192016-10-03 15:46:0214285 AUTH_ASYNC,
14286 OK,
14287 kServer,
14288 AUTH_ASYNC,
14289 ERR_INVALID_AUTH_CREDENTIALS,
14290 3,
14291 kNoSSL,
14292 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514293 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614294 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114295 {__LINE__,
14296 kProxy,
14297 AUTH_ASYNC,
14298 ERR_INVALID_AUTH_CREDENTIALS,
14299 kServer,
14300 AUTH_ASYNC,
14301 ERR_INVALID_AUTH_CREDENTIALS,
14302 4,
14303 kNoSSL,
14304 {TestRound(kGetProxy, kProxyChallenge, OK),
14305 TestRound(kGetProxy, kProxyChallenge, OK),
14306 TestRound(kGetProxyAuth, kServerChallenge, OK),
14307 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214308 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114309 {__LINE__,
14310 nullptr,
asankac93076192016-10-03 15:46:0214311 AUTH_NONE,
14312 OK,
14313 kSecureServer,
14314 AUTH_NONE,
14315 OK,
14316 1,
14317 0,
14318 {TestRound(kGet, kSuccess, OK)}},
14319 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114320 {__LINE__,
14321 nullptr,
asankac93076192016-10-03 15:46:0214322 AUTH_NONE,
14323 OK,
14324 kSecureServer,
14325 AUTH_SYNC,
14326 OK,
14327 2,
14328 0,
14329 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514330 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114331 {__LINE__,
14332 nullptr,
asankac93076192016-10-03 15:46:0214333 AUTH_NONE,
14334 OK,
14335 kSecureServer,
14336 AUTH_SYNC,
14337 ERR_INVALID_AUTH_CREDENTIALS,
14338 2,
14339 0,
asankae2257db2016-10-11 22:03:1614340 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114341 {__LINE__,
14342 nullptr,
asankac93076192016-10-03 15:46:0214343 AUTH_NONE,
14344 OK,
14345 kSecureServer,
14346 AUTH_ASYNC,
14347 OK,
14348 2,
14349 0,
14350 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514351 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114352 {__LINE__,
14353 nullptr,
asankac93076192016-10-03 15:46:0214354 AUTH_NONE,
14355 OK,
14356 kSecureServer,
14357 AUTH_ASYNC,
14358 ERR_INVALID_AUTH_CREDENTIALS,
14359 2,
14360 0,
asankae2257db2016-10-11 22:03:1614361 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214362 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114363 {__LINE__,
14364 kProxy,
asankac93076192016-10-03 15:46:0214365 AUTH_NONE,
14366 OK,
14367 kSecureServer,
14368 AUTH_NONE,
14369 OK,
14370 1,
14371 0,
14372 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
14373 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114374 {__LINE__,
14375 kProxy,
asankac93076192016-10-03 15:46:0214376 AUTH_NONE,
14377 OK,
14378 kSecureServer,
14379 AUTH_SYNC,
14380 OK,
14381 2,
14382 0,
14383 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514384 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114385 {__LINE__,
14386 kProxy,
asankac93076192016-10-03 15:46:0214387 AUTH_NONE,
14388 OK,
14389 kSecureServer,
14390 AUTH_SYNC,
14391 ERR_INVALID_AUTH_CREDENTIALS,
14392 2,
14393 0,
14394 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614395 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114396 {__LINE__,
14397 kProxy,
asankac93076192016-10-03 15:46:0214398 AUTH_NONE,
14399 OK,
14400 kSecureServer,
14401 AUTH_ASYNC,
14402 OK,
14403 2,
14404 0,
14405 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514406 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114407 {__LINE__,
14408 kProxy,
asankac93076192016-10-03 15:46:0214409 AUTH_NONE,
14410 OK,
14411 kSecureServer,
14412 AUTH_ASYNC,
14413 ERR_INVALID_AUTH_CREDENTIALS,
14414 2,
14415 0,
14416 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614417 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214418 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114419 {__LINE__,
14420 kProxy,
asankac93076192016-10-03 15:46:0214421 AUTH_SYNC,
14422 OK,
14423 kSecureServer,
14424 AUTH_NONE,
14425 OK,
14426 2,
14427 1,
14428 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514429 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114430 {__LINE__,
14431 kProxy,
asankac93076192016-10-03 15:46:0214432 AUTH_SYNC,
14433 ERR_INVALID_AUTH_CREDENTIALS,
14434 kSecureServer,
14435 AUTH_NONE,
14436 OK,
14437 2,
14438 kNoSSL,
14439 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614440 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114441 {__LINE__,
14442 kProxy,
asankae2257db2016-10-11 22:03:1614443 AUTH_SYNC,
14444 ERR_UNSUPPORTED_AUTH_SCHEME,
14445 kSecureServer,
14446 AUTH_NONE,
14447 OK,
14448 2,
14449 kNoSSL,
14450 {TestRound(kConnect, kProxyChallenge, OK),
14451 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114452 {__LINE__,
14453 kProxy,
asankae2257db2016-10-11 22:03:1614454 AUTH_SYNC,
14455 ERR_UNEXPECTED,
14456 kSecureServer,
14457 AUTH_NONE,
14458 OK,
14459 2,
14460 kNoSSL,
14461 {TestRound(kConnect, kProxyChallenge, OK),
14462 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3114463 {__LINE__,
14464 kProxy,
asankac93076192016-10-03 15:46:0214465 AUTH_ASYNC,
14466 OK,
14467 kSecureServer,
14468 AUTH_NONE,
14469 OK,
14470 2,
14471 1,
14472 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514473 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114474 {__LINE__,
14475 kProxy,
asankac93076192016-10-03 15:46:0214476 AUTH_ASYNC,
14477 ERR_INVALID_AUTH_CREDENTIALS,
14478 kSecureServer,
14479 AUTH_NONE,
14480 OK,
14481 2,
14482 kNoSSL,
14483 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614484 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0214485 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114486 {__LINE__,
14487 kProxy,
asankac93076192016-10-03 15:46:0214488 AUTH_SYNC,
14489 OK,
14490 kSecureServer,
14491 AUTH_SYNC,
14492 OK,
14493 3,
14494 1,
14495 {TestRound(kConnect, kProxyChallenge, OK),
14496 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14497 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514498 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114499 {__LINE__,
14500 kProxy,
asankac93076192016-10-03 15:46:0214501 AUTH_SYNC,
14502 OK,
14503 kSecureServer,
14504 AUTH_SYNC,
14505 ERR_INVALID_AUTH_CREDENTIALS,
14506 3,
14507 1,
14508 {TestRound(kConnect, kProxyChallenge, OK),
14509 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14510 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614511 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114512 {__LINE__,
14513 kProxy,
asankac93076192016-10-03 15:46:0214514 AUTH_ASYNC,
14515 OK,
14516 kSecureServer,
14517 AUTH_SYNC,
14518 OK,
14519 3,
14520 1,
14521 {TestRound(kConnect, kProxyChallenge, OK),
14522 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14523 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514524 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114525 {__LINE__,
14526 kProxy,
asankac93076192016-10-03 15:46:0214527 AUTH_ASYNC,
14528 OK,
14529 kSecureServer,
14530 AUTH_SYNC,
14531 ERR_INVALID_AUTH_CREDENTIALS,
14532 3,
14533 1,
14534 {TestRound(kConnect, kProxyChallenge, OK),
14535 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14536 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614537 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114538 {__LINE__,
14539 kProxy,
asankac93076192016-10-03 15:46:0214540 AUTH_SYNC,
14541 OK,
14542 kSecureServer,
14543 AUTH_ASYNC,
14544 OK,
14545 3,
14546 1,
14547 {TestRound(kConnect, kProxyChallenge, OK),
14548 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14549 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514550 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114551 {__LINE__,
14552 kProxy,
asankac93076192016-10-03 15:46:0214553 AUTH_SYNC,
14554 OK,
14555 kSecureServer,
14556 AUTH_ASYNC,
14557 ERR_INVALID_AUTH_CREDENTIALS,
14558 3,
14559 1,
14560 {TestRound(kConnect, kProxyChallenge, OK),
14561 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14562 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614563 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114564 {__LINE__,
14565 kProxy,
asankac93076192016-10-03 15:46:0214566 AUTH_ASYNC,
14567 OK,
14568 kSecureServer,
14569 AUTH_ASYNC,
14570 OK,
14571 3,
14572 1,
14573 {TestRound(kConnect, kProxyChallenge, OK),
14574 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14575 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514576 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114577 {__LINE__,
14578 kProxy,
asankac93076192016-10-03 15:46:0214579 AUTH_ASYNC,
14580 OK,
14581 kSecureServer,
14582 AUTH_ASYNC,
14583 ERR_INVALID_AUTH_CREDENTIALS,
14584 3,
14585 1,
14586 {TestRound(kConnect, kProxyChallenge, OK),
14587 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14588 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614589 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114590 {__LINE__,
14591 kProxy,
14592 AUTH_ASYNC,
14593 ERR_INVALID_AUTH_CREDENTIALS,
14594 kSecureServer,
14595 AUTH_ASYNC,
14596 ERR_INVALID_AUTH_CREDENTIALS,
14597 4,
14598 2,
14599 {TestRound(kConnect, kProxyChallenge, OK),
14600 TestRound(kConnect, kProxyChallenge, OK),
14601 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14602 &kServerChallenge),
14603 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1514604 };
14605
asanka463ca4262016-11-16 02:34:3114606 for (const auto& test_config : test_configs) {
14607 SCOPED_TRACE(::testing::Message() << "Test config at "
14608 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0814609 HttpAuthHandlerMock::Factory* auth_factory(
14610 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714611 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4914612 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2614613
14614 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1514615 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3114616 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0814617 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14618 std::string auth_challenge = "Mock realm=proxy";
14619 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2414620 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14621 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0814622 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina428341112016-09-22 13:38:2014623 empty_ssl_info, origin,
14624 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814625 auth_handler->SetGenerateExpectation(
14626 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114627 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0814628 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
14629 }
[email protected]044de0642010-06-17 10:42:1514630 }
14631 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0014632 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1514633 std::string auth_challenge = "Mock realm=server";
14634 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2414635 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14636 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1514637 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina428341112016-09-22 13:38:2014638 empty_ssl_info, origin,
14639 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514640 auth_handler->SetGenerateExpectation(
14641 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114642 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0814643 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1614644
14645 // The second handler always succeeds. It should only be used where there
14646 // are multiple auth sessions for server auth in the same network
14647 // transaction using the same auth scheme.
14648 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1914649 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1614650 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
14651 empty_ssl_info, origin,
14652 NetLogWithSource());
14653 second_handler->SetGenerateExpectation(true, OK);
14654 auth_factory->AddMockHandler(second_handler.release(),
14655 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1514656 }
14657 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5914658 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914659 ProxyResolutionService::CreateFixed(test_config.proxy_url,
14660 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514661 } else {
Bence Béky53a5aef2018-03-29 21:54:1214662 session_deps_.proxy_resolution_service =
14663 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1514664 }
14665
14666 HttpRequestInfo request;
14667 request.method = "GET";
14668 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e62018-02-07 07:41:1014669 request.traffic_annotation =
14670 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514671
danakj1fd259a02016-04-16 03:17:0914672 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1514673
rchcb68dc62015-05-21 04:45:3614674 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
14675
14676 std::vector<std::vector<MockRead>> mock_reads(1);
14677 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1514678 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214679 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1514680 const TestRound& read_write_round = test_config.rounds[round];
14681
14682 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3614683 mock_reads.back().push_back(read_write_round.read);
14684 mock_writes.back().push_back(read_write_round.write);
14685
14686 // kProxyChallenge uses Proxy-Connection: close which means that the
14687 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5414688 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3614689 mock_reads.push_back(std::vector<MockRead>());
14690 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1514691 }
14692
rchcb68dc62015-05-21 04:45:3614693 if (read_write_round.extra_read) {
14694 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1514695 }
rchcb68dc62015-05-21 04:45:3614696 if (read_write_round.extra_write) {
14697 mock_writes.back().push_back(*read_write_round.extra_write);
14698 }
[email protected]044de0642010-06-17 10:42:1514699
14700 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1514701 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0714702 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1514703 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3614704 }
[email protected]044de0642010-06-17 10:42:1514705
danakj1fd259a02016-04-16 03:17:0914706 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3614707 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1914708 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0114709 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3614710 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3214711 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3614712 }
14713
mmenkecc2298e2015-12-07 18:20:1814714 // Transaction must be created after DataProviders, so it's destroyed before
14715 // they are as well.
14716 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14717
rchcb68dc62015-05-21 04:45:3614718 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214719 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3614720 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1514721 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4114722 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1514723 int rv;
14724 if (round == 0) {
tfarina428341112016-09-22 13:38:2014725 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514726 } else {
[email protected]49639fa2011-12-20 23:22:4114727 rv = trans.RestartWithAuth(
14728 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1514729 }
14730 if (rv == ERR_IO_PENDING)
14731 rv = callback.WaitForResult();
14732
14733 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1614734 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5014735 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5514736 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1514737 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
14738 continue;
14739 }
14740 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5814741 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1514742 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5814743 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1614744 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1514745 }
14746 }
[email protected]e5ae96a2010-04-14 20:12:4514747 }
14748}
14749
bncd16676a2016-07-20 16:23:0114750TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1414751 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1414752 HttpAuthHandlerMock::Factory* auth_factory(
14753 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714754 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1214755 session_deps_.proxy_resolution_service =
14756 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0714757 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1414758
14759 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14760 auth_handler->set_connection_based(true);
14761 std::string auth_challenge = "Mock realm=server";
14762 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2414763 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14764 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4914765 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1414766 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina428341112016-09-22 13:38:2014767 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814768 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1414769
[email protected]c871bce92010-07-15 21:51:1414770 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3514771 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1414772 HttpRequestInfo request;
14773 request.method = "GET";
14774 request.url = origin;
Ramin Halavatib5e433e62018-02-07 07:41:1014775 request.traffic_annotation =
14776 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2714777
danakj1fd259a02016-04-16 03:17:0914778 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1014779
14780 // Use a TCP Socket Pool with only one connection per group. This is used
14781 // to validate that the TCP socket is not released to the pool between
14782 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4214783 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3614784 CommonConnectJobParams common_connect_job_params(
14785 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2814786 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5914787 50, // Max sockets for pool
14788 1, // Max sockets per group
14789 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3614790 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5214791 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1914792 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4014793 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
14794 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4814795 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1014796
bnc691fda62016-08-12 00:43:1614797 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114798 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1414799
14800 const MockWrite kGet(
14801 "GET / HTTP/1.1\r\n"
14802 "Host: www.example.com\r\n"
14803 "Connection: keep-alive\r\n\r\n");
14804 const MockWrite kGetAuth(
14805 "GET / HTTP/1.1\r\n"
14806 "Host: www.example.com\r\n"
14807 "Connection: keep-alive\r\n"
14808 "Authorization: auth_token\r\n\r\n");
14809
14810 const MockRead kServerChallenge(
14811 "HTTP/1.1 401 Unauthorized\r\n"
14812 "WWW-Authenticate: Mock realm=server\r\n"
14813 "Content-Type: text/html; charset=iso-8859-1\r\n"
14814 "Content-Length: 14\r\n\r\n"
14815 "Unauthorized\r\n");
14816 const MockRead kSuccess(
14817 "HTTP/1.1 200 OK\r\n"
14818 "Content-Type: text/html; charset=iso-8859-1\r\n"
14819 "Content-Length: 3\r\n\r\n"
14820 "Yes");
14821
14822 MockWrite writes[] = {
14823 // First round
14824 kGet,
14825 // Second round
14826 kGetAuth,
14827 // Third round
14828 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3014829 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1014830 kGetAuth,
14831 // Competing request
14832 kGet,
[email protected]c871bce92010-07-15 21:51:1414833 };
14834 MockRead reads[] = {
14835 // First round
14836 kServerChallenge,
14837 // Second round
14838 kServerChallenge,
14839 // Third round
[email protected]eca50e122010-09-11 14:03:3014840 kServerChallenge,
14841 // Fourth round
[email protected]c871bce92010-07-15 21:51:1414842 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1014843 // Competing response
14844 kSuccess,
[email protected]c871bce92010-07-15 21:51:1414845 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114846 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0714847 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1414848
Matt Menkef6edce752019-03-19 17:21:5614849 const ClientSocketPool::GroupId kSocketGroup(
14850 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3414851 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
14852 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1014853
14854 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1414855 auth_handler->SetGenerateExpectation(false, OK);
tfarina428341112016-09-22 13:38:2014856 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1414857 if (rv == ERR_IO_PENDING)
14858 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114859 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614860 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214861 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814862 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314863 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114864 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14865 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414866
[email protected]7ef4cbbb2011-02-06 11:19:1014867 // In between rounds, another request comes in for the same domain.
14868 // It should not be able to grab the TCP socket that trans has already
14869 // claimed.
bnc691fda62016-08-12 00:43:1614870 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114871 TestCompletionCallback callback_compete;
tfarina428341112016-09-22 13:38:2014872 rv = trans_compete.Start(&request, callback_compete.callback(),
14873 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114874 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1014875 // callback_compete.WaitForResult at this point would stall forever,
14876 // since the HttpNetworkTransaction does not release the request back to
14877 // the pool until after authentication completes.
14878
14879 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1414880 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614881 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414882 if (rv == ERR_IO_PENDING)
14883 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114884 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614885 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214886 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814887 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314888 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114889 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14890 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414891
[email protected]7ef4cbbb2011-02-06 11:19:1014892 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1414893 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614894 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414895 if (rv == ERR_IO_PENDING)
14896 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114897 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614898 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214899 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814900 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314901 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114902 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14903 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3014904
[email protected]7ef4cbbb2011-02-06 11:19:1014905 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3014906 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614907 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3014908 if (rv == ERR_IO_PENDING)
14909 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114910 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614911 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214912 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814913 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314914 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014915
asanka463ca4262016-11-16 02:34:3114916 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
14917 // auth handler should transition to a DONE state in concert with the remote
14918 // server. But that's not something we can test here with a mock handler.
14919 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
14920 auth_handler->state());
14921
[email protected]7ef4cbbb2011-02-06 11:19:1014922 // Read the body since the fourth round was successful. This will also
14923 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4414924 scoped_refptr<IOBufferWithSize> io_buf =
14925 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1614926 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014927 if (rv == ERR_IO_PENDING)
14928 rv = callback.WaitForResult();
14929 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614930 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014931 EXPECT_EQ(0, rv);
14932 // There are still 0 idle sockets, since the trans_compete transaction
14933 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314934 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014935
14936 // The competing request can now finish. Wait for the headers and then
14937 // read the body.
14938 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0114939 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614940 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014941 if (rv == ERR_IO_PENDING)
14942 rv = callback.WaitForResult();
14943 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614944 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014945 EXPECT_EQ(0, rv);
14946
14947 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314948 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1414949}
14950
[email protected]65041fa2010-05-21 06:56:5314951// This tests the case that a request is issued via http instead of spdy after
14952// npn is negotiated.
bncd16676a2016-07-20 16:23:0114953TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5314954 HttpRequestInfo request;
14955 request.method = "GET";
bncce36dca22015-04-21 22:11:2314956 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014957 request.traffic_annotation =
14958 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5314959
14960 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314961 MockWrite(
14962 "GET / HTTP/1.1\r\n"
14963 "Host: www.example.org\r\n"
14964 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5314965 };
14966
14967 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214968 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314969 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214970 MockRead("\r\n"),
14971 MockRead("hello world"),
14972 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5314973 };
14974
[email protected]8ddf8322012-02-23 18:08:0614975 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614976 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5314977
[email protected]bb88e1d32013-05-03 23:11:0714978 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5314979
Ryan Sleevib8d7ea02018-05-07 20:01:0114980 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0714981 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5314982
[email protected]49639fa2011-12-20 23:22:4114983 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5314984
danakj1fd259a02016-04-16 03:17:0914985 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614986 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5314987
tfarina428341112016-09-22 13:38:2014988 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5314989
robpercival214763f2016-07-01 23:27:0114990 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14991 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5314992
bnc691fda62016-08-12 00:43:1614993 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214994 ASSERT_TRUE(response);
14995 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5314996 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14997
14998 std::string response_data;
bnc691fda62016-08-12 00:43:1614999 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5315000 EXPECT_EQ("hello world", response_data);
15001
15002 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215003 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5315004}
[email protected]26ef6582010-06-24 02:30:4715005
bnc55ff9da2015-08-19 18:42:3515006// Simulate the SSL handshake completing with an NPN negotiation followed by an
15007// immediate server closing of the socket.
15008// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0115009TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4715010 HttpRequestInfo request;
15011 request.method = "GET";
bncce36dca22015-04-21 22:11:2315012 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015013 request.traffic_annotation =
15014 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4715015
[email protected]8ddf8322012-02-23 18:08:0615016 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615017 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715018 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4715019
Ryan Hamilton0239aac2018-05-19 00:03:1315020 spdy::SpdySerializedFrame req(
15021 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115022 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4715023
15024 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615025 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4715026 };
15027
Ryan Sleevib8d7ea02018-05-07 20:01:0115028 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715029 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4715030
[email protected]49639fa2011-12-20 23:22:4115031 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4715032
danakj1fd259a02016-04-16 03:17:0915033 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615034 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4715035
tfarina428341112016-09-22 13:38:2015036 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115037 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15038 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4715039}
[email protected]65d34382010-07-01 18:12:2615040
[email protected]795cbf82013-07-22 09:37:2715041// A subclass of HttpAuthHandlerMock that records the request URL when
15042// it gets it. This is needed since the auth handler may get destroyed
15043// before we get a chance to query it.
15044class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
15045 public:
15046 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
15047
Chris Watkins7a41d3552017-12-01 02:13:2715048 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2715049
15050 protected:
dchengb03027d2014-10-21 12:00:2015051 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
15052 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0915053 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2015054 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2715055 *url_ = request->url;
15056 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0915057 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2715058 }
15059
15060 private:
15061 GURL* url_;
15062};
15063
[email protected]8e6441ca2010-08-19 05:56:3815064// Test that if we cancel the transaction as the connection is completing, that
15065// everything tears down correctly.
bncd16676a2016-07-20 16:23:0115066TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3815067 // Setup everything about the connection to complete synchronously, so that
15068 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
15069 // for is the callback from the HttpStreamRequest.
15070 // Then cancel the transaction.
15071 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3615072 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3815073 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615074 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
15075 MockRead(SYNCHRONOUS, "hello world"),
15076 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3815077 };
15078
[email protected]8e6441ca2010-08-19 05:56:3815079 HttpRequestInfo request;
15080 request.method = "GET";
bncce36dca22015-04-21 22:11:2315081 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015082 request.traffic_annotation =
15083 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3815084
danakj1fd259a02016-04-16 03:17:0915085 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5815086 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1915087 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2715088
Ryan Sleevib8d7ea02018-05-07 20:01:0115089 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3815090 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0715091 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3815092
[email protected]49639fa2011-12-20 23:22:4115093 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3815094
vishal.b62985ca92015-04-17 08:45:5115095 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4115096 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115097 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3815098 trans.reset(); // Cancel the transaction here.
15099
fdoray92e35a72016-06-10 15:54:5515100 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3015101}
15102
[email protected]ecab6e052014-05-16 14:58:1215103// Test that if a transaction is cancelled after receiving the headers, the
15104// stream is drained properly and added back to the socket pool. The main
15105// purpose of this test is to make sure that an HttpStreamParser can be read
15106// from after the HttpNetworkTransaction and the objects it owns have been
15107// deleted.
15108// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0115109TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1215110 MockRead data_reads[] = {
15111 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
15112 MockRead(ASYNC, "Content-Length: 2\r\n"),
15113 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
15114 MockRead(ASYNC, "1"),
15115 // 2 async reads are necessary to trigger a ReadResponseBody call after the
15116 // HttpNetworkTransaction has been deleted.
15117 MockRead(ASYNC, "2"),
15118 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
15119 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115120 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1215121 session_deps_.socket_factory->AddSocketDataProvider(&data);
15122
danakj1fd259a02016-04-16 03:17:0915123 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1215124
15125 {
15126 HttpRequestInfo request;
15127 request.method = "GET";
bncce36dca22015-04-21 22:11:2315128 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015129 request.traffic_annotation =
15130 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1215131
dcheng48459ac22014-08-26 00:46:4115132 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1215133 TestCompletionCallback callback;
15134
tfarina428341112016-09-22 13:38:2015135 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115136 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1215137 callback.WaitForResult();
15138
15139 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215140 ASSERT_TRUE(response);
15141 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1215142 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15143
15144 // The transaction and HttpRequestInfo are deleted.
15145 }
15146
15147 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5515148 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1215149
15150 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4115151 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1215152}
15153
[email protected]76a505b2010-08-25 06:23:0015154// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0115155TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915156 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915157 ProxyResolutionService::CreateFixedFromPacResult(
15158 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115159 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715160 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915161 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015162
[email protected]76a505b2010-08-25 06:23:0015163 HttpRequestInfo request;
15164 request.method = "GET";
bncce36dca22015-04-21 22:11:2315165 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015166 request.traffic_annotation =
15167 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015168
15169 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2315170 MockWrite(
15171 "GET http://www.example.org/ HTTP/1.1\r\n"
15172 "Host: www.example.org\r\n"
15173 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015174 };
15175
15176 MockRead data_reads1[] = {
15177 MockRead("HTTP/1.1 200 OK\r\n"),
15178 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15179 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615180 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015181 };
15182
Ryan Sleevib8d7ea02018-05-07 20:01:0115183 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715184 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0015185
[email protected]49639fa2011-12-20 23:22:4115186 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015187
bnc691fda62016-08-12 00:43:1615188 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915189 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615190 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915191 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15192 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015193
bnc691fda62016-08-12 00:43:1615194 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115195 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015196
15197 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115198 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0015199
bnc691fda62016-08-12 00:43:1615200 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215201 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015202
15203 EXPECT_TRUE(response->headers->IsKeepAlive());
15204 EXPECT_EQ(200, response->headers->response_code());
15205 EXPECT_EQ(100, response->headers->GetContentLength());
15206 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715207 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15208 HostPortPair::FromString("myproxy:70")),
15209 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915210 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15211 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15212 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0015213 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2015214
15215 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615216 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015217 TestLoadTimingNotReusedWithPac(load_timing_info,
15218 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0015219}
15220
15221// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0115222TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915223 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915224 ProxyResolutionService::CreateFixedFromPacResult(
15225 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115226 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715227 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915228 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015229
[email protected]76a505b2010-08-25 06:23:0015230 HttpRequestInfo request;
15231 request.method = "GET";
bncce36dca22015-04-21 22:11:2315232 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015233 request.traffic_annotation =
15234 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015235
15236 // Since we have proxy, should try to establish tunnel.
15237 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715238 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15239 "Host: www.example.org:443\r\n"
15240 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015241
rsleevidb16bb02015-11-12 23:47:1715242 MockWrite("GET / HTTP/1.1\r\n"
15243 "Host: www.example.org\r\n"
15244 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015245 };
15246
15247 MockRead data_reads1[] = {
15248 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15249
15250 MockRead("HTTP/1.1 200 OK\r\n"),
15251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15252 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615253 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015254 };
15255
Ryan Sleevib8d7ea02018-05-07 20:01:0115256 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715257 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615258 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715259 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015260
[email protected]49639fa2011-12-20 23:22:4115261 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015262
bnc691fda62016-08-12 00:43:1615263 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915264 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615265 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915266 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15267 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015268
bnc691fda62016-08-12 00:43:1615269 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115270 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015271
15272 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115273 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415274 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015275 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015276 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15277 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015278 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015279 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015280 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15281 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015282
bnc691fda62016-08-12 00:43:1615283 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215284 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015285
15286 EXPECT_TRUE(response->headers->IsKeepAlive());
15287 EXPECT_EQ(200, response->headers->response_code());
15288 EXPECT_EQ(100, response->headers->GetContentLength());
15289 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15290 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715291 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15292 HostPortPair::FromString("myproxy:70")),
15293 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915294 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15295 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15296 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2015297
15298 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615299 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015300 TestLoadTimingNotReusedWithPac(load_timing_info,
15301 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0015302}
15303
rsleevidb16bb02015-11-12 23:47:1715304// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
15305// literal host.
bncd16676a2016-07-20 16:23:0115306TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5915307 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915308 ProxyResolutionService::CreateFixedFromPacResult(
15309 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715310 BoundTestNetLog log;
15311 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915312 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1715313
15314 HttpRequestInfo request;
15315 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1515316 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e62018-02-07 07:41:1015317 request.traffic_annotation =
15318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715319
15320 // Since we have proxy, should try to establish tunnel.
15321 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1515322 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
15323 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1715324 "Proxy-Connection: keep-alive\r\n\r\n"),
15325
15326 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1515327 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1715328 "Connection: keep-alive\r\n\r\n"),
15329 };
15330
15331 MockRead data_reads1[] = {
15332 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15333
15334 MockRead("HTTP/1.1 200 OK\r\n"),
15335 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15336 MockRead("Content-Length: 100\r\n\r\n"),
15337 MockRead(SYNCHRONOUS, OK),
15338 };
15339
Ryan Sleevib8d7ea02018-05-07 20:01:0115340 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1715341 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15342 SSLSocketDataProvider ssl(ASYNC, OK);
15343 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15344
15345 TestCompletionCallback callback1;
15346
bnc691fda62016-08-12 00:43:1615347 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1715348
bnc691fda62016-08-12 00:43:1615349 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115350 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1715351
15352 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115353 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415354 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1715355 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015356 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15357 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715358 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015359 entries, pos,
15360 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15361 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715362
bnc691fda62016-08-12 00:43:1615363 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215364 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1715365
15366 EXPECT_TRUE(response->headers->IsKeepAlive());
15367 EXPECT_EQ(200, response->headers->response_code());
15368 EXPECT_EQ(100, response->headers->GetContentLength());
15369 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15370 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715371 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15372 HostPortPair::FromString("myproxy:70")),
15373 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1715374
15375 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615376 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1715377 TestLoadTimingNotReusedWithPac(load_timing_info,
15378 CONNECT_TIMING_HAS_SSL_TIMES);
15379}
15380
[email protected]76a505b2010-08-25 06:23:0015381// Test a basic HTTPS GET request through a proxy, but the server hangs up
15382// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0115383TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4915384 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15385 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115386 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715387 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915388 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015389
[email protected]76a505b2010-08-25 06:23:0015390 HttpRequestInfo request;
15391 request.method = "GET";
bncce36dca22015-04-21 22:11:2315392 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015393 request.traffic_annotation =
15394 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015395
15396 // Since we have proxy, should try to establish tunnel.
15397 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715398 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15399 "Host: www.example.org:443\r\n"
15400 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015401
rsleevidb16bb02015-11-12 23:47:1715402 MockWrite("GET / HTTP/1.1\r\n"
15403 "Host: www.example.org\r\n"
15404 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015405 };
15406
15407 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0015408 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615409 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0015410 };
15411
Ryan Sleevib8d7ea02018-05-07 20:01:0115412 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715413 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615414 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715415 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015416
[email protected]49639fa2011-12-20 23:22:4115417 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015418
bnc691fda62016-08-12 00:43:1615419 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5015420
bnc691fda62016-08-12 00:43:1615421 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115422 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015423
15424 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115425 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5415426 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015427 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015428 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15429 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015430 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015431 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015432 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15433 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015434}
15435
[email protected]749eefa82010-09-13 22:14:0315436// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0115437TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1315438 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4915439 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115440 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0315441
Raul Tambre94493c652019-03-11 17:18:3515442 spdy::SpdySerializedFrame resp(
15443 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315444 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0315445 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115446 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0315447 };
15448
Ryan Sleevib8d7ea02018-05-07 20:01:0115449 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715450 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0315451
[email protected]8ddf8322012-02-23 18:08:0615452 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615453 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715454 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0315455
danakj1fd259a02016-04-16 03:17:0915456 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315457
15458 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315459 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015460 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115461 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3415462 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
15463 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2715464 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5215465 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0315466
15467 HttpRequestInfo request;
15468 request.method = "GET";
bncce36dca22015-04-21 22:11:2315469 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015470 request.traffic_annotation =
15471 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0315472
bnc691fda62016-08-12 00:43:1615473 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0315474
[email protected]41d64e82013-07-03 22:44:2615475 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:2015476 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115477 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15478 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0315479}
15480
[email protected]73b8dd222010-11-11 19:55:2415481// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1615482// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0215483void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0715484 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2915485 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715486 request_info.url = GURL("https://www.example.com/");
15487 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915488 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015489 request_info.traffic_annotation =
15490 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715491
[email protected]8ddf8322012-02-23 18:08:0615492 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2915493 MockWrite data_writes[] = {
15494 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2415495 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115496 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715497 session_deps_.socket_factory->AddSocketDataProvider(&data);
15498 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2415499
danakj1fd259a02016-04-16 03:17:0915500 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615501 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2415502
[email protected]49639fa2011-12-20 23:22:4115503 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:2015504 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2915505 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2415506 rv = callback.WaitForResult();
15507 ASSERT_EQ(error, rv);
15508}
15509
bncd16676a2016-07-20 16:23:0115510TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2415511 // Just check a grab bag of cert errors.
15512 static const int kErrors[] = {
15513 ERR_CERT_COMMON_NAME_INVALID,
15514 ERR_CERT_AUTHORITY_INVALID,
15515 ERR_CERT_DATE_INVALID,
15516 };
Avi Drissman4365a4782018-12-28 19:26:2415517 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0615518 CheckErrorIsPassedBack(kErrors[i], ASYNC);
15519 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2415520 }
15521}
15522
[email protected]bd0b6772011-01-11 19:59:3015523// Ensure that a client certificate is removed from the SSL client auth
15524// cache when:
15525// 1) No proxy is involved.
15526// 2) TLS False Start is disabled.
15527// 3) The initial TLS handshake requests a client certificate.
15528// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115529TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915530 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715531 request_info.url = GURL("https://www.example.com/");
15532 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915533 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015534 request_info.traffic_annotation =
15535 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715536
David Benjamin1c4b6d012019-07-08 17:12:5715537 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115538 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015539
15540 // [ssl_]data1 contains the data for the first SSL handshake. When a
15541 // CertificateRequest is received for the first time, the handshake will
15542 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2915543 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015544 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715545 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115546 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715547 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015548
15549 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
15550 // False Start is not being used, the result of the SSL handshake will be
15551 // returned as part of the SSLClientSocket::Connect() call. This test
15552 // matches the result of a server sending a handshake_failure alert,
15553 // rather than a Finished message, because it requires a client
15554 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2915555 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3015556 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715557 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0115558 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0715559 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015560
15561 // [ssl_]data3 contains the data for the third SSL handshake. When a
15562 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1315563 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
15564 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3015565 // of the HttpNetworkTransaction. Because this test failure is due to
15566 // requiring a client certificate, this fallback handshake should also
15567 // fail.
ttuttle859dc7a2015-04-23 19:42:2915568 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1315569 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3015570 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715571 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115572 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0715573 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015574
[email protected]80c75f682012-05-26 16:22:1715575 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
15576 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4215577 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
15578 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1715579 // of the HttpNetworkTransaction. Because this test failure is due to
15580 // requiring a client certificate, this fallback handshake should also
15581 // fail.
ttuttle859dc7a2015-04-23 19:42:2915582 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1715583 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715584 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115585 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0715586 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715587
danakj1fd259a02016-04-16 03:17:0915588 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615589 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015590
[email protected]bd0b6772011-01-11 19:59:3015591 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4115592 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:2015593 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115594 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015595
15596 // Complete the SSL handshake, which should abort due to requiring a
15597 // client certificate.
15598 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115599 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015600
15601 // Indicate that no certificate should be supplied. From the perspective
15602 // of SSLClientCertCache, NULL is just as meaningful as a real
15603 // certificate, so this is the same as supply a
15604 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515605 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115606 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015607
15608 // Ensure the certificate was added to the client auth cache before
15609 // allowing the connection to continue restarting.
15610 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415611 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115612 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415613 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215614 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015615
15616 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715617 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15618 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015619 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115620 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015621
15622 // Ensure that the client certificate is removed from the cache on a
15623 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4115624 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415625 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015626}
15627
15628// Ensure that a client certificate is removed from the SSL client auth
15629// cache when:
15630// 1) No proxy is involved.
15631// 2) TLS False Start is enabled.
15632// 3) The initial TLS handshake requests a client certificate.
15633// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115634TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915635 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715636 request_info.url = GURL("https://www.example.com/");
15637 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915638 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015639 request_info.traffic_annotation =
15640 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715641
David Benjamin1c4b6d012019-07-08 17:12:5715642 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115643 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015644
15645 // When TLS False Start is used, SSLClientSocket::Connect() calls will
15646 // return successfully after reading up to the peer's Certificate message.
15647 // This is to allow the caller to call SSLClientSocket::Write(), which can
15648 // enqueue application data to be sent in the same packet as the
15649 // ChangeCipherSpec and Finished messages.
15650 // The actual handshake will be finished when SSLClientSocket::Read() is
15651 // called, which expects to process the peer's ChangeCipherSpec and
15652 // Finished messages. If there was an error negotiating with the peer,
15653 // such as due to the peer requiring a client certificate when none was
15654 // supplied, the alert sent by the peer won't be processed until Read() is
15655 // called.
15656
15657 // Like the non-False Start case, when a client certificate is requested by
15658 // the peer, the handshake is aborted during the Connect() call.
15659 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2915660 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015661 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715662 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115663 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715664 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015665
15666 // When a client certificate is supplied, Connect() will not be aborted
15667 // when the peer requests the certificate. Instead, the handshake will
15668 // artificially succeed, allowing the caller to write the HTTP request to
15669 // the socket. The handshake messages are not processed until Read() is
15670 // called, which then detects that the handshake was aborted, due to the
15671 // peer sending a handshake_failure because it requires a client
15672 // certificate.
ttuttle859dc7a2015-04-23 19:42:2915673 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015674 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715675 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2915676 MockRead data2_reads[] = {
15677 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3015678 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115679 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715680 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015681
15682 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1715683 // the data for the SSL handshake once the TLSv1.1 connection falls back to
15684 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915685 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015686 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715687 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115688 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715689 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015690
[email protected]80c75f682012-05-26 16:22:1715691 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
15692 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915693 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1715694 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715695 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115696 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715697 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715698
[email protected]7799de12013-05-30 05:52:5115699 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2915700 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5115701 ssl_data5.cert_request_info = cert_request.get();
15702 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0115703 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5115704 session_deps_.socket_factory->AddSocketDataProvider(&data5);
15705
danakj1fd259a02016-04-16 03:17:0915706 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615707 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015708
[email protected]bd0b6772011-01-11 19:59:3015709 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4115710 TestCompletionCallback callback;
tfarina428341112016-09-22 13:38:2015711 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115712 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015713
15714 // Complete the SSL handshake, which should abort due to requiring a
15715 // client certificate.
15716 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115717 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015718
15719 // Indicate that no certificate should be supplied. From the perspective
15720 // of SSLClientCertCache, NULL is just as meaningful as a real
15721 // certificate, so this is the same as supply a
15722 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515723 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115724 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015725
15726 // Ensure the certificate was added to the client auth cache before
15727 // allowing the connection to continue restarting.
15728 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415729 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115730 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415731 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215732 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015733
[email protected]bd0b6772011-01-11 19:59:3015734 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715735 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15736 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015737 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115738 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015739
15740 // Ensure that the client certificate is removed from the cache on a
15741 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4115742 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415743 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015744}
15745
[email protected]8c405132011-01-11 22:03:1815746// Ensure that a client certificate is removed from the SSL client auth
15747// cache when:
15748// 1) An HTTPS proxy is involved.
15749// 3) The HTTPS proxy requests a client certificate.
15750// 4) The client supplies an invalid/unacceptable certificate for the
15751// proxy.
bncd16676a2016-07-20 16:23:0115752TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4915753 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15754 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115755 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715756 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1815757
David Benjamin3b94b0f2019-04-25 23:07:5215758 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115759 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1815760
David Benjamin3b94b0f2019-04-25 23:07:5215761 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
15762 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2915763 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1815764 requests[0].url = GURL("https://www.example.com/");
15765 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915766 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015767 requests[0].traffic_annotation =
15768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815769
David Benjamin3b94b0f2019-04-25 23:07:5215770 // HTTPS requests are tunneled.
15771 MockWrite https_writes[] = {
15772 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
15773 "Host: www.example.com:443\r\n"
15774 "Proxy-Connection: keep-alive\r\n\r\n"),
15775 };
15776
[email protected]8c405132011-01-11 22:03:1815777 requests[1].url = GURL("http://www.example.com/");
15778 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915779 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015780 requests[1].traffic_annotation =
15781 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815782
David Benjamin3b94b0f2019-04-25 23:07:5215783 // HTTP requests are not.
15784 MockWrite http_writes[] = {
15785 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
15786 "Host: www.example.com\r\n"
15787 "Proxy-Connection: keep-alive\r\n\r\n"),
15788 };
[email protected]8c405132011-01-11 22:03:1815789
David Benjamin3b94b0f2019-04-25 23:07:5215790 // When the server rejects the client certificate, it will close the
15791 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
15792 // TLS 1.2 with False Start), the error is returned out of the first Read().
15793 for (bool reject_in_connect : {true, false}) {
15794 SCOPED_TRACE(reject_in_connect);
15795 // Client certificate errors are typically signaled with
15796 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
15797 // protocol error.
15798 for (Error reject_error :
15799 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
15800 SCOPED_TRACE(reject_error);
15801 // Tunneled and non-tunneled requests are handled differently. Test both.
15802 for (const HttpRequestInfo& request : requests) {
15803 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1815804
David Benjamin3b94b0f2019-04-25 23:07:5215805 session_deps_.socket_factory =
15806 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1815807
David Benjamin3b94b0f2019-04-25 23:07:5215808 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
15809 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
15810 // for proxies. Rather than represending the endpoint
15811 // (www.example.com:443), they represent failures with the HTTPS proxy
15812 // (proxy:70).
15813 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
15814 ssl_data1.cert_request_info = cert_request.get();
15815 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15816 StaticSocketDataProvider data1;
15817 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1815818
David Benjamin3b94b0f2019-04-25 23:07:5215819 base::Optional<SSLSocketDataProvider> ssl_data2;
15820 base::Optional<StaticSocketDataProvider> data2;
15821 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
15822 if (reject_in_connect) {
15823 ssl_data2.emplace(ASYNC, reject_error);
15824 // There are no reads or writes.
15825 data2.emplace();
15826 } else {
15827 ssl_data2.emplace(ASYNC, OK);
15828 // We will get one Write() in before observing the error in Read().
15829 if (request.url.SchemeIsCryptographic()) {
15830 data2.emplace(error_in_read, https_writes);
15831 } else {
15832 data2.emplace(error_in_read, http_writes);
15833 }
15834 }
15835 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1815836
David Benjamin3b94b0f2019-04-25 23:07:5215837 session_deps_.socket_factory->AddSSLSocketDataProvider(
15838 &ssl_data2.value());
15839 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1815840
David Benjamin3b94b0f2019-04-25 23:07:5215841 std::unique_ptr<HttpNetworkSession> session =
15842 CreateSession(&session_deps_);
15843 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15844
15845 // Begin the SSL handshake with the proxy.
15846 TestCompletionCallback callback;
15847 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15848 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15849
15850 // Complete the SSL handshake, which should abort due to requiring a
15851 // client certificate.
15852 rv = callback.WaitForResult();
15853 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15854
15855 // Indicate that no certificate should be supplied. From the
15856 // perspective of SSLClientCertCache, NULL is just as meaningful as a
15857 // real certificate, so this is the same as supply a
15858 // legitimate-but-unacceptable certificate.
15859 rv =
15860 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
15861 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15862
15863 // Ensure the certificate was added to the client auth cache before
15864 // allowing the connection to continue restarting.
15865 scoped_refptr<X509Certificate> client_cert;
15866 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115867 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215868 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15869 ASSERT_FALSE(client_cert);
15870 // Ensure the certificate was NOT cached for the endpoint. This only
15871 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4115872 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215873 HostPortPair("www.example.com", 443), &client_cert,
15874 &client_private_key));
15875
15876 // Restart the handshake. This will consume ssl_data2. The result code
15877 // is checked against what ssl_data2 should return.
15878 rv = callback.WaitForResult();
15879 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
15880 IsError(reject_error)));
15881
15882 // Now that the new handshake has failed, ensure that the client
15883 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4115884 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215885 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4115886 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215887 HostPortPair("www.example.com", 443), &client_cert,
15888 &client_private_key));
15889 }
15890 }
[email protected]8c405132011-01-11 22:03:1815891 }
15892}
15893
David Benjamin1a0566082019-04-30 07:36:1915894// Test that HttpNetworkTransaction correctly handles (mocked) certificate
15895// requests during a TLS renegotiation.
15896TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
15897 HttpRequestInfo request_info;
15898 request_info.url = GURL("https://www.example.com/");
15899 request_info.method = "GET";
15900 request_info.load_flags = LOAD_NORMAL;
15901 request_info.traffic_annotation =
15902 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15903
15904 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
15905 cert_request->host_and_port = HostPortPair("www.example.com", 443);
15906
15907 std::unique_ptr<FakeClientCertIdentity> identity =
15908 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
15909 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
15910 ASSERT_TRUE(identity);
15911
15912 // The first connection's handshake succeeds, but we get
15913 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
15914 SSLSocketDataProvider ssl_data1(ASYNC, OK);
15915 ssl_data1.cert_request_info = cert_request.get();
15916 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15917 MockWrite data1_writes[] = {
15918 MockWrite("GET / HTTP/1.1\r\n"
15919 "Host: www.example.com\r\n"
15920 "Connection: keep-alive\r\n\r\n"),
15921 };
15922 MockRead data1_reads[] = {
15923 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
15924 };
15925 StaticSocketDataProvider data1(data1_reads, data1_writes);
15926 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15927
15928 // After supplying with certificate, we restart the request from the top,
15929 // which succeeds this time.
15930 SSLSocketDataProvider ssl_data2(ASYNC, OK);
15931 ssl_data2.expected_send_client_cert = true;
15932 ssl_data2.expected_client_cert = identity->certificate();
15933 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
15934 MockWrite data2_writes[] = {
15935 MockWrite("GET / HTTP/1.1\r\n"
15936 "Host: www.example.com\r\n"
15937 "Connection: keep-alive\r\n\r\n"),
15938 };
15939 MockRead data2_reads[] = {
15940 MockRead("HTTP/1.1 200 OK\r\n"
15941 "Content-Length: 0\r\n\r\n"),
15942 };
15943 StaticSocketDataProvider data2(data2_reads, data2_writes);
15944 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15945
15946 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
15947 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15948
15949 TestCompletionCallback callback;
15950 int rv = callback.GetResult(
15951 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
15952 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15953
15954 rv = trans.RestartWithCertificate(identity->certificate(),
15955 identity->ssl_private_key(),
15956 callback.callback());
15957 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15958
15959 // Ensure the certificate was added to the client auth cache
15960 // allowing the connection to continue restarting.
15961 scoped_refptr<X509Certificate> client_cert;
15962 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115963 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1915964 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15965 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15966
15967 // Complete the handshake. The request now succeeds.
15968 rv = callback.WaitForResult();
15969 ASSERT_THAT(rv, IsError(OK));
15970 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
15971
15972 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4115973 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1915974 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15975 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15976}
15977
bncd16676a2016-07-20 16:23:0115978TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4615979 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915980 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915981 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615982
bnc032658ba2016-09-26 18:17:1515983 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615984
Ryan Hamilton0239aac2018-05-19 00:03:1315985 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915986 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815987 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315988 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715989 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615990 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115991 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615992 };
Ryan Hamilton0239aac2018-05-19 00:03:1315993 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515994 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315995 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115996 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315997 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515998 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315999 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116000 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616001 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116002 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16003 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316004 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616005 };
16006
eroman36d84e54432016-03-17 03:23:0216007 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216008 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116009 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716010 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616011
[email protected]aa22b242011-11-16 18:58:2916012 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616013 HttpRequestInfo request1;
16014 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316015 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616016 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016017 request1.traffic_annotation =
16018 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016019 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616020
tfarina428341112016-09-22 13:38:2016021 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116022 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16023 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616024
16025 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216026 ASSERT_TRUE(response);
16027 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216028 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616029
16030 std::string response_data;
robpercival214763f2016-07-01 23:27:0116031 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616032 EXPECT_EQ("hello!", response_data);
16033
bnca4d611d2016-09-22 19:55:3716034 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316035 rv = session_deps_.host_resolver->LoadIntoCache(
16036 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116037 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616038
16039 HttpRequestInfo request2;
16040 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716041 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616042 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016043 request2.traffic_annotation =
16044 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016045 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616046
tfarina428341112016-09-22 13:38:2016047 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116048 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16049 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616050
16051 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216052 ASSERT_TRUE(response);
16053 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216054 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616055 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216056 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116057 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616058 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616059}
16060
bncd16676a2016-07-20 16:23:0116061TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0216062 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916063 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916064 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0216065
bnc032658ba2016-09-26 18:17:1516066 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0216067
Ryan Hamilton0239aac2018-05-19 00:03:1316068 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916069 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816070 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316071 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716072 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0216073 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116074 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0216075 };
Ryan Hamilton0239aac2018-05-19 00:03:1316076 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516077 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316078 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116079 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316080 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516081 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316082 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116083 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0216084 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116085 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16086 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316087 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0216088 };
16089
eroman36d84e54432016-03-17 03:23:0216090 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216091 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116092 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716093 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0216094
16095 TestCompletionCallback callback;
16096 HttpRequestInfo request1;
16097 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316098 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0216099 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016100 request1.traffic_annotation =
16101 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016102 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216103
tfarina428341112016-09-22 13:38:2016104 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116105 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16106 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216107
16108 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216109 ASSERT_TRUE(response);
16110 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216111 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216112
16113 std::string response_data;
robpercival214763f2016-07-01 23:27:0116114 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216115 EXPECT_EQ("hello!", response_data);
16116
16117 HttpRequestInfo request2;
16118 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716119 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0216120 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016121 request2.traffic_annotation =
16122 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016123 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216124
tfarina428341112016-09-22 13:38:2016125 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116126 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16127 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216128
16129 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216130 ASSERT_TRUE(response);
16131 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216132 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216133 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216134 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116135 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216136 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0216137}
16138
bnc8016c1f2017-03-31 02:11:2916139// Regression test for https://crbug.com/546991.
16140// The server might not be able to serve an IP pooled request, and might send a
16141// 421 Misdirected Request response status to indicate this.
16142// HttpNetworkTransaction should reset the request and retry without IP pooling.
16143TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
16144 // Two hosts resolve to the same IP address.
16145 const std::string ip_addr = "1.2.3.4";
16146 IPAddress ip;
16147 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16148 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16149
Jeremy Roman0579ed62017-08-29 15:56:1916150 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2916151 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16152 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16153
16154 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16155
16156 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316157 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2916158 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16159 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316160 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2916161 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316162 spdy::SpdySerializedFrame rst(
16163 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2916164 MockWrite writes1[] = {
16165 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16166 CreateMockWrite(rst, 6),
16167 };
16168
16169 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316170 spdy::SpdySerializedFrame resp1(
16171 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16172 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16173 spdy::SpdyHeaderBlock response_headers;
16174 response_headers[spdy::kHttp2StatusHeader] = "421";
16175 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2916176 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
16177 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16178 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16179
16180 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116181 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2916182 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16183
16184 AddSSLSocketData();
16185
16186 // Retry the second request on a second connection.
16187 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316188 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2916189 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16190 MockWrite writes2[] = {
16191 CreateMockWrite(req3, 0),
16192 };
16193
Ryan Hamilton0239aac2018-05-19 00:03:1316194 spdy::SpdySerializedFrame resp3(
16195 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
16196 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2916197 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16198 MockRead(ASYNC, 0, 3)};
16199
16200 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116201 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2916202 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16203
16204 AddSSLSocketData();
16205
16206 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316207 int rv = session_deps_.host_resolver->LoadIntoCache(
16208 HostPortPair("mail.example.com", 443), base::nullopt);
bnc8016c1f2017-03-31 02:11:2916209 EXPECT_THAT(rv, IsOk());
16210
16211 HttpRequestInfo request1;
16212 request1.method = "GET";
16213 request1.url = GURL("https://www.example.org/");
16214 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016215 request1.traffic_annotation =
16216 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916217 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16218
Eric Orthf4db66a2019-02-19 21:35:3316219 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2916220 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16221 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16222 rv = callback.WaitForResult();
16223 EXPECT_THAT(rv, IsOk());
16224
16225 const HttpResponseInfo* response = trans1.GetResponseInfo();
16226 ASSERT_TRUE(response);
16227 ASSERT_TRUE(response->headers);
16228 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16229 EXPECT_TRUE(response->was_fetched_via_spdy);
16230 EXPECT_TRUE(response->was_alpn_negotiated);
16231 std::string response_data;
16232 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16233 EXPECT_EQ("hello!", response_data);
16234
16235 HttpRequestInfo request2;
16236 request2.method = "GET";
16237 request2.url = GURL("https://mail.example.org/");
16238 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016239 request2.traffic_annotation =
16240 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916241 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16242
16243 BoundTestNetLog log;
16244 rv = trans2.Start(&request2, callback.callback(), log.bound());
16245 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16246 rv = callback.WaitForResult();
16247 EXPECT_THAT(rv, IsOk());
16248
16249 response = trans2.GetResponseInfo();
16250 ASSERT_TRUE(response);
16251 ASSERT_TRUE(response->headers);
16252 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16253 EXPECT_TRUE(response->was_fetched_via_spdy);
16254 EXPECT_TRUE(response->was_alpn_negotiated);
16255 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16256 EXPECT_EQ("hello!", response_data);
16257
Eric Roman79cc7552019-07-19 02:17:5416258 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5916259 ExpectLogContainsSomewhere(
16260 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2916261 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5916262}
16263
16264// Test that HTTP 421 responses are properly returned to the caller if received
16265// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
16266// portions of the response.
16267TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
16268 // Two hosts resolve to the same IP address.
16269 const std::string ip_addr = "1.2.3.4";
16270 IPAddress ip;
16271 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16272 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16273
Jeremy Roman0579ed62017-08-29 15:56:1916274 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5916275 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16276 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16277
16278 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16279
16280 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316281 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5916282 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16283 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316284 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5916285 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316286 spdy::SpdySerializedFrame rst(
16287 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5916288 MockWrite writes1[] = {
16289 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16290 CreateMockWrite(rst, 6),
16291 };
16292
16293 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316294 spdy::SpdySerializedFrame resp1(
16295 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16296 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16297 spdy::SpdyHeaderBlock response_headers;
16298 response_headers[spdy::kHttp2StatusHeader] = "421";
16299 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5916300 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
16301 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16302 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16303
16304 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116305 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5916306 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16307
16308 AddSSLSocketData();
16309
16310 // Retry the second request on a second connection. It returns 421 Misdirected
16311 // Retry again.
16312 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316313 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5916314 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16315 MockWrite writes2[] = {
16316 CreateMockWrite(req3, 0),
16317 };
16318
Ryan Hamilton0239aac2018-05-19 00:03:1316319 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5916320 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1316321 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5916322 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16323 MockRead(ASYNC, 0, 3)};
16324
16325 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116326 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5916327 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16328
16329 AddSSLSocketData();
16330
16331 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316332 int rv = session_deps_.host_resolver->LoadIntoCache(
16333 HostPortPair("mail.example.com", 443), base::nullopt);
davidbence688ae2017-05-04 15:12:5916334 EXPECT_THAT(rv, IsOk());
16335
16336 HttpRequestInfo request1;
16337 request1.method = "GET";
16338 request1.url = GURL("https://www.example.org/");
16339 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016340 request1.traffic_annotation =
16341 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916342 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16343
Eric Orthf4db66a2019-02-19 21:35:3316344 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5916345 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16346 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16347 rv = callback.WaitForResult();
16348 EXPECT_THAT(rv, IsOk());
16349
16350 const HttpResponseInfo* response = trans1.GetResponseInfo();
16351 ASSERT_TRUE(response);
16352 ASSERT_TRUE(response->headers);
16353 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16354 EXPECT_TRUE(response->was_fetched_via_spdy);
16355 EXPECT_TRUE(response->was_alpn_negotiated);
16356 std::string response_data;
16357 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16358 EXPECT_EQ("hello!", response_data);
16359
16360 HttpRequestInfo request2;
16361 request2.method = "GET";
16362 request2.url = GURL("https://mail.example.org/");
16363 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016364 request2.traffic_annotation =
16365 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916366 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16367
16368 BoundTestNetLog log;
16369 rv = trans2.Start(&request2, callback.callback(), log.bound());
16370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16371 rv = callback.WaitForResult();
16372 EXPECT_THAT(rv, IsOk());
16373
16374 // After a retry, the 421 Misdirected Request is reported back up to the
16375 // caller.
16376 response = trans2.GetResponseInfo();
16377 ASSERT_TRUE(response);
16378 ASSERT_TRUE(response->headers);
16379 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
16380 EXPECT_TRUE(response->was_fetched_via_spdy);
16381 EXPECT_TRUE(response->was_alpn_negotiated);
16382 EXPECT_TRUE(response->ssl_info.cert);
16383 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16384 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2916385}
16386
bncd16676a2016-07-20 16:23:0116387TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1316388 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3416389 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
16390 session_deps_.host_resolver =
16391 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0916392 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616393
bnc032658ba2016-09-26 18:17:1516394 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616395
Ryan Hamilton0239aac2018-05-19 00:03:1316396 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916397 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816398 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316399 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716400 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616401 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116402 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616403 };
Ryan Hamilton0239aac2018-05-19 00:03:1316404 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516405 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316406 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116407 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316408 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516409 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316410 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116411 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616412 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116413 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16414 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316415 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616416 };
16417
eroman36d84e54432016-03-17 03:23:0216418 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216419 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116420 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716421 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616422
[email protected]aa22b242011-11-16 18:58:2916423 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616424 HttpRequestInfo request1;
16425 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316426 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616427 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016428 request1.traffic_annotation =
16429 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016430 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616431
tfarina428341112016-09-22 13:38:2016432 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116433 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16434 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616435
16436 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216437 ASSERT_TRUE(response);
16438 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216439 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616440
16441 std::string response_data;
robpercival214763f2016-07-01 23:27:0116442 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616443 EXPECT_EQ("hello!", response_data);
16444
16445 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316446 rv = session_deps_.host_resolver->LoadIntoCache(
16447 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116448 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616449
16450 HttpRequestInfo request2;
16451 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716452 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616453 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016454 request2.traffic_annotation =
16455 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016456 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616457
tfarina428341112016-09-22 13:38:2016458 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116459 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16460 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616461
16462 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216463 ASSERT_TRUE(response);
16464 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216465 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616466 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216467 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116468 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616469 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616470}
16471
bncd16676a2016-07-20 16:23:0116472TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2316473 const std::string https_url = "https://www.example.org:8080/";
16474 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416475
16476 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1316477 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916478 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0416479
16480 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116481 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0416482 };
16483
Raul Tambre94493c652019-03-11 17:18:3516484 spdy::SpdySerializedFrame resp1(
16485 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316486 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116487 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5916488 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0416489
Ryan Sleevib8d7ea02018-05-07 20:01:0116490 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416491 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716492 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416493
16494 // HTTP GET for the HTTP URL
16495 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1316496 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3416497 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2316498 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3416499 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0416500 };
16501
16502 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1316503 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
16504 MockRead(ASYNC, 2, "hello"),
16505 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0416506 };
16507
Ryan Sleevib8d7ea02018-05-07 20:01:0116508 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0416509
[email protected]8450d722012-07-02 19:14:0416510 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616511 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716512 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16513 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16514 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0416515
danakj1fd259a02016-04-16 03:17:0916516 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0416517
16518 // Start the first transaction to set up the SpdySession
16519 HttpRequestInfo request1;
16520 request1.method = "GET";
16521 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416522 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016523 request1.traffic_annotation =
16524 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016525 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416526 TestCompletionCallback callback1;
16527 EXPECT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2016528 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516529 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416530
robpercival214763f2016-07-01 23:27:0116531 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416532 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16533
16534 // Now, start the HTTP request
16535 HttpRequestInfo request2;
16536 request2.method = "GET";
16537 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416538 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016539 request2.traffic_annotation =
16540 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016541 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416542 TestCompletionCallback callback2;
16543 EXPECT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2016544 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516545 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416546
robpercival214763f2016-07-01 23:27:0116547 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416548 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16549}
16550
bnc5452e2a2015-05-08 16:27:4216551// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
16552// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0116553TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2516554 url::SchemeHostPort server("https", "www.example.org", 443);
16555 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4216556
bnc8bef8da22016-05-30 01:28:2516557 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4216558 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616559 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216560 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16561
16562 // No data should be read from the alternative, because HTTP/1.1 is
16563 // negotiated.
16564 StaticSocketDataProvider data;
16565 session_deps_.socket_factory->AddSocketDataProvider(&data);
16566
16567 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4616568 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4216569 // mocked. This way the request relies on the alternate Job.
16570 StaticSocketDataProvider data_refused;
16571 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16572 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16573
zhongyi3d4a55e72016-04-22 20:36:4616574 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916575 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016576 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216577 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116578 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216579 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116580 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716581 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216582
bnc5452e2a2015-05-08 16:27:4216583 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4616584 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216585 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2516586 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e62018-02-07 07:41:1016587 request.traffic_annotation =
16588 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216589 TestCompletionCallback callback;
16590
16591 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5216592 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina428341112016-09-22 13:38:2016593 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5216594 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4216595}
16596
bnc40448a532015-05-11 19:13:1416597// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4616598// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1416599// succeeds, the request should succeed, even if the latter fails because
16600// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0116601TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2516602 url::SchemeHostPort server("https", "www.example.org", 443);
16603 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1416604
16605 // Negotiate HTTP/1.1 with alternative.
16606 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616607 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416608 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
16609
16610 // No data should be read from the alternative, because HTTP/1.1 is
16611 // negotiated.
16612 StaticSocketDataProvider data;
16613 session_deps_.socket_factory->AddSocketDataProvider(&data);
16614
zhongyi3d4a55e72016-04-22 20:36:4616615 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1416616 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616617 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416618 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
16619
16620 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2516621 MockWrite("GET / HTTP/1.1\r\n"
16622 "Host: www.example.org\r\n"
16623 "Connection: keep-alive\r\n\r\n"),
16624 MockWrite("GET /second HTTP/1.1\r\n"
16625 "Host: www.example.org\r\n"
16626 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1416627 };
16628
16629 MockRead http_reads[] = {
16630 MockRead("HTTP/1.1 200 OK\r\n"),
16631 MockRead("Content-Type: text/html\r\n"),
16632 MockRead("Content-Length: 6\r\n\r\n"),
16633 MockRead("foobar"),
16634 MockRead("HTTP/1.1 200 OK\r\n"),
16635 MockRead("Content-Type: text/html\r\n"),
16636 MockRead("Content-Length: 7\r\n\r\n"),
16637 MockRead("another"),
16638 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116639 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1416640 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16641
zhongyi3d4a55e72016-04-22 20:36:4616642 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916643 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016644 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1416645 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116646 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216647 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116648 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716649 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1416650
16651 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16652 HttpRequestInfo request1;
16653 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2516654 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1416655 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016656 request1.traffic_annotation =
16657 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416658 TestCompletionCallback callback1;
16659
tfarina428341112016-09-22 13:38:2016660 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416661 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116662 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416663
16664 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216665 ASSERT_TRUE(response1);
16666 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1416667 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
16668
16669 std::string response_data1;
robpercival214763f2016-07-01 23:27:0116670 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1416671 EXPECT_EQ("foobar", response_data1);
16672
16673 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
16674 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0516675 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
16676 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1416677
zhongyi3d4a55e72016-04-22 20:36:4616678 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1416679 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4616680 // to server.
bnc40448a532015-05-11 19:13:1416681 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16682 HttpRequestInfo request2;
16683 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2516684 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1416685 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016686 request2.traffic_annotation =
16687 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416688 TestCompletionCallback callback2;
16689
tfarina428341112016-09-22 13:38:2016690 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416691 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116692 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416693
16694 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216695 ASSERT_TRUE(response2);
16696 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1416697 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
16698
16699 std::string response_data2;
robpercival214763f2016-07-01 23:27:0116700 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1416701 EXPECT_EQ("another", response_data2);
16702}
16703
bnc5452e2a2015-05-08 16:27:4216704// Alternative service requires HTTP/2 (or SPDY), but there is already a
16705// HTTP/1.1 socket open to the alternative server. That socket should not be
16706// used.
bncd16676a2016-07-20 16:23:0116707TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4616708 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4216709 HostPortPair alternative("alternative.example.org", 443);
16710 std::string origin_url = "https://origin.example.org:443";
16711 std::string alternative_url = "https://alternative.example.org:443";
16712
16713 // Negotiate HTTP/1.1 with alternative.example.org.
16714 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616715 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216716 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16717
16718 // HTTP/1.1 data for |request1| and |request2|.
16719 MockWrite http_writes[] = {
16720 MockWrite(
16721 "GET / HTTP/1.1\r\n"
16722 "Host: alternative.example.org\r\n"
16723 "Connection: keep-alive\r\n\r\n"),
16724 MockWrite(
16725 "GET / HTTP/1.1\r\n"
16726 "Host: alternative.example.org\r\n"
16727 "Connection: keep-alive\r\n\r\n"),
16728 };
16729
16730 MockRead http_reads[] = {
16731 MockRead(
16732 "HTTP/1.1 200 OK\r\n"
16733 "Content-Type: text/html; charset=iso-8859-1\r\n"
16734 "Content-Length: 40\r\n\r\n"
16735 "first HTTP/1.1 response from alternative"),
16736 MockRead(
16737 "HTTP/1.1 200 OK\r\n"
16738 "Content-Type: text/html; charset=iso-8859-1\r\n"
16739 "Content-Length: 41\r\n\r\n"
16740 "second HTTP/1.1 response from alternative"),
16741 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116742 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4216743 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16744
16745 // This test documents that an alternate Job should not pool to an already
16746 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4616747 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4216748 StaticSocketDataProvider data_refused;
16749 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16750 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16751
zhongyi3d4a55e72016-04-22 20:36:4616752 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916753 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016754 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216755 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116756 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216757 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116758 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716759 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216760
16761 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4216762 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4616763 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216764 request1.method = "GET";
16765 request1.url = GURL(alternative_url);
16766 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016767 request1.traffic_annotation =
16768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216769 TestCompletionCallback callback1;
16770
tfarina428341112016-09-22 13:38:2016771 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116772 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616773 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216774 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5216775 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4216776 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216777 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216778 EXPECT_FALSE(response1->was_fetched_via_spdy);
16779 std::string response_data1;
bnc691fda62016-08-12 00:43:1616780 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4216781 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
16782
16783 // Request for origin.example.org, which has an alternative service. This
16784 // will start two Jobs: the alternative looks for connections to pool to,
16785 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4616786 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4216787 // this request fails.
bnc5452e2a2015-05-08 16:27:4216788 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4616789 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216790 request2.method = "GET";
16791 request2.url = GURL(origin_url);
16792 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016793 request2.traffic_annotation =
16794 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216795 TestCompletionCallback callback2;
16796
tfarina428341112016-09-22 13:38:2016797 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116798 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4216799
16800 // Another transaction to alternative. This is to test that the HTTP/1.1
16801 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4216802 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4616803 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216804 request3.method = "GET";
16805 request3.url = GURL(alternative_url);
16806 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016807 request3.traffic_annotation =
16808 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216809 TestCompletionCallback callback3;
16810
tfarina428341112016-09-22 13:38:2016811 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116812 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616813 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216814 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5216815 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4216816 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216817 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216818 EXPECT_FALSE(response3->was_fetched_via_spdy);
16819 std::string response_data3;
bnc691fda62016-08-12 00:43:1616820 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4216821 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
16822}
16823
bncd16676a2016-07-20 16:23:0116824TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2316825 const std::string https_url = "https://www.example.org:8080/";
16826 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416827
rdsmithebb50aa2015-11-12 03:44:3816828 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0116829 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3816830
[email protected]8450d722012-07-02 19:14:0416831 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2316832 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0416833 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
16834 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
16835 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1316836 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916837 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316838 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0216839 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3916840
16841 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1316842 spdy::SpdyHeaderBlock req2_block;
16843 req2_block[spdy::kHttp2MethodHeader] = "GET";
16844 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
16845 req2_block[spdy::kHttp2SchemeHeader] = "http";
16846 req2_block[spdy::kHttp2PathHeader] = "/";
16847 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1516848 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0416849
16850 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116851 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
16852 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0416853 };
16854
Ryan Hamilton0239aac2018-05-19 00:03:1316855 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1516856 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316857 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1516858 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316859 spdy::SpdySerializedFrame body1(
16860 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
16861 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3816862 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316863 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3816864 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3516865 spdy::SpdySerializedFrame resp2(
16866 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316867 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3316868 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116869 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3316870 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4116871 CreateMockRead(wrapped_resp1, 4),
16872 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3316873 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4116874 CreateMockRead(resp2, 8),
16875 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3316876 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
16877 };
[email protected]8450d722012-07-02 19:14:0416878
Ryan Sleevib8d7ea02018-05-07 20:01:0116879 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416880 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716881 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416882
Lily Houghton8c2f97d2018-01-22 05:06:5916883 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4916884 ProxyResolutionService::CreateFixedFromPacResult(
16885 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116886 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716887 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0416888 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616889 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316890 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0416891 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616892 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316893 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16894 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0416895
danakj1fd259a02016-04-16 03:17:0916896 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0416897
16898 // Start the first transaction to set up the SpdySession
16899 HttpRequestInfo request1;
16900 request1.method = "GET";
16901 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416902 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016903 request1.traffic_annotation =
16904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016905 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416906 TestCompletionCallback callback1;
tfarina428341112016-09-22 13:38:2016907 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416908
mmenke666a6fea2015-12-19 04:16:3316909 // This pause is a hack to avoid running into https://crbug.com/497228.
16910 data1.RunUntilPaused();
16911 base::RunLoop().RunUntilIdle();
16912 data1.Resume();
robpercival214763f2016-07-01 23:27:0116913 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0416914 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16915
[email protected]f6c63db52013-02-02 00:35:2216916 LoadTimingInfo load_timing_info1;
16917 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
16918 TestLoadTimingNotReusedWithPac(load_timing_info1,
16919 CONNECT_TIMING_HAS_SSL_TIMES);
16920
mmenke666a6fea2015-12-19 04:16:3316921 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0416922 HttpRequestInfo request2;
16923 request2.method = "GET";
16924 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416925 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016926 request2.traffic_annotation =
16927 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016928 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416929 TestCompletionCallback callback2;
tfarina428341112016-09-22 13:38:2016930 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416931
mmenke666a6fea2015-12-19 04:16:3316932 // This pause is a hack to avoid running into https://crbug.com/497228.
16933 data1.RunUntilPaused();
16934 base::RunLoop().RunUntilIdle();
16935 data1.Resume();
robpercival214763f2016-07-01 23:27:0116936 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3316937
[email protected]8450d722012-07-02 19:14:0416938 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2216939
16940 LoadTimingInfo load_timing_info2;
16941 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
16942 // The established SPDY sessions is considered reused by the HTTP request.
16943 TestLoadTimingReusedWithPac(load_timing_info2);
16944 // HTTP requests over a SPDY session should have a different connection
16945 // socket_log_id than requests over a tunnel.
16946 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0416947}
16948
[email protected]2d88e7d2012-07-19 17:55:1716949// Test that in the case where we have a SPDY session to a SPDY proxy
16950// that we do not pool other origins that resolve to the same IP when
16951// the certificate does not match the new origin.
16952// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0116953TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2316954 const std::string url1 = "http://www.example.org/";
16955 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1716956 const std::string ip_addr = "1.2.3.4";
16957
rdsmithebb50aa2015-11-12 03:44:3816958 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0116959 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3816960
[email protected]2d88e7d2012-07-19 17:55:1716961 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1316962 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2316963 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1316964 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1516965 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1716966
16967 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116968 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1716969 };
16970
Raul Tambre94493c652019-03-11 17:18:3516971 spdy::SpdySerializedFrame resp1(
16972 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316973 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1716974 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116975 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
16976 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1716977 };
16978
Ryan Sleevib8d7ea02018-05-07 20:01:0116979 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3216980 IPAddress ip;
martijn654c8c42016-02-10 22:10:5916981 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1716982 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16983 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3316984 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1716985
16986 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1316987 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916988 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1716989
16990 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116991 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1716992 };
16993
Ryan Hamilton0239aac2018-05-19 00:03:1316994 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3516995 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316996 spdy::SpdySerializedFrame body2(
16997 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116998 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3316999 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1717000
Ryan Sleevib8d7ea02018-05-07 20:01:0117001 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1717002 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3317003 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1717004
17005 // Set up a proxy config that sends HTTP requests to a proxy, and
17006 // all others direct.
17007 ProxyConfig proxy_config;
17008 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4917009 session_deps_.proxy_resolution_service =
17010 std::make_unique<ProxyResolutionService>(
17011 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
17012 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
17013 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1717014
bncce36dca22015-04-21 22:11:2317015 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617016 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1717017 // Load a valid cert. Note, that this does not need to
17018 // be valid for proxy because the MockSSLClientSocket does
17019 // not actually verify it. But SpdySession will use this
17020 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4917021 ssl1.ssl_info.cert =
17022 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
17023 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3317024 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17025 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1717026
17027 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617028 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317029 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17030 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1717031
Jeremy Roman0579ed62017-08-29 15:56:1917032 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2317033 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0717034 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1717035
danakj1fd259a02016-04-16 03:17:0917036 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1717037
17038 // Start the first transaction to set up the SpdySession
17039 HttpRequestInfo request1;
17040 request1.method = "GET";
17041 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1717042 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017043 request1.traffic_annotation =
17044 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017045 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717046 TestCompletionCallback callback1;
17047 ASSERT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2017048 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3317049 // This pause is a hack to avoid running into https://crbug.com/497228.
17050 data1.RunUntilPaused();
17051 base::RunLoop().RunUntilIdle();
17052 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1717053
robpercival214763f2016-07-01 23:27:0117054 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717055 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17056
17057 // Now, start the HTTP request
17058 HttpRequestInfo request2;
17059 request2.method = "GET";
17060 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1717061 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017062 request2.traffic_annotation =
17063 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017064 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717065 TestCompletionCallback callback2;
17066 EXPECT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2017067 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517068 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1717069
17070 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0117071 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717072 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17073}
17074
[email protected]85f97342013-04-17 06:12:2417075// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
17076// error) in SPDY session, removes the socket from pool and closes the SPDY
17077// session. Verify that new url's from the same HttpNetworkSession (and a new
17078// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0117079TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2317080 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2417081
17082 MockRead reads1[] = {
17083 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
17084 };
17085
Ryan Sleevib8d7ea02018-05-07 20:01:0117086 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2417087
Ryan Hamilton0239aac2018-05-19 00:03:1317088 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917089 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2417090 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117091 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2417092 };
17093
Raul Tambre94493c652019-03-11 17:18:3517094 spdy::SpdySerializedFrame resp2(
17095 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317096 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2417097 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4117098 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
17099 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2417100 };
17101
Ryan Sleevib8d7ea02018-05-07 20:01:0117102 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2417103
[email protected]85f97342013-04-17 06:12:2417104 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617105 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017106 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17107 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2417108
17109 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617110 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017111 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17112 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2417113
danakj1fd259a02016-04-16 03:17:0917114 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5017115 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2417116
17117 // Start the first transaction to set up the SpdySession and verify that
17118 // connection was closed.
17119 HttpRequestInfo request1;
17120 request1.method = "GET";
17121 request1.url = GURL(https_url);
17122 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017123 request1.traffic_annotation =
17124 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017125 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417126 TestCompletionCallback callback1;
17127 EXPECT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2017128 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0117129 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2417130
17131 // Now, start the second request and make sure it succeeds.
17132 HttpRequestInfo request2;
17133 request2.method = "GET";
17134 request2.url = GURL(https_url);
17135 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017136 request2.traffic_annotation =
17137 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017138 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417139 TestCompletionCallback callback2;
17140 EXPECT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2017141 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2417142
robpercival214763f2016-07-01 23:27:0117143 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2417144 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17145}
17146
bncd16676a2016-07-20 16:23:0117147TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0317148 ClientSocketPoolManager::set_max_sockets_per_group(
17149 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17150 ClientSocketPoolManager::set_max_sockets_per_pool(
17151 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17152
17153 // Use two different hosts with different IPs so they don't get pooled.
17154 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
17155 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0917156 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0317157
17158 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617159 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317160 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617161 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317162 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17163 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17164
Ryan Hamilton0239aac2018-05-19 00:03:1317165 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917166 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317167 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117168 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0317169 };
Ryan Hamilton0239aac2018-05-19 00:03:1317170 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517171 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317172 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117173 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317174 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117175 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917176 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317177 };
17178
rdsmithebb50aa2015-11-12 03:44:3817179 // Use a separate test instance for the separate SpdySession that will be
17180 // created.
bncd16676a2016-07-20 16:23:0117181 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0117182 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1217183 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0317184
Ryan Hamilton0239aac2018-05-19 00:03:1317185 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4917186 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317187 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117188 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0317189 };
Ryan Hamilton0239aac2018-05-19 00:03:1317190 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517191 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317192 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117193 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317194 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117195 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917196 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317197 };
17198
Ryan Sleevib8d7ea02018-05-07 20:01:0117199 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1217200 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0317201
17202 MockWrite http_write[] = {
17203 MockWrite("GET / HTTP/1.1\r\n"
17204 "Host: www.a.com\r\n"
17205 "Connection: keep-alive\r\n\r\n"),
17206 };
17207
17208 MockRead http_read[] = {
17209 MockRead("HTTP/1.1 200 OK\r\n"),
17210 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
17211 MockRead("Content-Length: 6\r\n\r\n"),
17212 MockRead("hello!"),
17213 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117214 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0317215 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17216
17217 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117218 SpdySessionKey spdy_session_key_a(
17219 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417220 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17221 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317222 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617223 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317224
17225 TestCompletionCallback callback;
17226 HttpRequestInfo request1;
17227 request1.method = "GET";
17228 request1.url = GURL("https://www.a.com/");
17229 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017230 request1.traffic_annotation =
17231 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817232 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917233 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317234
tfarina428341112016-09-22 13:38:2017235 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117236 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17237 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317238
17239 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217240 ASSERT_TRUE(response);
17241 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217242 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317243 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217244 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0317245
17246 std::string response_data;
robpercival214763f2016-07-01 23:27:0117247 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317248 EXPECT_EQ("hello!", response_data);
17249 trans.reset();
17250 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617251 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317252
17253 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117254 SpdySessionKey spdy_session_key_b(
17255 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417256 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17257 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317258 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617259 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317260 HttpRequestInfo request2;
17261 request2.method = "GET";
17262 request2.url = GURL("https://www.b.com/");
17263 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017264 request2.traffic_annotation =
17265 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817266 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917267 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317268
tfarina428341112016-09-22 13:38:2017269 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117270 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17271 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317272
17273 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217274 ASSERT_TRUE(response);
17275 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217276 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317277 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217278 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117279 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317280 EXPECT_EQ("hello!", response_data);
17281 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617282 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317283 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617284 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317285
17286 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1117287 SpdySessionKey spdy_session_key_a1(
17288 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417289 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17290 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317291 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617292 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0317293 HttpRequestInfo request3;
17294 request3.method = "GET";
17295 request3.url = GURL("http://www.a.com/");
17296 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017297 request3.traffic_annotation =
17298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817299 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917300 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317301
tfarina428341112016-09-22 13:38:2017302 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117303 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17304 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317305
17306 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217307 ASSERT_TRUE(response);
17308 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0317309 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17310 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217311 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117312 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317313 EXPECT_EQ("hello!", response_data);
17314 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617315 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317316 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617317 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317318}
17319
bncd16676a2016-07-20 16:23:0117320TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417321 HttpRequestInfo request;
17322 request.method = "GET";
bncce36dca22015-04-21 22:11:2317323 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017324 request.traffic_annotation =
17325 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417326
danakj1fd259a02016-04-16 03:17:0917327 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617328 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417329
ttuttled9dbc652015-09-29 20:00:5917330 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417331 StaticSocketDataProvider data;
17332 data.set_connect_data(mock_connect);
17333 session_deps_.socket_factory->AddSocketDataProvider(&data);
17334
17335 TestCompletionCallback callback;
17336
tfarina428341112016-09-22 13:38:2017337 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117338 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417339
17340 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117341 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417342
ttuttle1f2d7e92015-04-28 16:17:4717343 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617344 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717345 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117346 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917347
17348 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617349 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917350 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417351}
17352
bncd16676a2016-07-20 16:23:0117353TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417354 HttpRequestInfo request;
17355 request.method = "GET";
bncce36dca22015-04-21 22:11:2317356 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017357 request.traffic_annotation =
17358 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417359
danakj1fd259a02016-04-16 03:17:0917360 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617361 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417362
ttuttled9dbc652015-09-29 20:00:5917363 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417364 StaticSocketDataProvider data;
17365 data.set_connect_data(mock_connect);
17366 session_deps_.socket_factory->AddSocketDataProvider(&data);
17367
17368 TestCompletionCallback callback;
17369
tfarina428341112016-09-22 13:38:2017370 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117371 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417372
17373 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117374 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417375
ttuttle1f2d7e92015-04-28 16:17:4717376 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617377 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717378 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117379 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917380
17381 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617382 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917383 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417384}
17385
bncd16676a2016-07-20 16:23:0117386TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417387 HttpRequestInfo request;
17388 request.method = "GET";
bncce36dca22015-04-21 22:11:2317389 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017390 request.traffic_annotation =
17391 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417392
danakj1fd259a02016-04-16 03:17:0917393 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617394 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417395
17396 MockWrite data_writes[] = {
17397 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17398 };
17399 MockRead data_reads[] = {
17400 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17401 };
17402
Ryan Sleevib8d7ea02018-05-07 20:01:0117403 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417404 session_deps_.socket_factory->AddSocketDataProvider(&data);
17405
17406 TestCompletionCallback callback;
17407
tfarina428341112016-09-22 13:38:2017408 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117409 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417410
17411 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117412 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417413}
17414
bncd16676a2016-07-20 16:23:0117415TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417416 HttpRequestInfo request;
17417 request.method = "GET";
bncce36dca22015-04-21 22:11:2317418 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017419 request.traffic_annotation =
17420 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417421
danakj1fd259a02016-04-16 03:17:0917422 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617423 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417424
17425 MockWrite data_writes[] = {
17426 MockWrite(ASYNC, ERR_CONNECTION_RESET),
17427 };
17428 MockRead data_reads[] = {
17429 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17430 };
17431
Ryan Sleevib8d7ea02018-05-07 20:01:0117432 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417433 session_deps_.socket_factory->AddSocketDataProvider(&data);
17434
17435 TestCompletionCallback callback;
17436
tfarina428341112016-09-22 13:38:2017437 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117438 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417439
17440 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117441 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417442}
17443
bncd16676a2016-07-20 16:23:0117444TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417445 HttpRequestInfo request;
17446 request.method = "GET";
bncce36dca22015-04-21 22:11:2317447 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017448 request.traffic_annotation =
17449 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417450
danakj1fd259a02016-04-16 03:17:0917451 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617452 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417453
17454 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317455 MockWrite(
17456 "GET / HTTP/1.1\r\n"
17457 "Host: www.example.org\r\n"
17458 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417459 };
17460 MockRead data_reads[] = {
17461 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
17462 };
17463
Ryan Sleevib8d7ea02018-05-07 20:01:0117464 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417465 session_deps_.socket_factory->AddSocketDataProvider(&data);
17466
17467 TestCompletionCallback callback;
17468
tfarina428341112016-09-22 13:38:2017469 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117470 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417471
17472 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117473 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417474}
17475
bncd16676a2016-07-20 16:23:0117476TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417477 HttpRequestInfo request;
17478 request.method = "GET";
bncce36dca22015-04-21 22:11:2317479 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017480 request.traffic_annotation =
17481 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417482
danakj1fd259a02016-04-16 03:17:0917483 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617484 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417485
17486 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317487 MockWrite(
17488 "GET / HTTP/1.1\r\n"
17489 "Host: www.example.org\r\n"
17490 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417491 };
17492 MockRead data_reads[] = {
17493 MockRead(ASYNC, ERR_CONNECTION_RESET),
17494 };
17495
Ryan Sleevib8d7ea02018-05-07 20:01:0117496 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417497 session_deps_.socket_factory->AddSocketDataProvider(&data);
17498
17499 TestCompletionCallback callback;
17500
tfarina428341112016-09-22 13:38:2017501 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117502 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417503
17504 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117505 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417506}
17507
[email protected]043b68c82013-08-22 23:41:5217508// Tests that when a used socket is returned to the SSL socket pool, it's closed
17509// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117510TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5217511 ClientSocketPoolManager::set_max_sockets_per_group(
17512 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17513 ClientSocketPoolManager::set_max_sockets_per_pool(
17514 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17515
17516 // Set up SSL request.
17517
17518 HttpRequestInfo ssl_request;
17519 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2317520 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017521 ssl_request.traffic_annotation =
17522 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217523
17524 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2317525 MockWrite(
17526 "GET / HTTP/1.1\r\n"
17527 "Host: www.example.org\r\n"
17528 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217529 };
17530 MockRead ssl_reads[] = {
17531 MockRead("HTTP/1.1 200 OK\r\n"),
17532 MockRead("Content-Length: 11\r\n\r\n"),
17533 MockRead("hello world"),
17534 MockRead(SYNCHRONOUS, OK),
17535 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117536 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5217537 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17538
17539 SSLSocketDataProvider ssl(ASYNC, OK);
17540 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17541
17542 // Set up HTTP request.
17543
17544 HttpRequestInfo http_request;
17545 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317546 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017547 http_request.traffic_annotation =
17548 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217549
17550 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317551 MockWrite(
17552 "GET / HTTP/1.1\r\n"
17553 "Host: www.example.org\r\n"
17554 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217555 };
17556 MockRead http_reads[] = {
17557 MockRead("HTTP/1.1 200 OK\r\n"),
17558 MockRead("Content-Length: 7\r\n\r\n"),
17559 MockRead("falafel"),
17560 MockRead(SYNCHRONOUS, OK),
17561 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117562 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217563 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17564
danakj1fd259a02016-04-16 03:17:0917565 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217566
17567 // Start the SSL request.
17568 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1617569 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:2017570 ASSERT_EQ(ERR_IO_PENDING,
17571 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
17572 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5217573
17574 // Start the HTTP request. Pool should stall.
17575 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617576 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:2017577 ASSERT_EQ(ERR_IO_PENDING,
17578 http_trans.Start(&http_request, http_callback.callback(),
17579 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117580 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217581
17582 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0117583 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217584 std::string response_data;
bnc691fda62016-08-12 00:43:1617585 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217586 EXPECT_EQ("hello world", response_data);
17587
17588 // The SSL socket should automatically be closed, so the HTTP request can
17589 // start.
Matt Menke9d5e2c92019-02-05 01:42:2317590 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4117591 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217592
17593 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0117594 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1617595 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217596 EXPECT_EQ("falafel", response_data);
17597
dcheng48459ac22014-08-26 00:46:4117598 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217599}
17600
17601// Tests that when a SSL connection is established but there's no corresponding
17602// request that needs it, the new socket is closed if the transport socket pool
17603// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117604TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5217605 ClientSocketPoolManager::set_max_sockets_per_group(
17606 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17607 ClientSocketPoolManager::set_max_sockets_per_pool(
17608 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17609
17610 // Set up an ssl request.
17611
17612 HttpRequestInfo ssl_request;
17613 ssl_request.method = "GET";
17614 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1017615 ssl_request.traffic_annotation =
17616 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217617
17618 // No data will be sent on the SSL socket.
17619 StaticSocketDataProvider ssl_data;
17620 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17621
17622 SSLSocketDataProvider ssl(ASYNC, OK);
17623 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17624
17625 // Set up HTTP request.
17626
17627 HttpRequestInfo http_request;
17628 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317629 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017630 http_request.traffic_annotation =
17631 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217632
17633 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317634 MockWrite(
17635 "GET / HTTP/1.1\r\n"
17636 "Host: www.example.org\r\n"
17637 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217638 };
17639 MockRead http_reads[] = {
17640 MockRead("HTTP/1.1 200 OK\r\n"),
17641 MockRead("Content-Length: 7\r\n\r\n"),
17642 MockRead("falafel"),
17643 MockRead(SYNCHRONOUS, OK),
17644 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117645 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217646 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17647
danakj1fd259a02016-04-16 03:17:0917648 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217649
17650 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
17651 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2917652 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5917653 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2317654 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217655
17656 // Start the HTTP request. Pool should stall.
17657 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617658 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:2017659 ASSERT_EQ(ERR_IO_PENDING,
17660 http_trans.Start(&http_request, http_callback.callback(),
17661 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117662 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217663
17664 // The SSL connection will automatically be closed once the connection is
17665 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0117666 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217667 std::string response_data;
bnc691fda62016-08-12 00:43:1617668 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217669 EXPECT_EQ("falafel", response_data);
17670
dcheng48459ac22014-08-26 00:46:4117671 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217672}
17673
bncd16676a2016-07-20 16:23:0117674TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917675 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217676 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917677 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217678 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417679
17680 HttpRequestInfo request;
17681 request.method = "POST";
17682 request.url = GURL("http://www.foo.com/");
17683 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017684 request.traffic_annotation =
17685 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417686
danakj1fd259a02016-04-16 03:17:0917687 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617688 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417689 // Send headers successfully, but get an error while sending the body.
17690 MockWrite data_writes[] = {
17691 MockWrite("POST / HTTP/1.1\r\n"
17692 "Host: www.foo.com\r\n"
17693 "Connection: keep-alive\r\n"
17694 "Content-Length: 3\r\n\r\n"),
17695 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17696 };
17697
17698 MockRead data_reads[] = {
17699 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17700 MockRead("hello world"),
17701 MockRead(SYNCHRONOUS, OK),
17702 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117703 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417704 session_deps_.socket_factory->AddSocketDataProvider(&data);
17705
17706 TestCompletionCallback callback;
17707
tfarina428341112016-09-22 13:38:2017708 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117709 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417710
17711 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117712 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417713
bnc691fda62016-08-12 00:43:1617714 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217715 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417716
wezca1070932016-05-26 20:30:5217717 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417718 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17719
17720 std::string response_data;
bnc691fda62016-08-12 00:43:1617721 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117722 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417723 EXPECT_EQ("hello world", response_data);
17724}
17725
17726// This test makes sure the retry logic doesn't trigger when reading an error
17727// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0117728TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417729 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0917730 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5417731 MockWrite data_writes[] = {
17732 MockWrite("GET / HTTP/1.1\r\n"
17733 "Host: www.foo.com\r\n"
17734 "Connection: keep-alive\r\n\r\n"),
17735 MockWrite("POST / HTTP/1.1\r\n"
17736 "Host: www.foo.com\r\n"
17737 "Connection: keep-alive\r\n"
17738 "Content-Length: 3\r\n\r\n"),
17739 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17740 };
17741
17742 MockRead data_reads[] = {
17743 MockRead("HTTP/1.1 200 Peachy\r\n"
17744 "Content-Length: 14\r\n\r\n"),
17745 MockRead("first response"),
17746 MockRead("HTTP/1.1 400 Not OK\r\n"
17747 "Content-Length: 15\r\n\r\n"),
17748 MockRead("second response"),
17749 MockRead(SYNCHRONOUS, OK),
17750 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117751 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417752 session_deps_.socket_factory->AddSocketDataProvider(&data);
17753
17754 TestCompletionCallback callback;
17755 HttpRequestInfo request1;
17756 request1.method = "GET";
17757 request1.url = GURL("http://www.foo.com/");
17758 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017759 request1.traffic_annotation =
17760 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417761
bnc87dcefc2017-05-25 12:47:5817762 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1917763 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:2017764 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117765 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417766
17767 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117768 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417769
17770 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5217771 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5417772
wezca1070932016-05-26 20:30:5217773 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5417774 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
17775
17776 std::string response_data1;
17777 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0117778 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417779 EXPECT_EQ("first response", response_data1);
17780 // Delete the transaction to release the socket back into the socket pool.
17781 trans1.reset();
17782
danakj1fd259a02016-04-16 03:17:0917783 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217784 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917785 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217786 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417787
17788 HttpRequestInfo request2;
17789 request2.method = "POST";
17790 request2.url = GURL("http://www.foo.com/");
17791 request2.upload_data_stream = &upload_data_stream;
17792 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017793 request2.traffic_annotation =
17794 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417795
bnc691fda62016-08-12 00:43:1617796 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina428341112016-09-22 13:38:2017797 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117798 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417799
17800 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117801 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417802
bnc691fda62016-08-12 00:43:1617803 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217804 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5417805
wezca1070932016-05-26 20:30:5217806 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5417807 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
17808
17809 std::string response_data2;
bnc691fda62016-08-12 00:43:1617810 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0117811 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417812 EXPECT_EQ("second response", response_data2);
17813}
17814
bncd16676a2016-07-20 16:23:0117815TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417816 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0917817 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217818 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917819 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217820 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417821
17822 HttpRequestInfo request;
17823 request.method = "POST";
17824 request.url = GURL("http://www.foo.com/");
17825 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017826 request.traffic_annotation =
17827 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417828
danakj1fd259a02016-04-16 03:17:0917829 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617830 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417831 // Send headers successfully, but get an error while sending the body.
17832 MockWrite data_writes[] = {
17833 MockWrite("POST / HTTP/1.1\r\n"
17834 "Host: www.foo.com\r\n"
17835 "Connection: keep-alive\r\n"
17836 "Content-Length: 3\r\n\r\n"
17837 "fo"),
17838 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17839 };
17840
17841 MockRead data_reads[] = {
17842 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17843 MockRead("hello world"),
17844 MockRead(SYNCHRONOUS, OK),
17845 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117846 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417847 session_deps_.socket_factory->AddSocketDataProvider(&data);
17848
17849 TestCompletionCallback callback;
17850
tfarina428341112016-09-22 13:38:2017851 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117852 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417853
17854 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117855 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417856
bnc691fda62016-08-12 00:43:1617857 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217858 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417859
wezca1070932016-05-26 20:30:5217860 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417861 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17862
17863 std::string response_data;
bnc691fda62016-08-12 00:43:1617864 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117865 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417866 EXPECT_EQ("hello world", response_data);
17867}
17868
17869// This tests the more common case than the previous test, where headers and
17870// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0117871TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0717872 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5417873
17874 HttpRequestInfo request;
17875 request.method = "POST";
17876 request.url = GURL("http://www.foo.com/");
17877 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017878 request.traffic_annotation =
17879 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417880
danakj1fd259a02016-04-16 03:17:0917881 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617882 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417883 // Send headers successfully, but get an error while sending the body.
17884 MockWrite data_writes[] = {
17885 MockWrite("POST / HTTP/1.1\r\n"
17886 "Host: www.foo.com\r\n"
17887 "Connection: keep-alive\r\n"
17888 "Transfer-Encoding: chunked\r\n\r\n"),
17889 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17890 };
17891
17892 MockRead data_reads[] = {
17893 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17894 MockRead("hello world"),
17895 MockRead(SYNCHRONOUS, OK),
17896 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117897 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417898 session_deps_.socket_factory->AddSocketDataProvider(&data);
17899
17900 TestCompletionCallback callback;
17901
tfarina428341112016-09-22 13:38:2017902 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117903 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417904 // Make sure the headers are sent before adding a chunk. This ensures that
17905 // they can't be merged with the body in a single send. Not currently
17906 // necessary since a chunked body is never merged with headers, but this makes
17907 // the test more future proof.
17908 base::RunLoop().RunUntilIdle();
17909
mmenkecbc2b712014-10-09 20:29:0717910 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5417911
17912 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117913 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417914
bnc691fda62016-08-12 00:43:1617915 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217916 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417917
wezca1070932016-05-26 20:30:5217918 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417919 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17920
17921 std::string response_data;
bnc691fda62016-08-12 00:43:1617922 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117923 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417924 EXPECT_EQ("hello world", response_data);
17925}
17926
bncd16676a2016-07-20 16:23:0117927TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917928 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217929 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917930 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217931 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417932
17933 HttpRequestInfo request;
17934 request.method = "POST";
17935 request.url = GURL("http://www.foo.com/");
17936 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017937 request.traffic_annotation =
17938 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417939
danakj1fd259a02016-04-16 03:17:0917940 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617941 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417942
17943 MockWrite data_writes[] = {
17944 MockWrite("POST / HTTP/1.1\r\n"
17945 "Host: www.foo.com\r\n"
17946 "Connection: keep-alive\r\n"
17947 "Content-Length: 3\r\n\r\n"),
17948 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17949 };
17950
17951 MockRead data_reads[] = {
17952 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17953 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17954 MockRead("hello world"),
17955 MockRead(SYNCHRONOUS, OK),
17956 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117957 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417958 session_deps_.socket_factory->AddSocketDataProvider(&data);
17959
17960 TestCompletionCallback callback;
17961
tfarina428341112016-09-22 13:38:2017962 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117963 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417964
17965 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117966 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417967
bnc691fda62016-08-12 00:43:1617968 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217969 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417970
wezca1070932016-05-26 20:30:5217971 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417972 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17973
17974 std::string response_data;
bnc691fda62016-08-12 00:43:1617975 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117976 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417977 EXPECT_EQ("hello world", response_data);
17978}
17979
bncd16676a2016-07-20 16:23:0117980TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917981 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217982 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917983 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217984 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417985
17986 HttpRequestInfo request;
17987 request.method = "POST";
17988 request.url = GURL("http://www.foo.com/");
17989 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017990 request.traffic_annotation =
17991 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417992
danakj1fd259a02016-04-16 03:17:0917993 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617994 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417995 // Send headers successfully, but get an error while sending the body.
17996 MockWrite data_writes[] = {
17997 MockWrite("POST / HTTP/1.1\r\n"
17998 "Host: www.foo.com\r\n"
17999 "Connection: keep-alive\r\n"
18000 "Content-Length: 3\r\n\r\n"),
18001 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18002 };
18003
18004 MockRead data_reads[] = {
18005 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
18006 MockRead("hello world"),
18007 MockRead(SYNCHRONOUS, OK),
18008 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118009 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418010 session_deps_.socket_factory->AddSocketDataProvider(&data);
18011
18012 TestCompletionCallback callback;
18013
tfarina428341112016-09-22 13:38:2018014 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118015 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418016
18017 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118018 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418019}
18020
bncd16676a2016-07-20 16:23:0118021TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418022 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918023 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218024 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918025 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218026 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418027
18028 HttpRequestInfo request;
18029 request.method = "POST";
18030 request.url = GURL("http://www.foo.com/");
18031 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018032 request.traffic_annotation =
18033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418034
danakj1fd259a02016-04-16 03:17:0918035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618036 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418037 // Send headers successfully, but get an error while sending the body.
18038 MockWrite data_writes[] = {
18039 MockWrite("POST / HTTP/1.1\r\n"
18040 "Host: www.foo.com\r\n"
18041 "Connection: keep-alive\r\n"
18042 "Content-Length: 3\r\n\r\n"),
18043 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18044 };
18045
18046 MockRead data_reads[] = {
18047 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18048 MockRead("HTTP/1.0 302 Redirect\r\n"),
18049 MockRead("Location: http://somewhere-else.com/\r\n"),
18050 MockRead("Content-Length: 0\r\n\r\n"),
18051 MockRead(SYNCHRONOUS, OK),
18052 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118053 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418054 session_deps_.socket_factory->AddSocketDataProvider(&data);
18055
18056 TestCompletionCallback callback;
18057
tfarina428341112016-09-22 13:38:2018058 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118059 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418060
18061 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118062 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418063}
18064
bncd16676a2016-07-20 16:23:0118065TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918066 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218067 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918068 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218069 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418070
18071 HttpRequestInfo request;
18072 request.method = "POST";
18073 request.url = GURL("http://www.foo.com/");
18074 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018075 request.traffic_annotation =
18076 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418077
danakj1fd259a02016-04-16 03:17:0918078 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618079 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418080 // Send headers successfully, but get an error while sending the body.
18081 MockWrite data_writes[] = {
18082 MockWrite("POST / HTTP/1.1\r\n"
18083 "Host: www.foo.com\r\n"
18084 "Connection: keep-alive\r\n"
18085 "Content-Length: 3\r\n\r\n"),
18086 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18087 };
18088
18089 MockRead data_reads[] = {
18090 MockRead("HTTP 0.9 rocks!"),
18091 MockRead(SYNCHRONOUS, OK),
18092 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118093 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418094 session_deps_.socket_factory->AddSocketDataProvider(&data);
18095
18096 TestCompletionCallback callback;
18097
tfarina428341112016-09-22 13:38:2018098 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118099 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418100
18101 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118102 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418103}
18104
bncd16676a2016-07-20 16:23:0118105TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0918106 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218107 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918108 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218109 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418110
18111 HttpRequestInfo request;
18112 request.method = "POST";
18113 request.url = GURL("http://www.foo.com/");
18114 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018115 request.traffic_annotation =
18116 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418117
danakj1fd259a02016-04-16 03:17:0918118 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618119 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418120 // Send headers successfully, but get an error while sending the body.
18121 MockWrite data_writes[] = {
18122 MockWrite("POST / HTTP/1.1\r\n"
18123 "Host: www.foo.com\r\n"
18124 "Connection: keep-alive\r\n"
18125 "Content-Length: 3\r\n\r\n"),
18126 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18127 };
18128
18129 MockRead data_reads[] = {
18130 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
18131 MockRead(SYNCHRONOUS, OK),
18132 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118133 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418134 session_deps_.socket_factory->AddSocketDataProvider(&data);
18135
18136 TestCompletionCallback callback;
18137
tfarina428341112016-09-22 13:38:2018138 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118139 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418140
18141 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118142 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418143}
18144
Bence Békydca6bd92018-01-30 13:43:0618145#if BUILDFLAG(ENABLE_WEBSOCKETS)
18146
18147namespace {
18148
18149void AddWebSocketHeaders(HttpRequestHeaders* headers) {
18150 headers->SetHeader("Connection", "Upgrade");
18151 headers->SetHeader("Upgrade", "websocket");
18152 headers->SetHeader("Origin", "http://www.example.org");
18153 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0618154}
18155
18156} // namespace
18157
18158TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0118159 for (bool secure : {true, false}) {
18160 MockWrite data_writes[] = {
18161 MockWrite("GET / HTTP/1.1\r\n"
18162 "Host: www.example.org\r\n"
18163 "Connection: Upgrade\r\n"
18164 "Upgrade: websocket\r\n"
18165 "Origin: http://www.example.org\r\n"
18166 "Sec-WebSocket-Version: 13\r\n"
18167 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18168 "Sec-WebSocket-Extensions: permessage-deflate; "
18169 "client_max_window_bits\r\n\r\n")};
18170
18171 MockRead data_reads[] = {
18172 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18173 "Upgrade: websocket\r\n"
18174 "Connection: Upgrade\r\n"
18175 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
18176
Ryan Sleevib8d7ea02018-05-07 20:01:0118177 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0118178 session_deps_.socket_factory->AddSocketDataProvider(&data);
18179 SSLSocketDataProvider ssl(ASYNC, OK);
18180 if (secure)
18181 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0618182
18183 HttpRequestInfo request;
18184 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0118185 request.url =
18186 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18187 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e62018-02-07 07:41:1018188 request.traffic_annotation =
18189 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0618190
Bence Béky2fcf4fa2018-04-06 20:06:0118191 TestWebSocketHandshakeStreamCreateHelper
18192 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1518193
Bence Béky2fcf4fa2018-04-06 20:06:0118194 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0618195 HttpNetworkTransaction trans(LOW, session.get());
18196 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0118197 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0618198
18199 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0118200 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18201 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0618202
Bence Béky2fcf4fa2018-04-06 20:06:0118203 const HttpStreamRequest* stream_request = trans.stream_request_.get();
18204 ASSERT_TRUE(stream_request);
18205 EXPECT_EQ(&websocket_handshake_stream_create_helper,
18206 stream_request->websocket_handshake_stream_create_helper());
18207
18208 rv = callback.WaitForResult();
18209 EXPECT_THAT(rv, IsOk());
18210
18211 EXPECT_TRUE(data.AllReadDataConsumed());
18212 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0618213 }
18214}
18215
Adam Rice425cf122015-01-19 06:18:2418216// Verify that proxy headers are not sent to the destination server when
18217// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0118218TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2418219 HttpRequestInfo request;
18220 request.method = "GET";
bncce36dca22015-04-21 22:11:2318221 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018222 request.traffic_annotation =
18223 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418224 AddWebSocketHeaders(&request.extra_headers);
18225
18226 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918227 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918228 ProxyResolutionService::CreateFixedFromPacResult(
18229 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418230
danakj1fd259a02016-04-16 03:17:0918231 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418232
18233 // Since a proxy is configured, try to establish a tunnel.
18234 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1718235 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18236 "Host: www.example.org:443\r\n"
18237 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418238
18239 // After calling trans->RestartWithAuth(), this is the request we should
18240 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1718241 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18242 "Host: www.example.org:443\r\n"
18243 "Proxy-Connection: keep-alive\r\n"
18244 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418245
rsleevidb16bb02015-11-12 23:47:1718246 MockWrite("GET / HTTP/1.1\r\n"
18247 "Host: www.example.org\r\n"
18248 "Connection: Upgrade\r\n"
18249 "Upgrade: websocket\r\n"
18250 "Origin: http://www.example.org\r\n"
18251 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1518252 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18253 "Sec-WebSocket-Extensions: permessage-deflate; "
18254 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418255
18256 // The proxy responds to the connect with a 407, using a persistent
18257 // connection.
18258 MockRead data_reads[] = {
18259 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1518260 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
18261 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
18262 "Content-Length: 0\r\n"
18263 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418264
18265 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18266
Bence Béky8d1c6052018-02-07 12:48:1518267 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18268 "Upgrade: websocket\r\n"
18269 "Connection: Upgrade\r\n"
18270 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418271
Ryan Sleevib8d7ea02018-05-07 20:01:0118272 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418273 session_deps_.socket_factory->AddSocketDataProvider(&data);
18274 SSLSocketDataProvider ssl(ASYNC, OK);
18275 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18276
Bence Béky8d1c6052018-02-07 12:48:1518277 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18278
bnc87dcefc2017-05-25 12:47:5818279 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918280 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418281 trans->SetWebSocketHandshakeStreamCreateHelper(
18282 &websocket_stream_create_helper);
18283
18284 {
18285 TestCompletionCallback callback;
18286
tfarina428341112016-09-22 13:38:2018287 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118288 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418289
18290 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118291 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418292 }
18293
18294 const HttpResponseInfo* response = trans->GetResponseInfo();
18295 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218296 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418297 EXPECT_EQ(407, response->headers->response_code());
18298
18299 {
18300 TestCompletionCallback callback;
18301
18302 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
18303 callback.callback());
robpercival214763f2016-07-01 23:27:0118304 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418305
18306 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118307 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418308 }
18309
18310 response = trans->GetResponseInfo();
18311 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218312 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418313
18314 EXPECT_EQ(101, response->headers->response_code());
18315
18316 trans.reset();
18317 session->CloseAllConnections();
18318}
18319
18320// Verify that proxy headers are not sent to the destination server when
18321// establishing a tunnel for an insecure WebSocket connection.
18322// This requires the authentication info to be injected into the auth cache
18323// due to crbug.com/395064
18324// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0118325TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2418326 HttpRequestInfo request;
18327 request.method = "GET";
bncce36dca22015-04-21 22:11:2318328 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018329 request.traffic_annotation =
18330 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418331 AddWebSocketHeaders(&request.extra_headers);
18332
18333 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918334 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918335 ProxyResolutionService::CreateFixedFromPacResult(
18336 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418337
danakj1fd259a02016-04-16 03:17:0918338 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418339
18340 MockWrite data_writes[] = {
18341 // Try to establish a tunnel for the WebSocket connection, with
18342 // credentials. Because WebSockets have a separate set of socket pools,
18343 // they cannot and will not use the same TCP/IP connection as the
18344 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1518345 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
18346 "Host: www.example.org:80\r\n"
18347 "Proxy-Connection: keep-alive\r\n"
18348 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418349
Bence Béky8d1c6052018-02-07 12:48:1518350 MockWrite("GET / HTTP/1.1\r\n"
18351 "Host: www.example.org\r\n"
18352 "Connection: Upgrade\r\n"
18353 "Upgrade: websocket\r\n"
18354 "Origin: http://www.example.org\r\n"
18355 "Sec-WebSocket-Version: 13\r\n"
18356 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18357 "Sec-WebSocket-Extensions: permessage-deflate; "
18358 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418359
18360 MockRead data_reads[] = {
18361 // HTTP CONNECT with credentials.
18362 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18363
18364 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1518365 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18366 "Upgrade: websocket\r\n"
18367 "Connection: Upgrade\r\n"
18368 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418369
Ryan Sleevib8d7ea02018-05-07 20:01:0118370 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418371 session_deps_.socket_factory->AddSocketDataProvider(&data);
18372
18373 session->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:3318374 GURL("http://myproxy:70/"), HttpAuth::AUTH_PROXY, "MyRealm1",
18375 HttpAuth::AUTH_SCHEME_BASIC, "Basic realm=MyRealm1",
18376 AuthCredentials(kFoo, kBar), "/");
Adam Rice425cf122015-01-19 06:18:2418377
Bence Béky8d1c6052018-02-07 12:48:1518378 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18379
bnc87dcefc2017-05-25 12:47:5818380 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918381 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418382 trans->SetWebSocketHandshakeStreamCreateHelper(
18383 &websocket_stream_create_helper);
18384
18385 TestCompletionCallback callback;
18386
tfarina428341112016-09-22 13:38:2018387 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118388 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418389
18390 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118391 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418392
18393 const HttpResponseInfo* response = trans->GetResponseInfo();
18394 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218395 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418396
18397 EXPECT_EQ(101, response->headers->response_code());
18398
18399 trans.reset();
18400 session->CloseAllConnections();
18401}
18402
Matt Menke1d6093e32019-03-22 17:33:4318403// WebSockets over QUIC is not supported, including over QUIC proxies.
18404TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
18405 for (bool secure : {true, false}) {
18406 SCOPED_TRACE(secure);
18407 session_deps_.proxy_resolution_service =
18408 ProxyResolutionService::CreateFixedFromPacResult(
18409 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
18410 session_deps_.enable_quic = true;
18411
18412 HttpRequestInfo request;
18413 request.url =
18414 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18415 AddWebSocketHeaders(&request.extra_headers);
18416 request.traffic_annotation =
18417 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18418
18419 TestWebSocketHandshakeStreamCreateHelper
18420 websocket_handshake_stream_create_helper;
18421
18422 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18423 HttpNetworkTransaction trans(LOW, session.get());
18424 trans.SetWebSocketHandshakeStreamCreateHelper(
18425 &websocket_handshake_stream_create_helper);
18426
18427 TestCompletionCallback callback;
18428 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18429 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18430
18431 rv = callback.WaitForResult();
18432 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
18433 }
18434}
18435
Bence Békydca6bd92018-01-30 13:43:0618436#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
18437
bncd16676a2016-07-20 16:23:0118438TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0918439 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218440 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918441 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218442 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218443
18444 HttpRequestInfo request;
18445 request.method = "POST";
18446 request.url = GURL("http://www.foo.com/");
18447 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018448 request.traffic_annotation =
18449 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218450
danakj1fd259a02016-04-16 03:17:0918451 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618452 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218453 MockWrite data_writes[] = {
18454 MockWrite("POST / HTTP/1.1\r\n"
18455 "Host: www.foo.com\r\n"
18456 "Connection: keep-alive\r\n"
18457 "Content-Length: 3\r\n\r\n"),
18458 MockWrite("foo"),
18459 };
18460
18461 MockRead data_reads[] = {
18462 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18463 MockRead(SYNCHRONOUS, OK),
18464 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118465 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218466 session_deps_.socket_factory->AddSocketDataProvider(&data);
18467
18468 TestCompletionCallback callback;
18469
18470 EXPECT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2018471 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118472 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218473
18474 std::string response_data;
bnc691fda62016-08-12 00:43:1618475 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218476
Ryan Sleevib8d7ea02018-05-07 20:01:0118477 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18478 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218479}
18480
bncd16676a2016-07-20 16:23:0118481TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0918482 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218483 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918484 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218485 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218486
18487 HttpRequestInfo request;
18488 request.method = "POST";
18489 request.url = GURL("http://www.foo.com/");
18490 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018491 request.traffic_annotation =
18492 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218493
danakj1fd259a02016-04-16 03:17:0918494 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618495 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218496 MockWrite data_writes[] = {
18497 MockWrite("POST / HTTP/1.1\r\n"
18498 "Host: www.foo.com\r\n"
18499 "Connection: keep-alive\r\n"
18500 "Content-Length: 3\r\n\r\n"),
18501 MockWrite("foo"),
18502 };
18503
18504 MockRead data_reads[] = {
18505 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
18506 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18507 MockRead(SYNCHRONOUS, OK),
18508 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118509 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218510 session_deps_.socket_factory->AddSocketDataProvider(&data);
18511
18512 TestCompletionCallback callback;
18513
18514 EXPECT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2018515 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118516 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218517
18518 std::string response_data;
bnc691fda62016-08-12 00:43:1618519 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218520
Ryan Sleevib8d7ea02018-05-07 20:01:0118521 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18522 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218523}
18524
bncd16676a2016-07-20 16:23:0118525TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2218526 ChunkedUploadDataStream upload_data_stream(0);
18527
18528 HttpRequestInfo request;
18529 request.method = "POST";
18530 request.url = GURL("http://www.foo.com/");
18531 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018532 request.traffic_annotation =
18533 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218534
danakj1fd259a02016-04-16 03:17:0918535 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618536 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218537 // Send headers successfully, but get an error while sending the body.
18538 MockWrite data_writes[] = {
18539 MockWrite("POST / HTTP/1.1\r\n"
18540 "Host: www.foo.com\r\n"
18541 "Connection: keep-alive\r\n"
18542 "Transfer-Encoding: chunked\r\n\r\n"),
18543 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
18544 };
18545
18546 MockRead data_reads[] = {
18547 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18548 MockRead(SYNCHRONOUS, OK),
18549 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118550 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218551 session_deps_.socket_factory->AddSocketDataProvider(&data);
18552
18553 TestCompletionCallback callback;
18554
18555 EXPECT_EQ(ERR_IO_PENDING,
tfarina428341112016-09-22 13:38:2018556 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2218557
18558 base::RunLoop().RunUntilIdle();
18559 upload_data_stream.AppendData("f", 1, false);
18560
18561 base::RunLoop().RunUntilIdle();
18562 upload_data_stream.AppendData("oo", 2, true);
18563
robpercival214763f2016-07-01 23:27:0118564 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218565
18566 std::string response_data;
bnc691fda62016-08-12 00:43:1618567 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218568
Ryan Sleevib8d7ea02018-05-07 20:01:0118569 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18570 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218571}
18572
eustasc7d27da2017-04-06 10:33:2018573void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
18574 const std::string& accept_encoding,
18575 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0318576 const std::string& location,
eustasc7d27da2017-04-06 10:33:2018577 bool should_match) {
18578 HttpRequestInfo request;
18579 request.method = "GET";
18580 request.url = GURL("http://www.foo.com/");
18581 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
18582 accept_encoding);
Ramin Halavatib5e433e62018-02-07 07:41:1018583 request.traffic_annotation =
18584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2018585
18586 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
18587 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18588 // Send headers successfully, but get an error while sending the body.
18589 MockWrite data_writes[] = {
18590 MockWrite("GET / HTTP/1.1\r\n"
18591 "Host: www.foo.com\r\n"
18592 "Connection: keep-alive\r\n"
18593 "Accept-Encoding: "),
18594 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
18595 };
18596
sky50576f32017-05-01 19:28:0318597 std::string response_code = "200 OK";
18598 std::string extra;
18599 if (!location.empty()) {
18600 response_code = "301 Redirect\r\nLocation: ";
18601 response_code.append(location);
18602 }
18603
eustasc7d27da2017-04-06 10:33:2018604 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0318605 MockRead("HTTP/1.0 "),
18606 MockRead(response_code.data()),
18607 MockRead("\r\nContent-Encoding: "),
18608 MockRead(content_encoding.data()),
18609 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2018610 MockRead(SYNCHRONOUS, OK),
18611 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118612 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2018613 session_deps->socket_factory->AddSocketDataProvider(&data);
18614
18615 TestCompletionCallback callback;
18616
18617 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18618 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18619
18620 rv = callback.WaitForResult();
18621 if (should_match) {
18622 EXPECT_THAT(rv, IsOk());
18623 } else {
18624 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
18625 }
18626}
18627
18628TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0318629 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2018630}
18631
18632TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0318633 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
18634 true);
eustasc7d27da2017-04-06 10:33:2018635}
18636
18637TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
18638 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0318639 "", false);
18640}
18641
18642TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
18643 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
18644 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2018645}
18646
xunjieli96f2a402017-06-05 17:24:2718647TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
18648 ProxyConfig proxy_config;
18649 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18650 proxy_config.set_pac_mandatory(true);
18651 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918652 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918653 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18654 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0418655 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2718656
18657 HttpRequestInfo request;
18658 request.method = "GET";
18659 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018660 request.traffic_annotation =
18661 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718662
18663 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18664 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18665
18666 TestCompletionCallback callback;
18667
18668 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18669 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18670 EXPECT_THAT(callback.WaitForResult(),
18671 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18672}
18673
18674TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
18675 ProxyConfig proxy_config;
18676 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18677 proxy_config.set_pac_mandatory(true);
18678 MockAsyncProxyResolverFactory* proxy_resolver_factory =
18679 new MockAsyncProxyResolverFactory(false);
18680 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918681 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918682 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18683 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5918684 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2718685 HttpRequestInfo request;
18686 request.method = "GET";
18687 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018688 request.traffic_annotation =
18689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718690
18691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18692 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18693
18694 TestCompletionCallback callback;
18695 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18696 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18697
18698 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
18699 ERR_FAILED, &resolver);
18700 EXPECT_THAT(callback.WaitForResult(),
18701 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18702}
18703
18704TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5918705 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918706 ProxyResolutionService::CreateFixedFromPacResult(
18707 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718708 session_deps_.enable_quic = false;
18709 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18710
18711 HttpRequestInfo request;
18712 request.method = "GET";
18713 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018714 request.traffic_annotation =
18715 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718716
18717 TestCompletionCallback callback;
18718 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18719 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18720 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18721
18722 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
18723}
18724
Douglas Creager3cb042052018-11-06 23:08:5218725//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1418726// Reporting tests
18727
18728#if BUILDFLAG(ENABLE_REPORTING)
18729class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
18730 protected:
18731 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618732 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1418733 auto test_reporting_context = std::make_unique<TestReportingContext>(
18734 &clock_, &tick_clock_, ReportingPolicy());
18735 test_reporting_context_ = test_reporting_context.get();
18736 session_deps_.reporting_service =
18737 ReportingService::CreateForTesting(std::move(test_reporting_context));
18738 }
18739
18740 TestReportingContext* reporting_context() const {
18741 return test_reporting_context_;
18742 }
18743
18744 void clear_reporting_service() {
18745 session_deps_.reporting_service.reset();
18746 test_reporting_context_ = nullptr;
18747 }
18748
18749 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4218750 void RequestPolicy(CertStatus cert_status = 0) {
18751 HttpRequestInfo request;
18752 request.method = "GET";
18753 request.url = GURL(url_);
18754 request.traffic_annotation =
18755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18756
Lily Chend3930e72019-03-01 19:31:1118757 MockWrite data_writes[] = {
18758 MockWrite("GET / HTTP/1.1\r\n"
18759 "Host: www.example.org\r\n"
18760 "Connection: keep-alive\r\n\r\n"),
18761 };
Douglas Creager134b52e2018-11-09 18:00:1418762 MockRead data_reads[] = {
18763 MockRead("HTTP/1.0 200 OK\r\n"),
18764 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
18765 "\"endpoints\": [{\"url\": "
18766 "\"https://www.example.org/upload/\"}]}\r\n"),
18767 MockRead("\r\n"),
18768 MockRead("hello world"),
18769 MockRead(SYNCHRONOUS, OK),
18770 };
Douglas Creager134b52e2018-11-09 18:00:1418771
Lily Chenfec60d92019-01-24 01:16:4218772 StaticSocketDataProvider reads(data_reads, data_writes);
18773 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1418774
18775 SSLSocketDataProvider ssl(ASYNC, OK);
18776 if (request.url.SchemeIsCryptographic()) {
18777 ssl.ssl_info.cert =
18778 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18779 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218780 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1418781 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18782 }
18783
Douglas Creager134b52e2018-11-09 18:00:1418784 TestCompletionCallback callback;
18785 auto session = CreateSession(&session_deps_);
18786 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18787 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4218788 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1418789 }
18790
18791 protected:
18792 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1418793
18794 private:
18795 TestReportingContext* test_reporting_context_;
18796};
18797
18798TEST_F(HttpNetworkTransactionReportingTest,
18799 DontProcessReportToHeaderNoService) {
18800 base::HistogramTester histograms;
18801 clear_reporting_service();
18802 RequestPolicy();
18803 histograms.ExpectBucketCount(
18804 ReportingHeaderParser::kHeaderOutcomeHistogram,
18805 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
18806}
18807
18808TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
18809 base::HistogramTester histograms;
18810 url_ = "http://www.example.org/";
18811 RequestPolicy();
18812 histograms.ExpectBucketCount(
18813 ReportingHeaderParser::kHeaderOutcomeHistogram,
18814 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18815}
18816
18817TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
18818 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5418819 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1018820 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5418821 reporting_context()->cache()->GetEndpointForTesting(
18822 url::Origin::Create(GURL("https://www.example.org/")), "nel",
18823 GURL("https://www.example.org/upload/"));
18824 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1418825}
18826
18827TEST_F(HttpNetworkTransactionReportingTest,
18828 DontProcessReportToHeaderInvalidHttps) {
18829 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218830 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18831 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1418832 histograms.ExpectBucketCount(
18833 ReportingHeaderParser::kHeaderOutcomeHistogram,
18834 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
18835}
18836#endif // BUILDFLAG(ENABLE_REPORTING)
18837
18838//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5218839// Network Error Logging tests
18840
18841#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4218842namespace {
18843
18844const char kUserAgent[] = "Mozilla/1.0";
18845const char kReferrer[] = "https://www.referrer.org/";
18846
18847} // namespace
18848
Douglas Creager3cb042052018-11-06 23:08:5218849class HttpNetworkTransactionNetworkErrorLoggingTest
18850 : public HttpNetworkTransactionTest {
18851 protected:
18852 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618853 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5218854 auto network_error_logging_service =
18855 std::make_unique<TestNetworkErrorLoggingService>();
18856 test_network_error_logging_service_ = network_error_logging_service.get();
18857 session_deps_.network_error_logging_service =
18858 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4218859
18860 extra_headers_.SetHeader("User-Agent", kUserAgent);
18861 extra_headers_.SetHeader("Referer", kReferrer);
18862
18863 request_.method = "GET";
18864 request_.url = GURL(url_);
18865 request_.extra_headers = extra_headers_;
18866 request_.reporting_upload_depth = reporting_upload_depth_;
18867 request_.traffic_annotation =
18868 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5218869 }
18870
18871 TestNetworkErrorLoggingService* network_error_logging_service() const {
18872 return test_network_error_logging_service_;
18873 }
18874
18875 void clear_network_error_logging_service() {
18876 session_deps_.network_error_logging_service.reset();
18877 test_network_error_logging_service_ = nullptr;
18878 }
18879
18880 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4218881 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3618882 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318883 MockWrite data_writes[] = {
18884 MockWrite("GET / HTTP/1.1\r\n"
18885 "Host: www.example.org\r\n"
18886 "Connection: keep-alive\r\n"),
18887 MockWrite(ASYNC, extra_header_string.data(),
18888 extra_header_string.size()),
18889 };
Lily Chend3930e72019-03-01 19:31:1118890 MockRead data_reads[] = {
18891 MockRead("HTTP/1.0 200 OK\r\n"),
18892 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18893 MockRead("\r\n"),
18894 MockRead("hello world"),
18895 MockRead(SYNCHRONOUS, OK),
18896 };
Douglas Creager3cb042052018-11-06 23:08:5218897
Lily Chenfec60d92019-01-24 01:16:4218898 StaticSocketDataProvider reads(data_reads, data_writes);
18899 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5218900
18901 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4218902 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5218903 ssl.ssl_info.cert =
18904 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18905 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218906 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5218907 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18908 }
18909
Douglas Creager3cb042052018-11-06 23:08:5218910 TestCompletionCallback callback;
18911 auto session = CreateSession(&session_deps_);
18912 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4218913 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
18914 EXPECT_THAT(callback.GetResult(rv), IsOk());
18915
18916 std::string response_data;
18917 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
18918 EXPECT_EQ("hello world", response_data);
18919 }
18920
18921 void CheckReport(size_t index,
18922 int status_code,
18923 int error_type,
18924 IPAddress server_ip = IPAddress::IPv4Localhost()) {
18925 ASSERT_LT(index, network_error_logging_service()->errors().size());
18926
18927 const NetworkErrorLoggingService::RequestDetails& error =
18928 network_error_logging_service()->errors()[index];
18929 EXPECT_EQ(url_, error.uri);
18930 EXPECT_EQ(kReferrer, error.referrer);
18931 EXPECT_EQ(kUserAgent, error.user_agent);
18932 EXPECT_EQ(server_ip, error.server_ip);
18933 EXPECT_EQ("http/1.1", error.protocol);
18934 EXPECT_EQ("GET", error.method);
18935 EXPECT_EQ(status_code, error.status_code);
18936 EXPECT_EQ(error_type, error.type);
18937 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5218938 }
18939
18940 protected:
18941 std::string url_ = "https://www.example.org/";
18942 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4218943 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3618944 HttpRequestHeaders extra_headers_;
18945 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5218946
18947 private:
18948 TestNetworkErrorLoggingService* test_network_error_logging_service_;
18949};
18950
18951TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18952 DontProcessNelHeaderNoService) {
18953 base::HistogramTester histograms;
18954 clear_network_error_logging_service();
18955 RequestPolicy();
18956 histograms.ExpectBucketCount(
18957 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18958 NetworkErrorLoggingService::HeaderOutcome::
18959 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
18960 1);
18961}
18962
18963TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18964 DontProcessNelHeaderHttp) {
18965 base::HistogramTester histograms;
18966 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4218967 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5218968 RequestPolicy();
18969 histograms.ExpectBucketCount(
18970 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18971 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18972}
18973
Lily Chen90ae93cc2019-02-14 01:15:3918974// Don't set NEL policies received on a proxied connection.
18975TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18976 DontProcessNelHeaderProxy) {
18977 session_deps_.proxy_resolution_service =
18978 ProxyResolutionService::CreateFixedFromPacResult(
18979 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
18980 BoundTestNetLog log;
18981 session_deps_.net_log = log.bound().net_log();
18982 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18983
18984 HttpRequestInfo request;
18985 request.method = "GET";
18986 request.url = GURL("https://www.example.org/");
18987 request.traffic_annotation =
18988 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18989
18990 // Since we have proxy, should try to establish tunnel.
18991 MockWrite data_writes1[] = {
18992 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18993 "Host: www.example.org:443\r\n"
18994 "Proxy-Connection: keep-alive\r\n\r\n"),
18995
18996 MockWrite("GET / HTTP/1.1\r\n"
18997 "Host: www.example.org\r\n"
18998 "Connection: keep-alive\r\n\r\n"),
18999 };
19000
19001 MockRead data_reads1[] = {
19002 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19003
19004 MockRead("HTTP/1.1 200 OK\r\n"),
19005 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19006 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19007 MockRead("Content-Length: 100\r\n\r\n"),
19008 MockRead(SYNCHRONOUS, OK),
19009 };
19010
19011 StaticSocketDataProvider data1(data_reads1, data_writes1);
19012 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19013 SSLSocketDataProvider ssl(ASYNC, OK);
19014 ssl.ssl_info.cert =
19015 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19016 ASSERT_TRUE(ssl.ssl_info.cert);
19017 ssl.ssl_info.cert_status = 0;
19018 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19019
19020 TestCompletionCallback callback1;
19021 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19022
19023 int rv = trans.Start(&request, callback1.callback(), log.bound());
19024 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19025
19026 rv = callback1.WaitForResult();
19027 EXPECT_THAT(rv, IsOk());
19028
19029 const HttpResponseInfo* response = trans.GetResponseInfo();
19030 ASSERT_TRUE(response);
19031 EXPECT_EQ(200, response->headers->response_code());
19032 EXPECT_TRUE(response->was_fetched_via_proxy);
19033
19034 // No NEL header was set.
19035 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
19036}
19037
Douglas Creager3cb042052018-11-06 23:08:5219038TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
19039 RequestPolicy();
19040 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
19041 const auto& header = network_error_logging_service()->headers()[0];
19042 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
19043 header.origin);
19044 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
19045 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
19046}
19047
19048TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19049 DontProcessNelHeaderInvalidHttps) {
19050 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219051 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19052 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5219053 histograms.ExpectBucketCount(
19054 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19055 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
19056 1);
19057}
Douglas Creageref5eecdc2018-11-09 20:50:3619058
Lily Chenfec60d92019-01-24 01:16:4219059TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3619060 RequestPolicy();
19061 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219062 CheckReport(0 /* index */, 200 /* status_code */, OK);
19063}
19064
19065TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19066 CreateReportErrorAfterStart) {
19067 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19068 auto trans =
19069 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19070
19071 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
19072 StaticSocketDataProvider data;
19073 data.set_connect_data(mock_connect);
19074 session_deps_.socket_factory->AddSocketDataProvider(&data);
19075
19076 TestCompletionCallback callback;
19077
19078 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19079 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19080
19081 trans.reset();
19082
19083 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19084 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19085 IPAddress() /* server_ip */);
19086}
19087
19088// Same as above except the error is ASYNC
19089TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19090 CreateReportErrorAfterStartAsync) {
19091 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19092 auto trans =
19093 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19094
19095 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
19096 StaticSocketDataProvider data;
19097 data.set_connect_data(mock_connect);
19098 session_deps_.socket_factory->AddSocketDataProvider(&data);
19099
19100 TestCompletionCallback callback;
19101
19102 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19103 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19104
19105 trans.reset();
19106
19107 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19108 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19109 IPAddress() /* server_ip */);
19110}
19111
19112TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19113 CreateReportReadBodyError) {
19114 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319115 MockWrite data_writes[] = {
19116 MockWrite("GET / HTTP/1.1\r\n"
19117 "Host: www.example.org\r\n"
19118 "Connection: keep-alive\r\n"),
19119 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19120 };
Lily Chend3930e72019-03-01 19:31:1119121 MockRead data_reads[] = {
19122 MockRead("HTTP/1.0 200 OK\r\n"),
19123 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19124 MockRead("hello world"),
19125 MockRead(SYNCHRONOUS, OK),
19126 };
Lily Chenfec60d92019-01-24 01:16:4219127
19128 StaticSocketDataProvider reads(data_reads, data_writes);
19129 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19130
19131 SSLSocketDataProvider ssl(ASYNC, OK);
19132 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19133
19134 // Log start time
19135 base::TimeTicks start_time = base::TimeTicks::Now();
19136
19137 TestCompletionCallback callback;
19138 auto session = CreateSession(&session_deps_);
19139 auto trans =
19140 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19141 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19142 EXPECT_THAT(callback.GetResult(rv), IsOk());
19143
19144 const HttpResponseInfo* response = trans->GetResponseInfo();
19145 ASSERT_TRUE(response);
19146
19147 EXPECT_TRUE(response->headers);
19148 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19149
19150 std::string response_data;
19151 rv = ReadTransaction(trans.get(), &response_data);
19152 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19153
19154 trans.reset();
19155
19156 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19157
19158 CheckReport(0 /* index */, 200 /* status_code */,
19159 ERR_CONTENT_LENGTH_MISMATCH);
19160 const NetworkErrorLoggingService::RequestDetails& error =
19161 network_error_logging_service()->errors()[0];
19162 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19163}
19164
19165// Same as above except the final read is ASYNC.
19166TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19167 CreateReportReadBodyErrorAsync) {
19168 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319169 MockWrite data_writes[] = {
19170 MockWrite("GET / HTTP/1.1\r\n"
19171 "Host: www.example.org\r\n"
19172 "Connection: keep-alive\r\n"),
19173 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19174 };
Lily Chend3930e72019-03-01 19:31:1119175 MockRead data_reads[] = {
19176 MockRead("HTTP/1.0 200 OK\r\n"),
19177 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19178 MockRead("hello world"),
19179 MockRead(ASYNC, OK),
19180 };
Lily Chenfec60d92019-01-24 01:16:4219181
19182 StaticSocketDataProvider reads(data_reads, data_writes);
19183 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19184
19185 SSLSocketDataProvider ssl(ASYNC, OK);
19186 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19187
19188 // Log start time
19189 base::TimeTicks start_time = base::TimeTicks::Now();
19190
19191 TestCompletionCallback callback;
19192 auto session = CreateSession(&session_deps_);
19193 auto trans =
19194 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19195 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19196 EXPECT_THAT(callback.GetResult(rv), IsOk());
19197
19198 const HttpResponseInfo* response = trans->GetResponseInfo();
19199 ASSERT_TRUE(response);
19200
19201 EXPECT_TRUE(response->headers);
19202 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19203
19204 std::string response_data;
19205 rv = ReadTransaction(trans.get(), &response_data);
19206 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19207
19208 trans.reset();
19209
19210 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19211
19212 CheckReport(0 /* index */, 200 /* status_code */,
19213 ERR_CONTENT_LENGTH_MISMATCH);
19214 const NetworkErrorLoggingService::RequestDetails& error =
19215 network_error_logging_service()->errors()[0];
19216 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19217}
19218
19219TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19220 CreateReportRestartWithAuth) {
19221 std::string extra_header_string = extra_headers_.ToString();
19222 static const base::TimeDelta kSleepDuration =
19223 base::TimeDelta::FromMilliseconds(10);
19224
19225 MockWrite data_writes1[] = {
19226 MockWrite("GET / HTTP/1.1\r\n"
19227 "Host: www.example.org\r\n"
19228 "Connection: keep-alive\r\n"),
19229 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19230 };
19231
19232 MockRead data_reads1[] = {
19233 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19234 // Give a couple authenticate options (only the middle one is actually
19235 // supported).
19236 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19237 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19238 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19239 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19240 // Large content-length -- won't matter, as connection will be reset.
19241 MockRead("Content-Length: 10000\r\n\r\n"),
19242 MockRead(SYNCHRONOUS, ERR_FAILED),
19243 };
19244
19245 // After calling trans->RestartWithAuth(), this is the request we should
19246 // be issuing -- the final header line contains the credentials.
19247 MockWrite data_writes2[] = {
19248 MockWrite("GET / HTTP/1.1\r\n"
19249 "Host: www.example.org\r\n"
19250 "Connection: keep-alive\r\n"
19251 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19252 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19253 };
19254
19255 // Lastly, the server responds with the actual content.
19256 MockRead data_reads2[] = {
19257 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19258 MockRead("hello world"),
19259 MockRead(SYNCHRONOUS, OK),
19260 };
19261
19262 StaticSocketDataProvider data1(data_reads1, data_writes1);
19263 StaticSocketDataProvider data2(data_reads2, data_writes2);
19264 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19265 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19266
19267 SSLSocketDataProvider ssl1(ASYNC, OK);
19268 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19269 SSLSocketDataProvider ssl2(ASYNC, OK);
19270 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19271
19272 base::TimeTicks start_time = base::TimeTicks::Now();
19273 base::TimeTicks restart_time;
19274
19275 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19276 auto trans =
19277 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19278
19279 TestCompletionCallback callback1;
19280
19281 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19282 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19283
19284 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19285
19286 TestCompletionCallback callback2;
19287
19288 // Wait 10 ms then restart with auth
19289 FastForwardBy(kSleepDuration);
19290 restart_time = base::TimeTicks::Now();
19291 rv =
19292 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19293 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19294
19295 std::string response_data;
19296 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19297 EXPECT_EQ("hello world", response_data);
19298
19299 trans.reset();
19300
19301 // One 401 report for the auth challenge, then a 200 report for the successful
19302 // retry. Note that we don't report the error draining the body, as the first
19303 // request already generated a report for the auth challenge.
19304 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19305
19306 // Check error report contents
19307 CheckReport(0 /* index */, 401 /* status_code */, OK);
19308 CheckReport(1 /* index */, 200 /* status_code */, OK);
19309
19310 const NetworkErrorLoggingService::RequestDetails& error1 =
19311 network_error_logging_service()->errors()[0];
19312 const NetworkErrorLoggingService::RequestDetails& error2 =
19313 network_error_logging_service()->errors()[1];
19314
19315 // Sanity-check elapsed time values
19316 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19317 // Check that the start time is refreshed when restarting with auth.
19318 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19319}
19320
19321// Same as above, except draining the body before restarting fails
19322// asynchronously.
19323TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19324 CreateReportRestartWithAuthAsync) {
19325 std::string extra_header_string = extra_headers_.ToString();
19326 static const base::TimeDelta kSleepDuration =
19327 base::TimeDelta::FromMilliseconds(10);
19328
19329 MockWrite data_writes1[] = {
19330 MockWrite("GET / HTTP/1.1\r\n"
19331 "Host: www.example.org\r\n"
19332 "Connection: keep-alive\r\n"),
19333 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19334 };
19335
19336 MockRead data_reads1[] = {
19337 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19338 // Give a couple authenticate options (only the middle one is actually
19339 // supported).
19340 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19341 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19342 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19343 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19344 // Large content-length -- won't matter, as connection will be reset.
19345 MockRead("Content-Length: 10000\r\n\r\n"),
19346 MockRead(ASYNC, ERR_FAILED),
19347 };
19348
19349 // After calling trans->RestartWithAuth(), this is the request we should
19350 // be issuing -- the final header line contains the credentials.
19351 MockWrite data_writes2[] = {
19352 MockWrite("GET / HTTP/1.1\r\n"
19353 "Host: www.example.org\r\n"
19354 "Connection: keep-alive\r\n"
19355 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19356 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19357 };
19358
19359 // Lastly, the server responds with the actual content.
19360 MockRead data_reads2[] = {
19361 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19362 MockRead("hello world"),
19363 MockRead(SYNCHRONOUS, OK),
19364 };
19365
19366 StaticSocketDataProvider data1(data_reads1, data_writes1);
19367 StaticSocketDataProvider data2(data_reads2, data_writes2);
19368 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19369 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19370
19371 SSLSocketDataProvider ssl1(ASYNC, OK);
19372 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19373 SSLSocketDataProvider ssl2(ASYNC, OK);
19374 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19375
19376 base::TimeTicks start_time = base::TimeTicks::Now();
19377 base::TimeTicks restart_time;
19378
19379 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19380 auto trans =
19381 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19382
19383 TestCompletionCallback callback1;
19384
19385 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19386 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19387
19388 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19389
19390 TestCompletionCallback callback2;
19391
19392 // Wait 10 ms then restart with auth
19393 FastForwardBy(kSleepDuration);
19394 restart_time = base::TimeTicks::Now();
19395 rv =
19396 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19397 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19398
19399 std::string response_data;
19400 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19401 EXPECT_EQ("hello world", response_data);
19402
19403 trans.reset();
19404
19405 // One 401 report for the auth challenge, then a 200 report for the successful
19406 // retry. Note that we don't report the error draining the body, as the first
19407 // request already generated a report for the auth challenge.
19408 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19409
19410 // Check error report contents
19411 CheckReport(0 /* index */, 401 /* status_code */, OK);
19412 CheckReport(1 /* index */, 200 /* status_code */, OK);
19413
19414 const NetworkErrorLoggingService::RequestDetails& error1 =
19415 network_error_logging_service()->errors()[0];
19416 const NetworkErrorLoggingService::RequestDetails& error2 =
19417 network_error_logging_service()->errors()[1];
19418
19419 // Sanity-check elapsed time values
19420 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19421 // Check that the start time is refreshed when restarting with auth.
19422 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19423}
19424
19425TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19426 CreateReportRetryKeepAliveConnectionReset) {
19427 std::string extra_header_string = extra_headers_.ToString();
19428 MockWrite data_writes1[] = {
19429 MockWrite("GET / HTTP/1.1\r\n"
19430 "Host: www.example.org\r\n"
19431 "Connection: keep-alive\r\n"),
19432 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19433 MockWrite("GET / HTTP/1.1\r\n"
19434 "Host: www.example.org\r\n"
19435 "Connection: keep-alive\r\n"),
19436 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19437 };
19438
19439 MockRead data_reads1[] = {
19440 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19441 MockRead("hello"),
19442 // Connection is reset
19443 MockRead(ASYNC, ERR_CONNECTION_RESET),
19444 };
19445
19446 // Successful retry
19447 MockRead data_reads2[] = {
19448 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19449 MockRead("world"),
19450 MockRead(ASYNC, OK),
19451 };
19452
19453 StaticSocketDataProvider data1(data_reads1, data_writes1);
19454 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19455 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19456 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19457
19458 SSLSocketDataProvider ssl1(ASYNC, OK);
19459 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19460 SSLSocketDataProvider ssl2(ASYNC, OK);
19461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19462
19463 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19464 auto trans1 =
19465 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19466
19467 TestCompletionCallback callback1;
19468
19469 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19470 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19471
19472 std::string response_data;
19473 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19474 EXPECT_EQ("hello", response_data);
19475
19476 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19477
19478 auto trans2 =
19479 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19480
19481 TestCompletionCallback callback2;
19482
19483 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19484 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19485
19486 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19487 EXPECT_EQ("world", response_data);
19488
19489 trans1.reset();
19490 trans2.reset();
19491
19492 // One OK report from first request, then a ERR_CONNECTION_RESET report from
19493 // the second request, then an OK report from the successful retry.
19494 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19495
19496 // Check error report contents
19497 CheckReport(0 /* index */, 200 /* status_code */, OK);
19498 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
19499 CheckReport(2 /* index */, 200 /* status_code */, OK);
19500}
19501
19502TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19503 CreateReportRetryKeepAlive408) {
19504 std::string extra_header_string = extra_headers_.ToString();
19505 MockWrite data_writes1[] = {
19506 MockWrite("GET / HTTP/1.1\r\n"
19507 "Host: www.example.org\r\n"
19508 "Connection: keep-alive\r\n"),
19509 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19510 MockWrite("GET / HTTP/1.1\r\n"
19511 "Host: www.example.org\r\n"
19512 "Connection: keep-alive\r\n"),
19513 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19514 };
19515
19516 MockRead data_reads1[] = {
19517 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19518 MockRead("hello"),
19519 // 408 Request Timeout
19520 MockRead(SYNCHRONOUS,
19521 "HTTP/1.1 408 Request Timeout\r\n"
19522 "Connection: Keep-Alive\r\n"
19523 "Content-Length: 6\r\n\r\n"
19524 "Pickle"),
19525 };
19526
19527 // Successful retry
19528 MockRead data_reads2[] = {
19529 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19530 MockRead("world"),
19531 MockRead(ASYNC, OK),
19532 };
19533
19534 StaticSocketDataProvider data1(data_reads1, data_writes1);
19535 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19536 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19537 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19538
19539 SSLSocketDataProvider ssl1(ASYNC, OK);
19540 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19541 SSLSocketDataProvider ssl2(ASYNC, OK);
19542 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19543
19544 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19545 auto trans1 =
19546 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19547
19548 TestCompletionCallback callback1;
19549
19550 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19551 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19552
19553 std::string response_data;
19554 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19555 EXPECT_EQ("hello", response_data);
19556
19557 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19558
19559 auto trans2 =
19560 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19561
19562 TestCompletionCallback callback2;
19563
19564 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19565 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19566
19567 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19568 EXPECT_EQ("world", response_data);
19569
19570 trans1.reset();
19571 trans2.reset();
19572
19573 // One 200 report from first request, then a 408 report from
19574 // the second request, then a 200 report from the successful retry.
19575 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19576
19577 // Check error report contents
19578 CheckReport(0 /* index */, 200 /* status_code */, OK);
19579 CheckReport(1 /* index */, 408 /* status_code */, OK);
19580 CheckReport(2 /* index */, 200 /* status_code */, OK);
19581}
19582
19583TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19584 CreateReportRetry421WithoutConnectionPooling) {
19585 // Two hosts resolve to the same IP address.
19586 const std::string ip_addr = "1.2.3.4";
19587 IPAddress ip;
19588 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
19589 IPEndPoint peer_addr = IPEndPoint(ip, 443);
19590
19591 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19592 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
19593 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
19594
19595 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19596
19597 // Two requests on the first connection.
19598 spdy::SpdySerializedFrame req1(
19599 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19600 spdy_util_.UpdateWithStreamDestruction(1);
19601 spdy::SpdySerializedFrame req2(
19602 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
19603 spdy::SpdySerializedFrame rst(
19604 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
19605 MockWrite writes1[] = {
19606 CreateMockWrite(req1, 0),
19607 CreateMockWrite(req2, 3),
19608 CreateMockWrite(rst, 6),
19609 };
19610
19611 // The first one succeeds, the second gets error 421 Misdirected Request.
19612 spdy::SpdySerializedFrame resp1(
19613 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19614 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
19615 spdy::SpdyHeaderBlock response_headers;
19616 response_headers[spdy::kHttp2StatusHeader] = "421";
19617 spdy::SpdySerializedFrame resp2(
19618 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
19619 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
19620 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
19621
19622 MockConnect connect1(ASYNC, OK, peer_addr);
19623 SequencedSocketData data1(connect1, reads1, writes1);
19624 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19625
19626 AddSSLSocketData();
19627
19628 // Retry the second request on a second connection.
19629 SpdyTestUtil spdy_util2;
19630 spdy::SpdySerializedFrame req3(
19631 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
19632 MockWrite writes2[] = {
19633 CreateMockWrite(req3, 0),
19634 };
19635
19636 spdy::SpdySerializedFrame resp3(
19637 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
19638 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
19639 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
19640 MockRead(ASYNC, 0, 3)};
19641
19642 MockConnect connect2(ASYNC, OK, peer_addr);
19643 SequencedSocketData data2(connect2, reads2, writes2);
19644 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19645
19646 AddSSLSocketData();
19647
19648 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3319649 int rv = session_deps_.host_resolver->LoadIntoCache(
19650 HostPortPair("mail.example.com", 443), base::nullopt);
19651 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4219652
19653 HttpRequestInfo request1;
19654 request1.method = "GET";
19655 request1.url = GURL("https://www.example.org/");
19656 request1.load_flags = 0;
19657 request1.traffic_annotation =
19658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19659 auto trans1 =
19660 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19661
Eric Orthf4db66a2019-02-19 21:35:3319662 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219663 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
19664 EXPECT_THAT(callback.GetResult(rv), IsOk());
19665
19666 const HttpResponseInfo* response = trans1->GetResponseInfo();
19667 ASSERT_TRUE(response);
19668 ASSERT_TRUE(response->headers);
19669 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19670 EXPECT_TRUE(response->was_fetched_via_spdy);
19671 EXPECT_TRUE(response->was_alpn_negotiated);
19672 std::string response_data;
19673 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19674 EXPECT_EQ("hello!", response_data);
19675
19676 trans1.reset();
19677
19678 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19679
19680 HttpRequestInfo request2;
19681 request2.method = "GET";
19682 request2.url = GURL("https://mail.example.org/");
19683 request2.load_flags = 0;
19684 request2.traffic_annotation =
19685 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19686 auto trans2 =
19687 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19688
19689 BoundTestNetLog log;
19690 rv = trans2->Start(&request2, callback.callback(), log.bound());
19691 EXPECT_THAT(callback.GetResult(rv), IsOk());
19692
19693 response = trans2->GetResponseInfo();
19694 ASSERT_TRUE(response);
19695 ASSERT_TRUE(response->headers);
19696 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19697 EXPECT_TRUE(response->was_fetched_via_spdy);
19698 EXPECT_TRUE(response->was_alpn_negotiated);
19699 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19700 EXPECT_EQ("hello!", response_data);
19701
19702 trans2.reset();
19703
19704 // One 200 report from the first request, then a 421 report from the
19705 // second request, then a 200 report from the successful retry.
19706 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19707
19708 // Check error report contents
19709 const NetworkErrorLoggingService::RequestDetails& error1 =
19710 network_error_logging_service()->errors()[0];
19711 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
19712 EXPECT_TRUE(error1.referrer.is_empty());
19713 EXPECT_EQ("", error1.user_agent);
19714 EXPECT_EQ(ip, error1.server_ip);
19715 EXPECT_EQ("h2", error1.protocol);
19716 EXPECT_EQ("GET", error1.method);
19717 EXPECT_EQ(200, error1.status_code);
19718 EXPECT_EQ(OK, error1.type);
19719 EXPECT_EQ(0, error1.reporting_upload_depth);
19720
19721 const NetworkErrorLoggingService::RequestDetails& error2 =
19722 network_error_logging_service()->errors()[1];
19723 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
19724 EXPECT_TRUE(error2.referrer.is_empty());
19725 EXPECT_EQ("", error2.user_agent);
19726 EXPECT_EQ(ip, error2.server_ip);
19727 EXPECT_EQ("h2", error2.protocol);
19728 EXPECT_EQ("GET", error2.method);
19729 EXPECT_EQ(421, error2.status_code);
19730 EXPECT_EQ(OK, error2.type);
19731 EXPECT_EQ(0, error2.reporting_upload_depth);
19732
19733 const NetworkErrorLoggingService::RequestDetails& error3 =
19734 network_error_logging_service()->errors()[2];
19735 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
19736 EXPECT_TRUE(error3.referrer.is_empty());
19737 EXPECT_EQ("", error3.user_agent);
19738 EXPECT_EQ(ip, error3.server_ip);
19739 EXPECT_EQ("h2", error3.protocol);
19740 EXPECT_EQ("GET", error3.method);
19741 EXPECT_EQ(200, error3.status_code);
19742 EXPECT_EQ(OK, error3.type);
19743 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3619744}
19745
Lily Chend3930e72019-03-01 19:31:1119746TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19747 CreateReportCancelAfterStart) {
19748 StaticSocketDataProvider data;
19749 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
19750 session_deps_.socket_factory->AddSocketDataProvider(&data);
19751
19752 TestCompletionCallback callback;
19753 auto session = CreateSession(&session_deps_);
19754 auto trans =
19755 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19756 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19757 EXPECT_EQ(rv, ERR_IO_PENDING);
19758
19759 // Cancel after start.
19760 trans.reset();
19761
19762 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19763 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
19764 IPAddress() /* server_ip */);
19765}
19766
19767TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19768 CreateReportCancelBeforeReadingBody) {
19769 std::string extra_header_string = extra_headers_.ToString();
19770 MockWrite data_writes[] = {
19771 MockWrite("GET / HTTP/1.1\r\n"
19772 "Host: www.example.org\r\n"
19773 "Connection: keep-alive\r\n"),
19774 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19775 };
19776 MockRead data_reads[] = {
19777 MockRead("HTTP/1.0 200 OK\r\n"),
19778 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
19779 };
19780
19781 StaticSocketDataProvider data(data_reads, data_writes);
19782 session_deps_.socket_factory->AddSocketDataProvider(&data);
19783
19784 SSLSocketDataProvider ssl(ASYNC, OK);
19785 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19786
19787 TestCompletionCallback callback;
19788 auto session = CreateSession(&session_deps_);
19789 auto trans =
19790 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19791 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19792 EXPECT_THAT(callback.GetResult(rv), IsOk());
19793
19794 const HttpResponseInfo* response = trans->GetResponseInfo();
19795 ASSERT_TRUE(response);
19796
19797 EXPECT_TRUE(response->headers);
19798 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19799
19800 // Cancel before reading the body.
19801 trans.reset();
19802
19803 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19804 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
19805}
19806
Lily Chen00196ab62018-12-04 19:52:2919807TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
19808 base::HistogramTester histograms;
19809 RequestPolicy();
19810 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19811 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19812
19813 // Make HTTP request
19814 std::string extra_header_string = extra_headers_.ToString();
19815 MockRead data_reads[] = {
19816 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19817 MockRead("hello world"),
19818 MockRead(SYNCHRONOUS, OK),
19819 };
19820 MockWrite data_writes[] = {
19821 MockWrite("GET / HTTP/1.1\r\n"
19822 "Host: www.example.org\r\n"
19823 "Connection: keep-alive\r\n"),
19824 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19825 };
19826
Lily Chend3930e72019-03-01 19:31:1119827 StaticSocketDataProvider data(data_reads, data_writes);
19828 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2919829
Lily Chenfec60d92019-01-24 01:16:4219830 // Insecure url
19831 url_ = "http://www.example.org/";
19832 request_.url = GURL(url_);
19833
Lily Chen00196ab62018-12-04 19:52:2919834 TestCompletionCallback callback;
19835 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4219836 auto trans =
19837 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19838 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19839 EXPECT_THAT(callback.GetResult(rv), IsOk());
19840
19841 std::string response_data;
19842 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19843 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2919844
19845 // Insecure request does not generate a report
19846 histograms.ExpectBucketCount(
19847 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519848 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919849
19850 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19851}
19852
19853TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19854 DontCreateReportHttpError) {
19855 base::HistogramTester histograms;
19856 RequestPolicy();
19857 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19858 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19859
19860 // Make HTTP request that fails
19861 MockRead data_reads[] = {
19862 MockRead("hello world"),
19863 MockRead(SYNCHRONOUS, OK),
19864 };
19865
19866 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19867 session_deps_.socket_factory->AddSocketDataProvider(&data);
19868
Lily Chenfec60d92019-01-24 01:16:4219869 url_ = "http://www.originwithoutpolicy.com:2000/";
19870 request_.url = GURL(url_);
19871
Lily Chen00196ab62018-12-04 19:52:2919872 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19873
Lily Chen00196ab62018-12-04 19:52:2919874 auto trans =
19875 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2919876 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219877 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2919878 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
19879
19880 // Insecure request does not generate a report, regardless of existence of a
19881 // policy for the origin.
19882 histograms.ExpectBucketCount(
19883 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519884 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919885
19886 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19887}
19888
Lily Chen90ae93cc2019-02-14 01:15:3919889// Don't report on proxy auth challenges, don't report if connecting through a
19890// proxy.
19891TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
19892 HttpRequestInfo request;
19893 request.method = "GET";
19894 request.url = GURL("https://www.example.org/");
19895 request.traffic_annotation =
19896 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19897
19898 // Configure against proxy server "myproxy:70".
19899 session_deps_.proxy_resolution_service =
19900 ProxyResolutionService::CreateFixedFromPacResult(
19901 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19902 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19903
19904 // Since we have proxy, should try to establish tunnel.
19905 MockWrite data_writes1[] = {
19906 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19907 "Host: www.example.org:443\r\n"
19908 "Proxy-Connection: keep-alive\r\n\r\n"),
19909 };
19910
19911 // The proxy responds to the connect with a 407, using a non-persistent
19912 // connection.
19913 MockRead data_reads1[] = {
19914 // No credentials.
19915 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
19916 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19917 MockRead("Proxy-Connection: close\r\n\r\n"),
19918 };
19919
19920 MockWrite data_writes2[] = {
19921 // After calling trans->RestartWithAuth(), this is the request we should
19922 // be issuing -- the final header line contains the credentials.
19923 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19924 "Host: www.example.org:443\r\n"
19925 "Proxy-Connection: keep-alive\r\n"
19926 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
19927
19928 MockWrite("GET / HTTP/1.1\r\n"
19929 "Host: www.example.org\r\n"
19930 "Connection: keep-alive\r\n\r\n"),
19931 };
19932
19933 MockRead data_reads2[] = {
19934 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19935
19936 MockRead("HTTP/1.1 200 OK\r\n"),
19937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19938 MockRead("Content-Length: 5\r\n\r\n"),
19939 MockRead(SYNCHRONOUS, "hello"),
19940 };
19941
19942 StaticSocketDataProvider data1(data_reads1, data_writes1);
19943 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19944 StaticSocketDataProvider data2(data_reads2, data_writes2);
19945 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19946 SSLSocketDataProvider ssl(ASYNC, OK);
19947 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19948
19949 TestCompletionCallback callback1;
19950
19951 auto trans =
19952 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19953
19954 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
19955 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19956
19957 const HttpResponseInfo* response = trans->GetResponseInfo();
19958 EXPECT_EQ(407, response->headers->response_code());
19959
19960 std::string response_data;
19961 rv = ReadTransaction(trans.get(), &response_data);
19962 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
19963
19964 // No NEL report is generated for the 407.
19965 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19966
19967 TestCompletionCallback callback2;
19968
19969 rv =
19970 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19971 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19972
19973 response = trans->GetResponseInfo();
19974 EXPECT_EQ(200, response->headers->response_code());
19975
19976 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19977 EXPECT_EQ("hello", response_data);
19978
19979 trans.reset();
19980
19981 // No NEL report is generated because we are behind a proxy.
19982 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19983}
19984
Douglas Creageref5eecdc2018-11-09 20:50:3619985TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19986 ReportContainsUploadDepth) {
19987 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4219988 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3619989 RequestPolicy();
19990 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219991 const NetworkErrorLoggingService::RequestDetails& error =
19992 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3619993 EXPECT_EQ(7, error.reporting_upload_depth);
19994}
19995
Lily Chenfec60d92019-01-24 01:16:4219996TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
19997 std::string extra_header_string = extra_headers_.ToString();
19998 static const base::TimeDelta kSleepDuration =
19999 base::TimeDelta::FromMilliseconds(10);
20000
20001 std::vector<MockWrite> data_writes = {
20002 MockWrite(ASYNC, 0,
20003 "GET / HTTP/1.1\r\n"
20004 "Host: www.example.org\r\n"
20005 "Connection: keep-alive\r\n"),
20006 MockWrite(ASYNC, 1, extra_header_string.data()),
20007 };
20008
20009 std::vector<MockRead> data_reads = {
20010 // Write one byte of the status line, followed by a pause.
20011 MockRead(ASYNC, 2, "H"),
20012 MockRead(ASYNC, ERR_IO_PENDING, 3),
20013 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
20014 MockRead(ASYNC, 5, "hello world"),
20015 MockRead(SYNCHRONOUS, OK, 6),
20016 };
20017
20018 SequencedSocketData data(data_reads, data_writes);
20019 session_deps_.socket_factory->AddSocketDataProvider(&data);
20020
20021 SSLSocketDataProvider ssl(ASYNC, OK);
20022 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20023
20024 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20025
20026 auto trans =
20027 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20028
20029 TestCompletionCallback callback;
20030
20031 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20032 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20033
20034 data.RunUntilPaused();
20035 ASSERT_TRUE(data.IsPaused());
20036 FastForwardBy(kSleepDuration);
20037 data.Resume();
20038
20039 EXPECT_THAT(callback.GetResult(rv), IsOk());
20040
20041 std::string response_data;
20042 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20043 EXPECT_EQ("hello world", response_data);
20044
20045 trans.reset();
20046
Douglas Creageref5eecdc2018-11-09 20:50:3620047 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220048
20049 CheckReport(0 /* index */, 200 /* status_code */, OK);
20050
20051 const NetworkErrorLoggingService::RequestDetails& error =
20052 network_error_logging_service()->errors()[0];
20053
20054 // Sanity-check elapsed time in error report
20055 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3620056}
Lily Chenfec60d92019-01-24 01:16:4220057
Douglas Creager3cb042052018-11-06 23:08:5220058#endif // BUILDFLAG(ENABLE_REPORTING)
20059
Batalov Vladislava4e97a502019-04-11 15:35:2320060TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
20061 HttpRequestInfo request;
20062 request.method = "GET";
20063 request.url = GURL("http://example.org/");
20064
20065 request.load_flags = LOAD_ONLY_FROM_CACHE;
20066
20067 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20068 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
20069 TestCompletionCallback callback1;
20070 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
20071
20072 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
20073}
20074
Steven Valdez1c1859172019-04-10 15:33:2820075TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
20076 HttpRequestInfo request;
20077 request.method = "GET";
20078 request.url = GURL("https://www.example.org/");
20079 request.traffic_annotation =
20080 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20081
20082 MockWrite data_writes[] = {
20083 MockWrite("GET / HTTP/1.1\r\n"
20084 "Host: www.example.org\r\n"
20085 "Connection: keep-alive\r\n\r\n"),
20086 };
20087
Steven Valdez1c1859172019-04-10 15:33:2820088 MockRead data_reads[] = {
20089 MockRead("HTTP/1.1 200 OK\r\n"),
20090 MockRead("Content-Length: 1\r\n\r\n"),
20091 MockRead(SYNCHRONOUS, "1"),
20092 };
20093
20094 StaticSocketDataProvider data(data_reads, data_writes);
20095 session_deps_.socket_factory->AddSocketDataProvider(&data);
20096 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20097 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20098 session_deps_.enable_early_data = true;
20099 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20100
20101 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20102
20103 TestCompletionCallback callback;
20104 auto trans =
20105 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20106
20107 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20108 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20109
20110 rv = callback.WaitForResult();
20111 EXPECT_THAT(rv, IsOk());
20112
20113 const HttpResponseInfo* response = trans->GetResponseInfo();
20114 ASSERT_TRUE(response);
20115 ASSERT_TRUE(response->headers);
20116 EXPECT_EQ(200, response->headers->response_code());
20117 EXPECT_EQ(1, response->headers->GetContentLength());
20118
20119 // Check that ConfirmHandshake wasn't called.
20120 ASSERT_FALSE(ssl.ConfirmDataConsumed());
20121 ASSERT_TRUE(ssl.WriteBeforeConfirm());
20122
20123 trans.reset();
20124
20125 session->CloseAllConnections();
20126}
20127
20128TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
20129 HttpRequestInfo request;
20130 request.method = "POST";
20131 request.url = GURL("https://www.example.org/");
20132 request.traffic_annotation =
20133 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20134
20135 MockWrite data_writes[] = {
20136 MockWrite(SYNCHRONOUS,
20137 "POST / HTTP/1.1\r\n"
20138 "Host: www.example.org\r\n"
20139 "Connection: keep-alive\r\n"
20140 "Content-Length: 0\r\n\r\n"),
20141 };
20142
Steven Valdez1c1859172019-04-10 15:33:2820143 MockRead data_reads[] = {
20144 MockRead("HTTP/1.1 200 OK\r\n"),
20145 MockRead("Content-Length: 1\r\n\r\n"),
20146 MockRead(SYNCHRONOUS, "1"),
20147 };
20148
20149 StaticSocketDataProvider data(data_reads, data_writes);
20150 session_deps_.socket_factory->AddSocketDataProvider(&data);
20151 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20152 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20153 session_deps_.enable_early_data = true;
20154 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20155
20156 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20157
20158 TestCompletionCallback callback;
20159 auto trans =
20160 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20161
20162 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20163 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20164
20165 rv = callback.WaitForResult();
20166 EXPECT_THAT(rv, IsOk());
20167
20168 const HttpResponseInfo* response = trans->GetResponseInfo();
20169 ASSERT_TRUE(response);
20170 ASSERT_TRUE(response->headers);
20171 EXPECT_EQ(200, response->headers->response_code());
20172 EXPECT_EQ(1, response->headers->GetContentLength());
20173
20174 // Check that the Write didn't get called before ConfirmHandshake completed.
20175 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20176
20177 trans.reset();
20178
20179 session->CloseAllConnections();
20180}
20181
20182TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
20183 HttpRequestInfo request;
20184 request.method = "POST";
20185 request.url = GURL("https://www.example.org/");
20186 request.traffic_annotation =
20187 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20188
20189 MockWrite data_writes[] = {
20190 MockWrite(ASYNC,
20191 "POST / HTTP/1.1\r\n"
20192 "Host: www.example.org\r\n"
20193 "Connection: keep-alive\r\n"
20194 "Content-Length: 0\r\n\r\n"),
20195 };
20196
Steven Valdez1c1859172019-04-10 15:33:2820197 MockRead data_reads[] = {
20198 MockRead("HTTP/1.1 200 OK\r\n"),
20199 MockRead("Content-Length: 1\r\n\r\n"),
20200 MockRead(SYNCHRONOUS, "1"),
20201 };
20202
20203 StaticSocketDataProvider data(data_reads, data_writes);
20204 session_deps_.socket_factory->AddSocketDataProvider(&data);
20205 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20206 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20207 session_deps_.enable_early_data = true;
20208 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20209
20210 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20211
20212 TestCompletionCallback callback;
20213 auto trans =
20214 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20215
20216 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20217 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20218
20219 rv = callback.WaitForResult();
20220 EXPECT_THAT(rv, IsOk());
20221
20222 const HttpResponseInfo* response = trans->GetResponseInfo();
20223 ASSERT_TRUE(response);
20224 ASSERT_TRUE(response->headers);
20225 EXPECT_EQ(200, response->headers->response_code());
20226 EXPECT_EQ(1, response->headers->GetContentLength());
20227
20228 // Check that the Write didn't get called before ConfirmHandshake completed.
20229 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20230
20231 trans.reset();
20232
20233 session->CloseAllConnections();
20234}
20235
20236TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
20237 HttpRequestInfo request;
20238 request.method = "POST";
20239 request.url = GURL("https://www.example.org/");
20240 request.traffic_annotation =
20241 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20242
20243 MockWrite data_writes[] = {
20244 MockWrite(SYNCHRONOUS,
20245 "POST / HTTP/1.1\r\n"
20246 "Host: www.example.org\r\n"
20247 "Connection: keep-alive\r\n"
20248 "Content-Length: 0\r\n\r\n"),
20249 };
20250
Steven Valdez1c1859172019-04-10 15:33:2820251 MockRead data_reads[] = {
20252 MockRead("HTTP/1.1 200 OK\r\n"),
20253 MockRead("Content-Length: 1\r\n\r\n"),
20254 MockRead(SYNCHRONOUS, "1"),
20255 };
20256
20257 StaticSocketDataProvider data(data_reads, data_writes);
20258 session_deps_.socket_factory->AddSocketDataProvider(&data);
20259 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20260 ssl.confirm = MockConfirm(ASYNC, OK);
20261 session_deps_.enable_early_data = true;
20262 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20263
20264 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20265
20266 TestCompletionCallback callback;
20267 auto trans =
20268 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20269
20270 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20271 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20272
20273 rv = callback.WaitForResult();
20274 EXPECT_THAT(rv, IsOk());
20275
20276 const HttpResponseInfo* response = trans->GetResponseInfo();
20277 ASSERT_TRUE(response);
20278 ASSERT_TRUE(response->headers);
20279 EXPECT_EQ(200, response->headers->response_code());
20280 EXPECT_EQ(1, response->headers->GetContentLength());
20281
20282 // Check that the Write didn't get called before ConfirmHandshake completed.
20283 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20284
20285 trans.reset();
20286
20287 session->CloseAllConnections();
20288}
20289
20290TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
20291 HttpRequestInfo request;
20292 request.method = "POST";
20293 request.url = GURL("https://www.example.org/");
20294 request.traffic_annotation =
20295 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20296
20297 MockWrite data_writes[] = {
20298 MockWrite(ASYNC,
20299 "POST / HTTP/1.1\r\n"
20300 "Host: www.example.org\r\n"
20301 "Connection: keep-alive\r\n"
20302 "Content-Length: 0\r\n\r\n"),
20303 };
20304
Steven Valdez1c1859172019-04-10 15:33:2820305 MockRead data_reads[] = {
20306 MockRead("HTTP/1.1 200 OK\r\n"),
20307 MockRead("Content-Length: 1\r\n\r\n"),
20308 MockRead(SYNCHRONOUS, "1"),
20309 };
20310
20311 StaticSocketDataProvider data(data_reads, data_writes);
20312 session_deps_.socket_factory->AddSocketDataProvider(&data);
20313 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20314 ssl.confirm = MockConfirm(ASYNC, OK);
20315 session_deps_.enable_early_data = true;
20316 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20317
20318 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20319
20320 TestCompletionCallback callback;
20321 auto trans =
20322 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20323
20324 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20325 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20326
20327 rv = callback.WaitForResult();
20328 EXPECT_THAT(rv, IsOk());
20329
20330 const HttpResponseInfo* response = trans->GetResponseInfo();
20331 ASSERT_TRUE(response);
20332 ASSERT_TRUE(response->headers);
20333 EXPECT_EQ(200, response->headers->response_code());
20334 EXPECT_EQ(1, response->headers->GetContentLength());
20335
20336 // Check that the Write didn't get called before ConfirmHandshake completed.
20337 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20338
20339 trans.reset();
20340
20341 session->CloseAllConnections();
20342}
20343
David Benjaminfb976932019-05-15 13:39:1520344// 0-RTT rejects are handled at HttpNetworkTransaction.
20345TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
20346 enum class RejectType {
20347 kRead,
20348 kWrite,
20349 kConfirm,
20350 };
20351
20352 for (RejectType type :
20353 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
20354 SCOPED_TRACE(static_cast<int>(type));
20355 for (Error reject_error :
20356 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
20357 SCOPED_TRACE(reject_error);
20358 session_deps_.socket_factory =
20359 std::make_unique<MockClientSocketFactory>();
20360
20361 HttpRequestInfo request;
20362 request.method = type == RejectType::kConfirm ? "POST" : "GET";
20363 request.url = GURL("https://www.example.org/");
20364 request.traffic_annotation =
20365 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20366
20367 // The first request fails.
20368 std::vector<MockWrite> data1_writes;
20369 std::vector<MockRead> data1_reads;
20370 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
20371 switch (type) {
20372 case RejectType::kRead:
20373 data1_writes.emplace_back(
20374 "GET / HTTP/1.1\r\n"
20375 "Host: www.example.org\r\n"
20376 "Connection: keep-alive\r\n\r\n");
20377 data1_reads.emplace_back(ASYNC, reject_error);
20378 // Cause ConfirmHandshake to hang (it should not be called).
20379 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20380 break;
20381 case RejectType::kWrite:
20382 data1_writes.emplace_back(ASYNC, reject_error);
20383 // Cause ConfirmHandshake to hang (it should not be called).
20384 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20385 break;
20386 case RejectType::kConfirm:
20387 // The request never gets far enough to read or write.
20388 ssl1.confirm = MockConfirm(ASYNC, reject_error);
20389 break;
20390 }
20391
20392 StaticSocketDataProvider data1(data1_reads, data1_writes);
20393 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20394 session_deps_.enable_early_data = true;
20395 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20396
20397 // The retry succeeds.
20398 //
20399 // TODO(https://crbug.com/950705): If |reject_error| is
20400 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
20401 MockWrite data2_writes[] = {
20402 request.method == "POST"
20403 ? MockWrite("POST / HTTP/1.1\r\n"
20404 "Host: www.example.org\r\n"
20405 "Connection: keep-alive\r\n"
20406 "Content-Length: 0\r\n\r\n")
20407 : MockWrite("GET / HTTP/1.1\r\n"
20408 "Host: www.example.org\r\n"
20409 "Connection: keep-alive\r\n\r\n"),
20410 };
20411
20412 MockRead data2_reads[] = {
20413 MockRead("HTTP/1.1 200 OK\r\n"),
20414 MockRead("Content-Length: 1\r\n\r\n"),
20415 MockRead(SYNCHRONOUS, "1"),
20416 };
20417
20418 StaticSocketDataProvider data2(data2_reads, data2_writes);
20419 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20420 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
20421 ssl2.confirm = MockConfirm(ASYNC, OK);
20422 session_deps_.enable_early_data = true;
20423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20424
20425 std::unique_ptr<HttpNetworkSession> session(
20426 CreateSession(&session_deps_));
20427
20428 TestCompletionCallback callback;
20429 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20430 session.get());
20431
20432 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20433 NetLogWithSource())),
20434 IsOk());
20435
20436 const HttpResponseInfo* response = trans->GetResponseInfo();
20437 ASSERT_TRUE(response);
20438 ASSERT_TRUE(response->headers);
20439 EXPECT_EQ(200, response->headers->response_code());
20440 EXPECT_EQ(1, response->headers->GetContentLength());
20441 }
20442 }
20443}
20444
Steven Valdez1c1859172019-04-10 15:33:2820445TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
20446 HttpRequestInfo request;
20447 request.method = "POST";
20448 request.url = GURL("https://www.example.org/");
20449 request.traffic_annotation =
20450 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20451
20452 MockWrite data_writes[] = {
20453 MockWrite("POST / HTTP/1.1\r\n"
20454 "Host: www.example.org\r\n"
20455 "Connection: keep-alive\r\n"
20456 "Content-Length: 0\r\n\r\n"),
20457 };
20458
Steven Valdez1c1859172019-04-10 15:33:2820459 MockRead data_reads[] = {
20460 MockRead("HTTP/1.1 200 OK\r\n"),
20461 MockRead("Content-Length: 1\r\n\r\n"),
20462 MockRead(SYNCHRONOUS, "1"),
20463 };
20464
20465 StaticSocketDataProvider data(data_reads, data_writes);
20466 session_deps_.socket_factory->AddSocketDataProvider(&data);
20467 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20468 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
20469 session_deps_.enable_early_data = true;
20470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20471
20472 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20473
20474 TestCompletionCallback callback;
20475 auto trans =
20476 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20477
20478 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20479 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20480
20481 rv = callback.WaitForResult();
20482 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20483
20484 // Check that the Write didn't get called before ConfirmHandshake completed.
20485 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20486
20487 trans.reset();
20488
20489 session->CloseAllConnections();
20490}
20491
20492TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
20493 HttpRequestInfo request;
20494 request.method = "POST";
20495 request.url = GURL("https://www.example.org/");
20496 request.traffic_annotation =
20497 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20498
20499 MockWrite data_writes[] = {
20500 MockWrite("POST / HTTP/1.1\r\n"
20501 "Host: www.example.org\r\n"
20502 "Connection: keep-alive\r\n"
20503 "Content-Length: 0\r\n\r\n"),
20504 };
20505
Steven Valdez1c1859172019-04-10 15:33:2820506 MockRead data_reads[] = {
20507 MockRead("HTTP/1.1 200 OK\r\n"),
20508 MockRead("Content-Length: 1\r\n\r\n"),
20509 MockRead(SYNCHRONOUS, "1"),
20510 };
20511
20512 StaticSocketDataProvider data(data_reads, data_writes);
20513 session_deps_.socket_factory->AddSocketDataProvider(&data);
20514 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20515 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
20516 session_deps_.enable_early_data = true;
20517 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20518
20519 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20520
20521 TestCompletionCallback callback;
20522 auto trans =
20523 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20524
20525 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20527
20528 rv = callback.WaitForResult();
20529 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20530
20531 // Check that the Write didn't get called before ConfirmHandshake completed.
20532 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20533
20534 trans.reset();
20535
20536 session->CloseAllConnections();
20537}
20538
David Benjamin2eb827f2019-04-29 18:31:0420539// Test the proxy and origin server each requesting both TLS client certificates
20540// and HTTP auth. This is a regression test for https://crbug.com/946406.
20541TEST_F(HttpNetworkTransactionTest, AuthEverything) {
20542 // Note these hosts must match the CheckBasic*Auth() functions.
20543 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20544 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20545
20546 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20547 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20548
20549 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20550 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20551 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20552 ASSERT_TRUE(identity_proxy);
20553
20554 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20555 cert_request_info_origin->host_and_port =
20556 HostPortPair("www.example.org", 443);
20557
20558 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20559 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20560 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20561 ASSERT_TRUE(identity_origin);
20562
20563 HttpRequestInfo request;
20564 request.method = "GET";
20565 request.url = GURL("https://www.example.org/");
20566 request.traffic_annotation =
20567 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20568
David Benjamin7ebab032019-04-30 21:51:3020569 // First, the client connects to the proxy, which requests a client
20570 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420571 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20572 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20573 ssl_proxy1.expected_send_client_cert = false;
David Benjamin2eb827f2019-04-29 18:31:0420574 StaticSocketDataProvider data1;
20575 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020576 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420577
David Benjamin7ebab032019-04-30 21:51:3020578 // The client responds with a certificate on a new connection. The handshake
20579 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420580 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20581 ssl_proxy2.expected_send_client_cert = true;
20582 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020583 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420584 std::vector<MockWrite> mock_writes2;
20585 std::vector<MockRead> mock_reads2;
20586 mock_writes2.emplace_back(
20587 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20588 "Host: www.example.org:443\r\n"
20589 "Proxy-Connection: keep-alive\r\n\r\n");
20590 mock_reads2.emplace_back(
20591 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20592 "Content-Length: 0\r\n"
20593 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020594 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0420595 mock_writes2.emplace_back(
20596 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20597 "Host: www.example.org:443\r\n"
20598 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020599 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420600 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20601 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20602 // The origin requests client certificates.
20603 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20604 ssl_origin2.cert_request_info = cert_request_info_origin.get();
David Benjamin2eb827f2019-04-29 18:31:0420605 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20606 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020607 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20608 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0420609
David Benjamin7ebab032019-04-30 21:51:3020610 // The client responds to the origin client certificate request on a new
20611 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420612 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20613 ssl_proxy3.expected_send_client_cert = true;
20614 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
David Benjamin2eb827f2019-04-29 18:31:0420615 std::vector<MockWrite> mock_writes3;
20616 std::vector<MockRead> mock_reads3;
20617 mock_writes3.emplace_back(
20618 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20619 "Host: www.example.org:443\r\n"
20620 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020621 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420622 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20623 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20624 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
20625 ssl_origin3.expected_send_client_cert = true;
20626 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020627 // The client sends the origin HTTP request, which results in another HTTP
20628 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0420629 mock_writes3.emplace_back(
20630 "GET / HTTP/1.1\r\n"
20631 "Host: www.example.org\r\n"
20632 "Connection: keep-alive\r\n\r\n");
20633 mock_reads3.emplace_back(
20634 "HTTP/1.1 401 Unauthorized\r\n"
20635 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20636 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020637 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420638 mock_writes3.emplace_back(
20639 "GET / HTTP/1.1\r\n"
20640 "Host: www.example.org\r\n"
20641 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020642 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420643 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20644 mock_reads3.emplace_back(
20645 "HTTP/1.1 200 OK\r\n"
20646 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4120647 // The client makes another request. This should reuse the socket with all
20648 // credentials cached.
20649 mock_writes3.emplace_back(
20650 "GET / HTTP/1.1\r\n"
20651 "Host: www.example.org\r\n"
20652 "Connection: keep-alive\r\n"
20653 // Authenticate as user:pass.
20654 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20655 mock_reads3.emplace_back(
20656 "HTTP/1.1 200 OK\r\n"
20657 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0420658 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20659 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020660 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20661 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420662
20663 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20664
20665 // Start the request.
20666 TestCompletionCallback callback;
20667 auto trans =
20668 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20669 int rv = callback.GetResult(
20670 trans->Start(&request, callback.callback(), NetLogWithSource()));
20671
20672 // Handle the proxy client certificate challenge.
20673 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20674 SSLCertRequestInfo* cert_request_info =
20675 trans->GetResponseInfo()->cert_request_info.get();
20676 ASSERT_TRUE(cert_request_info);
20677 EXPECT_TRUE(cert_request_info->is_proxy);
20678 EXPECT_EQ(cert_request_info->host_and_port,
20679 cert_request_info_proxy->host_and_port);
20680 rv = callback.GetResult(trans->RestartWithCertificate(
20681 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20682 callback.callback()));
20683
20684 // Handle the proxy HTTP auth challenge.
20685 ASSERT_THAT(rv, IsOk());
20686 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20687 EXPECT_TRUE(
20688 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20689 rv = callback.GetResult(trans->RestartWithAuth(
20690 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20691 callback.callback()));
20692
20693 // Handle the origin client certificate challenge.
20694 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20695 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20696 ASSERT_TRUE(cert_request_info);
20697 EXPECT_FALSE(cert_request_info->is_proxy);
20698 EXPECT_EQ(cert_request_info->host_and_port,
20699 cert_request_info_origin->host_and_port);
20700 rv = callback.GetResult(trans->RestartWithCertificate(
20701 identity_origin->certificate(), identity_origin->ssl_private_key(),
20702 callback.callback()));
20703
20704 // Handle the origin HTTP auth challenge.
20705 ASSERT_THAT(rv, IsOk());
20706 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20707 EXPECT_TRUE(
20708 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20709 rv = callback.GetResult(trans->RestartWithAuth(
20710 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20711 callback.callback()));
20712
20713 // The request completes.
20714 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020715 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4120716
20717 // Make a second request. This time all credentials are cached.
20718 trans =
20719 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20720 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20721 NetLogWithSource())),
20722 IsOk());
20723 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420724}
20725
20726// Test the proxy and origin server each requesting both TLS client certificates
20727// and HTTP auth and each HTTP auth closing the connection. This is a regression
20728// test for https://crbug.com/946406.
20729TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
20730 // Note these hosts must match the CheckBasic*Auth() functions.
20731 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20732 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20733
20734 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20735 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20736
20737 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20738 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20739 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20740 ASSERT_TRUE(identity_proxy);
20741
20742 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20743 cert_request_info_origin->host_and_port =
20744 HostPortPair("www.example.org", 443);
20745
20746 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20747 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20748 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20749 ASSERT_TRUE(identity_origin);
20750
20751 HttpRequestInfo request;
20752 request.method = "GET";
20753 request.url = GURL("https://www.example.org/");
20754 request.traffic_annotation =
20755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20756
David Benjamin7ebab032019-04-30 21:51:3020757 // First, the client connects to the proxy, which requests a client
20758 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420759 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20760 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20761 ssl_proxy1.expected_send_client_cert = false;
20762 StaticSocketDataProvider data1;
20763 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020764 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420765
David Benjamin7ebab032019-04-30 21:51:3020766 // The client responds with a certificate on a new connection. The handshake
20767 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420768 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20769 ssl_proxy2.expected_send_client_cert = true;
20770 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020771 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420772 std::vector<MockWrite> mock_writes2;
20773 std::vector<MockRead> mock_reads2;
20774 mock_writes2.emplace_back(
20775 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20776 "Host: www.example.org:443\r\n"
20777 "Proxy-Connection: keep-alive\r\n\r\n");
20778 mock_reads2.emplace_back(
20779 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20780 "Content-Length: 0\r\n"
20781 "Proxy-Connection: close\r\n"
20782 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20783 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20784 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020785 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0420786
David Benjamin7ebab032019-04-30 21:51:3020787 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0420788 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20789 ssl_proxy3.expected_send_client_cert = true;
20790 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
20791 std::vector<MockWrite> mock_writes3;
20792 std::vector<MockRead> mock_reads3;
20793 mock_writes3.emplace_back(
20794 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20795 "Host: www.example.org:443\r\n"
20796 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020797 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420798 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20799 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20800 // The origin requests client certificates.
20801 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20802 ssl_origin3.cert_request_info = cert_request_info_origin.get();
20803 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20804 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020805 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20806 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420807
David Benjamin7ebab032019-04-30 21:51:3020808 // The client responds to the origin client certificate request on a new
20809 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420810 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
20811 ssl_proxy4.expected_send_client_cert = true;
20812 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
20813 std::vector<MockWrite> mock_writes4;
20814 std::vector<MockRead> mock_reads4;
20815 mock_writes4.emplace_back(
20816 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20817 "Host: www.example.org:443\r\n"
20818 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020819 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420820 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20821 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20822 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
20823 ssl_origin4.expected_send_client_cert = true;
20824 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020825 // The client sends the origin HTTP request, which results in another HTTP
20826 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0420827 mock_writes4.emplace_back(
20828 "GET / HTTP/1.1\r\n"
20829 "Host: www.example.org\r\n"
20830 "Connection: keep-alive\r\n\r\n");
20831 mock_reads4.emplace_back(
20832 "HTTP/1.1 401 Unauthorized\r\n"
20833 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20834 "Connection: close\r\n"
20835 "Content-Length: 0\r\n\r\n");
20836 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
20837 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3020838 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
20839 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0420840
David Benjamin7ebab032019-04-30 21:51:3020841 // The client retries with credentials on a new connection, and the request
20842 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420843 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
20844 ssl_proxy5.expected_send_client_cert = true;
20845 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
20846 std::vector<MockWrite> mock_writes5;
20847 std::vector<MockRead> mock_reads5;
20848 mock_writes5.emplace_back(
20849 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20850 "Host: www.example.org:443\r\n"
20851 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020852 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420853 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20854 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20855 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
20856 ssl_origin5.expected_send_client_cert = true;
20857 ssl_origin5.expected_client_cert = identity_origin->certificate();
20858 mock_writes5.emplace_back(
20859 "GET / HTTP/1.1\r\n"
20860 "Host: www.example.org\r\n"
20861 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020862 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420863 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20864 mock_reads5.emplace_back(
20865 "HTTP/1.1 200 OK\r\n"
20866 "Connection: close\r\n"
20867 "Content-Length: 0\r\n\r\n");
20868 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
20869 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3020870 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
20871 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0420872
David Benjaminbac8dff2019-08-07 01:30:4120873 // The client makes a second request. This needs yet another connection, but
20874 // all credentials are cached.
20875 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
20876 ssl_proxy6.expected_send_client_cert = true;
20877 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
20878 std::vector<MockWrite> mock_writes6;
20879 std::vector<MockRead> mock_reads6;
20880 mock_writes6.emplace_back(
20881 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20882 "Host: www.example.org:443\r\n"
20883 "Proxy-Connection: keep-alive\r\n"
20884 // Authenticate as proxyuser:proxypass.
20885 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20886 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20887 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
20888 ssl_origin6.expected_send_client_cert = true;
20889 ssl_origin6.expected_client_cert = identity_origin->certificate();
20890 mock_writes6.emplace_back(
20891 "GET / HTTP/1.1\r\n"
20892 "Host: www.example.org\r\n"
20893 "Connection: keep-alive\r\n"
20894 // Authenticate as user:pass.
20895 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20896 mock_reads6.emplace_back(
20897 "HTTP/1.1 200 OK\r\n"
20898 "Connection: close\r\n"
20899 "Content-Length: 0\r\n\r\n");
20900 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
20901 session_deps_.socket_factory->AddSocketDataProvider(&data6);
20902 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
20903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
20904
David Benjamin2eb827f2019-04-29 18:31:0420905 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20906
20907 // Start the request.
20908 TestCompletionCallback callback;
20909 auto trans =
20910 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20911 int rv = callback.GetResult(
20912 trans->Start(&request, callback.callback(), NetLogWithSource()));
20913
20914 // Handle the proxy client certificate challenge.
20915 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20916 SSLCertRequestInfo* cert_request_info =
20917 trans->GetResponseInfo()->cert_request_info.get();
20918 ASSERT_TRUE(cert_request_info);
20919 EXPECT_TRUE(cert_request_info->is_proxy);
20920 EXPECT_EQ(cert_request_info->host_and_port,
20921 cert_request_info_proxy->host_and_port);
20922 rv = callback.GetResult(trans->RestartWithCertificate(
20923 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20924 callback.callback()));
20925
20926 // Handle the proxy HTTP auth challenge.
20927 ASSERT_THAT(rv, IsOk());
20928 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20929 EXPECT_TRUE(
20930 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20931 rv = callback.GetResult(trans->RestartWithAuth(
20932 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20933 callback.callback()));
20934
20935 // Handle the origin client certificate challenge.
20936 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20937 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20938 ASSERT_TRUE(cert_request_info);
20939 EXPECT_FALSE(cert_request_info->is_proxy);
20940 EXPECT_EQ(cert_request_info->host_and_port,
20941 cert_request_info_origin->host_and_port);
20942 rv = callback.GetResult(trans->RestartWithCertificate(
20943 identity_origin->certificate(), identity_origin->ssl_private_key(),
20944 callback.callback()));
20945
20946 // Handle the origin HTTP auth challenge.
20947 ASSERT_THAT(rv, IsOk());
20948 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20949 EXPECT_TRUE(
20950 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20951 rv = callback.GetResult(trans->RestartWithAuth(
20952 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20953 callback.callback()));
20954
20955 // The request completes.
20956 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020957 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4120958
20959 // Make a second request. This time all credentials are cached.
20960 trans =
20961 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20962 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20963 NetLogWithSource())),
20964 IsOk());
20965 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3020966}
20967
20968// Test the proxy requesting HTTP auth and the server requesting TLS client
20969// certificates. This is a regression test for https://crbug.com/946406.
20970TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
20971 // Note these hosts must match the CheckBasic*Auth() functions.
20972 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20973 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20974
20975 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20976 cert_request_info_origin->host_and_port =
20977 HostPortPair("www.example.org", 443);
20978
20979 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20980 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20981 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20982 ASSERT_TRUE(identity_origin);
20983
20984 HttpRequestInfo request;
20985 request.method = "GET";
20986 request.url = GURL("https://www.example.org/");
20987 request.traffic_annotation =
20988 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20989
20990 // The client connects to the proxy. The handshake succeeds.
20991 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
20992 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20993 std::vector<MockWrite> mock_writes1;
20994 std::vector<MockRead> mock_reads1;
20995 mock_writes1.emplace_back(
20996 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20997 "Host: www.example.org:443\r\n"
20998 "Proxy-Connection: keep-alive\r\n\r\n");
20999 mock_reads1.emplace_back(
21000 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21001 "Content-Length: 0\r\n"
21002 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21003 // The client retries with credentials, and the request finally succeeds.
21004 mock_writes1.emplace_back(
21005 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21006 "Host: www.example.org:443\r\n"
21007 "Proxy-Connection: keep-alive\r\n"
21008 // Authenticate as proxyuser:proxypass.
21009 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21010 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21011 // The origin requests client certificates.
21012 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21013 ssl_origin1.cert_request_info = cert_request_info_origin.get();
21014 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
21015 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21016 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21017 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21018
21019 // The client responds to the origin client certificate request on a new
21020 // connection.
21021 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21022 std::vector<MockWrite> mock_writes2;
21023 std::vector<MockRead> mock_reads2;
21024 mock_writes2.emplace_back(
21025 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21026 "Host: www.example.org:443\r\n"
21027 "Proxy-Connection: keep-alive\r\n"
21028 // Authenticate as proxyuser:proxypass.
21029 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21030 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21031 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
21032 ssl_origin2.expected_send_client_cert = true;
21033 ssl_origin2.expected_client_cert = identity_origin->certificate();
21034 // The client sends the origin HTTP request, which succeeds.
21035 mock_writes2.emplace_back(
21036 "GET / HTTP/1.1\r\n"
21037 "Host: www.example.org\r\n"
21038 "Connection: keep-alive\r\n\r\n");
21039 mock_reads2.emplace_back(
21040 "HTTP/1.1 200 OK\r\n"
21041 "Content-Length: 0\r\n\r\n");
21042 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21043 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21044 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21045 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
21046
21047 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21048
21049 // Start the request.
21050 TestCompletionCallback callback;
21051 auto trans =
21052 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21053 int rv = callback.GetResult(
21054 trans->Start(&request, callback.callback(), NetLogWithSource()));
21055
21056 // Handle the proxy HTTP auth challenge.
21057 ASSERT_THAT(rv, IsOk());
21058 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21059 EXPECT_TRUE(
21060 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21061 rv = callback.GetResult(trans->RestartWithAuth(
21062 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21063 callback.callback()));
21064
21065 // Handle the origin client certificate challenge.
21066 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21067 SSLCertRequestInfo* cert_request_info =
21068 trans->GetResponseInfo()->cert_request_info.get();
21069 ASSERT_TRUE(cert_request_info);
21070 EXPECT_FALSE(cert_request_info->is_proxy);
21071 EXPECT_EQ(cert_request_info->host_and_port,
21072 cert_request_info_origin->host_and_port);
21073 rv = callback.GetResult(trans->RestartWithCertificate(
21074 identity_origin->certificate(), identity_origin->ssl_private_key(),
21075 callback.callback()));
21076
21077 // The request completes.
21078 ASSERT_THAT(rv, IsOk());
21079 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421080}
21081
David Benjamin6e673a82019-04-30 22:52:5821082// Test that socket reuse works with client certificates.
21083TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
21084 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
21085 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
21086
21087 std::unique_ptr<FakeClientCertIdentity> identity =
21088 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21089 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21090 ASSERT_TRUE(identity);
21091
21092 HttpRequestInfo request1;
21093 request1.method = "GET";
21094 request1.url = GURL("https://www.example.org/a");
21095 request1.traffic_annotation =
21096 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21097
21098 HttpRequestInfo request2;
21099 request2.method = "GET";
21100 request2.url = GURL("https://www.example.org/b");
21101 request2.traffic_annotation =
21102 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21103
21104 // The first connection results in a client certificate request.
21105 StaticSocketDataProvider data1;
21106 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21107 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21108 ssl1.cert_request_info = cert_request_info.get();
21109 ssl1.expected_send_client_cert = false;
21110 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21111
21112 // The second connection succeeds and is usable for both requests.
21113 MockWrite mock_writes[] = {
21114 MockWrite("GET /a HTTP/1.1\r\n"
21115 "Host: www.example.org\r\n"
21116 "Connection: keep-alive\r\n\r\n"),
21117 MockWrite("GET /b HTTP/1.1\r\n"
21118 "Host: www.example.org\r\n"
21119 "Connection: keep-alive\r\n\r\n"),
21120 };
21121 MockRead mock_reads[] = {
21122 MockRead("HTTP/1.1 200 OK\r\n"
21123 "Content-Length: 0\r\n\r\n"),
21124 MockRead("HTTP/1.1 200 OK\r\n"
21125 "Content-Length: 0\r\n\r\n"),
21126 };
21127 StaticSocketDataProvider data2(mock_reads, mock_writes);
21128 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21129 SSLSocketDataProvider ssl2(ASYNC, OK);
21130 ssl2.expected_send_client_cert = true;
21131 ssl2.expected_client_cert = identity->certificate();
21132 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21133
21134 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21135
21136 // Start the first request. It succeeds after providing client certificates.
21137 TestCompletionCallback callback;
21138 auto trans =
21139 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21140 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
21141 NetLogWithSource())),
21142 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21143
21144 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
21145 ASSERT_TRUE(info);
21146 EXPECT_FALSE(info->is_proxy);
21147 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
21148
21149 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
21150 identity->certificate(), identity->ssl_private_key(),
21151 callback.callback())),
21152 IsOk());
21153 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21154
21155 // Make the second request. It completes without requesting client
21156 // certificates.
21157 trans =
21158 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21159 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
21160 NetLogWithSource())),
21161 IsOk());
21162 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21163}
21164
Matt Menke166443c2019-05-24 18:45:5921165// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
21166// sequence with two different NetworkIsolationKeys, the first and last have the
21167// same key, the second a different one. Checks that the requests are
21168// partitioned across sockets as expected.
21169TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2721170 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21171 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21172 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21173 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5921174
21175 for (bool partition_connections : {false, true}) {
21176 SCOPED_TRACE(partition_connections);
21177
21178 base::test::ScopedFeatureList feature_list;
21179 if (partition_connections) {
21180 feature_list.InitAndEnableFeature(
21181 features::kPartitionConnectionsByNetworkIsolationKey);
21182 } else {
21183 feature_list.InitAndDisableFeature(
21184 features::kPartitionConnectionsByNetworkIsolationKey);
21185 }
21186
21187 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21188
21189 // Reads and writes for the unpartitioned case, where only one socket is
21190 // used.
21191
21192 const MockWrite kUnpartitionedWrites[] = {
21193 MockWrite("GET /1 HTTP/1.1\r\n"
21194 "Host: foo.test\r\n"
21195 "Connection: keep-alive\r\n\r\n"),
21196 MockWrite("GET /2 HTTP/1.1\r\n"
21197 "Host: foo.test\r\n"
21198 "Connection: keep-alive\r\n\r\n"),
21199 MockWrite("GET /3 HTTP/1.1\r\n"
21200 "Host: foo.test\r\n"
21201 "Connection: keep-alive\r\n\r\n"),
21202 };
21203
21204 const MockRead kUnpartitionedReads[] = {
21205 MockRead("HTTP/1.1 200 OK\r\n"
21206 "Connection: keep-alive\r\n"
21207 "Content-Length: 1\r\n\r\n"
21208 "1"),
21209 MockRead("HTTP/1.1 200 OK\r\n"
21210 "Connection: keep-alive\r\n"
21211 "Content-Length: 1\r\n\r\n"
21212 "2"),
21213 MockRead("HTTP/1.1 200 OK\r\n"
21214 "Connection: keep-alive\r\n"
21215 "Content-Length: 1\r\n\r\n"
21216 "3"),
21217 };
21218
21219 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
21220 kUnpartitionedWrites);
21221
21222 // Reads and writes for the partitioned case, where two sockets are used.
21223
21224 const MockWrite kPartitionedWrites1[] = {
21225 MockWrite("GET /1 HTTP/1.1\r\n"
21226 "Host: foo.test\r\n"
21227 "Connection: keep-alive\r\n\r\n"),
21228 MockWrite("GET /3 HTTP/1.1\r\n"
21229 "Host: foo.test\r\n"
21230 "Connection: keep-alive\r\n\r\n"),
21231 };
21232
21233 const MockRead kPartitionedReads1[] = {
21234 MockRead("HTTP/1.1 200 OK\r\n"
21235 "Connection: keep-alive\r\n"
21236 "Content-Length: 1\r\n\r\n"
21237 "1"),
21238 MockRead("HTTP/1.1 200 OK\r\n"
21239 "Connection: keep-alive\r\n"
21240 "Content-Length: 1\r\n\r\n"
21241 "3"),
21242 };
21243
21244 const MockWrite kPartitionedWrites2[] = {
21245 MockWrite("GET /2 HTTP/1.1\r\n"
21246 "Host: foo.test\r\n"
21247 "Connection: keep-alive\r\n\r\n"),
21248 };
21249
21250 const MockRead kPartitionedReads2[] = {
21251 MockRead("HTTP/1.1 200 OK\r\n"
21252 "Connection: keep-alive\r\n"
21253 "Content-Length: 1\r\n\r\n"
21254 "2"),
21255 };
21256
21257 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
21258 kPartitionedWrites1);
21259 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
21260 kPartitionedWrites2);
21261
21262 if (partition_connections) {
21263 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21264 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21265 } else {
21266 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
21267 }
21268
21269 TestCompletionCallback callback;
21270 HttpRequestInfo request1;
21271 request1.method = "GET";
21272 request1.url = GURL("http://foo.test/1");
21273 request1.traffic_annotation =
21274 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21275 request1.network_isolation_key = network_isolation_key1;
21276 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21277 session.get());
21278 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21279 EXPECT_THAT(callback.GetResult(rv), IsOk());
21280 std::string response_data1;
21281 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21282 EXPECT_EQ("1", response_data1);
21283 trans1.reset();
21284
21285 HttpRequestInfo request2;
21286 request2.method = "GET";
21287 request2.url = GURL("http://foo.test/2");
21288 request2.traffic_annotation =
21289 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21290 request2.network_isolation_key = network_isolation_key2;
21291 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21292 session.get());
21293 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21294 EXPECT_THAT(callback.GetResult(rv), IsOk());
21295 std::string response_data2;
21296 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21297 EXPECT_EQ("2", response_data2);
21298 trans2.reset();
21299
21300 HttpRequestInfo request3;
21301 request3.method = "GET";
21302 request3.url = GURL("http://foo.test/3");
21303 request3.traffic_annotation =
21304 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21305 request3.network_isolation_key = network_isolation_key1;
21306 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21307 session.get());
21308 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21309 EXPECT_THAT(callback.GetResult(rv), IsOk());
21310 std::string response_data3;
21311 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21312 EXPECT_EQ("3", response_data3);
21313 trans3.reset();
21314 }
21315}
21316
Matt Menkeae58eeb2019-05-24 21:09:5021317TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2721318 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21319 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21320 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21321 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5021322
21323 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
21324 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
21325 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
21326 // the same way as the HTTP over H2 proxy case.
21327 for (bool use_proxy : {false, true}) {
21328 SCOPED_TRACE(use_proxy);
21329 if (use_proxy) {
21330 session_deps_.proxy_resolution_service =
21331 ProxyResolutionService::CreateFixedFromPacResult(
21332 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
21333 } else {
21334 session_deps_.proxy_resolution_service =
21335 ProxyResolutionService::CreateDirect();
21336 }
21337 const char* url1 = nullptr;
21338 const char* url2 = nullptr;
21339 const char* url3 = nullptr;
21340 if (use_proxy) {
21341 url1 = "http://foo.test/1";
21342 url2 = "http://foo.test/2";
21343 url3 = "http://foo.test/3";
21344 } else {
21345 url1 = "https://foo.test/1";
21346 url2 = "https://foo.test/2";
21347 url3 = "https://foo.test/3";
21348 }
21349
21350 for (bool partition_connections : {false, true}) {
21351 SCOPED_TRACE(partition_connections);
21352
21353 base::test::ScopedFeatureList feature_list;
21354 if (partition_connections) {
21355 feature_list.InitAndEnableFeature(
21356 features::kPartitionConnectionsByNetworkIsolationKey);
21357 } else {
21358 feature_list.InitAndDisableFeature(
21359 features::kPartitionConnectionsByNetworkIsolationKey);
21360 }
21361
21362 std::unique_ptr<HttpNetworkSession> session(
21363 CreateSession(&session_deps_));
21364
21365 // Reads and writes for the unpartitioned case, where only one socket is
21366 // used.
21367
21368 SpdyTestUtil spdy_util;
21369 spdy::SpdySerializedFrame unpartitioned_req1(
21370 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
21371 spdy::SpdySerializedFrame unpartitioned_response1(
21372 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
21373 spdy::SpdySerializedFrame unpartitioned_body1(
21374 spdy_util.ConstructSpdyDataFrame(1, "1", true));
21375 spdy_util.UpdateWithStreamDestruction(1);
21376
21377 spdy::SpdySerializedFrame unpartitioned_req2(
21378 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
21379 spdy::SpdySerializedFrame unpartitioned_response2(
21380 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
21381 spdy::SpdySerializedFrame unpartitioned_body2(
21382 spdy_util.ConstructSpdyDataFrame(3, "2", true));
21383 spdy_util.UpdateWithStreamDestruction(3);
21384
21385 spdy::SpdySerializedFrame unpartitioned_req3(
21386 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
21387 spdy::SpdySerializedFrame unpartitioned_response3(
21388 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
21389 spdy::SpdySerializedFrame unpartitioned_body3(
21390 spdy_util.ConstructSpdyDataFrame(5, "3", true));
21391
21392 const MockWrite kUnpartitionedWrites[] = {
21393 CreateMockWrite(unpartitioned_req1, 0),
21394 CreateMockWrite(unpartitioned_req2, 3),
21395 CreateMockWrite(unpartitioned_req3, 6),
21396 };
21397
21398 const MockRead kUnpartitionedReads[] = {
21399 CreateMockRead(unpartitioned_response1, 1),
21400 CreateMockRead(unpartitioned_body1, 2),
21401 CreateMockRead(unpartitioned_response2, 4),
21402 CreateMockRead(unpartitioned_body2, 5),
21403 CreateMockRead(unpartitioned_response3, 7),
21404 CreateMockRead(unpartitioned_body3, 8),
21405 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
21406 };
21407
21408 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
21409 kUnpartitionedWrites);
21410
21411 // Reads and writes for the partitioned case, where two sockets are used.
21412
21413 SpdyTestUtil spdy_util2;
21414 spdy::SpdySerializedFrame partitioned_req1(
21415 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
21416 spdy::SpdySerializedFrame partitioned_response1(
21417 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
21418 spdy::SpdySerializedFrame partitioned_body1(
21419 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
21420 spdy_util2.UpdateWithStreamDestruction(1);
21421
21422 spdy::SpdySerializedFrame partitioned_req3(
21423 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
21424 spdy::SpdySerializedFrame partitioned_response3(
21425 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
21426 spdy::SpdySerializedFrame partitioned_body3(
21427 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
21428
21429 const MockWrite kPartitionedWrites1[] = {
21430 CreateMockWrite(partitioned_req1, 0),
21431 CreateMockWrite(partitioned_req3, 3),
21432 };
21433
21434 const MockRead kPartitionedReads1[] = {
21435 CreateMockRead(partitioned_response1, 1),
21436 CreateMockRead(partitioned_body1, 2),
21437 CreateMockRead(partitioned_response3, 4),
21438 CreateMockRead(partitioned_body3, 5),
21439 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
21440 };
21441
21442 SpdyTestUtil spdy_util3;
21443 spdy::SpdySerializedFrame partitioned_req2(
21444 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
21445 spdy::SpdySerializedFrame partitioned_response2(
21446 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
21447 spdy::SpdySerializedFrame partitioned_body2(
21448 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
21449
21450 const MockWrite kPartitionedWrites2[] = {
21451 CreateMockWrite(partitioned_req2, 0),
21452 };
21453
21454 const MockRead kPartitionedReads2[] = {
21455 CreateMockRead(partitioned_response2, 1),
21456 CreateMockRead(partitioned_body2, 2),
21457 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
21458 };
21459
21460 SequencedSocketData partitioned_data1(kPartitionedReads1,
21461 kPartitionedWrites1);
21462 SequencedSocketData partitioned_data2(kPartitionedReads2,
21463 kPartitionedWrites2);
21464
21465 // No need to segment SSLDataProviders by whether or not partitioning is
21466 // enabled.
21467 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21468 ssl_data1.next_proto = kProtoHTTP2;
21469 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21470 ssl_data2.next_proto = kProtoHTTP2;
21471
21472 if (partition_connections) {
21473 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21474 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21475 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21476 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21477 } else {
21478 session_deps_.socket_factory->AddSocketDataProvider(
21479 &unpartitioned_data);
21480 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21481 }
21482
21483 TestCompletionCallback callback;
21484 HttpRequestInfo request1;
21485 request1.method = "GET";
21486 request1.url = GURL(url1);
21487 request1.traffic_annotation =
21488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21489 request1.network_isolation_key = network_isolation_key1;
21490 auto trans1 =
21491 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21492 int rv =
21493 trans1->Start(&request1, callback.callback(), NetLogWithSource());
21494 EXPECT_THAT(callback.GetResult(rv), IsOk());
21495 std::string response_data1;
21496 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21497 EXPECT_EQ("1", response_data1);
21498 trans1.reset();
21499
21500 HttpRequestInfo request2;
21501 request2.method = "GET";
21502 request2.url = GURL(url2);
21503 request2.traffic_annotation =
21504 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21505 request2.network_isolation_key = network_isolation_key2;
21506 auto trans2 =
21507 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21508 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21509 EXPECT_THAT(callback.GetResult(rv), IsOk());
21510 std::string response_data2;
21511 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21512 EXPECT_EQ("2", response_data2);
21513 trans2.reset();
21514
21515 HttpRequestInfo request3;
21516 request3.method = "GET";
21517 request3.url = GURL(url3);
21518 request3.traffic_annotation =
21519 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21520 request3.network_isolation_key = network_isolation_key1;
21521 auto trans3 =
21522 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21523 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21524 EXPECT_THAT(callback.GetResult(rv), IsOk());
21525 std::string response_data3;
21526 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21527 EXPECT_EQ("3", response_data3);
21528 trans3.reset();
21529 }
21530 }
21531}
21532
Matt Menke7281f872019-06-25 19:29:2521533// Preconnect two sockets with different NetworkIsolationKeys when
21534// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
21535// request and make sure the correct socket is used. Loops three times,
21536// expecting to use the first preconnect, second preconnect, and neither.
21537TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
21538 base::test::ScopedFeatureList feature_list;
21539 feature_list.InitAndEnableFeature(
21540 features::kPartitionConnectionsByNetworkIsolationKey);
21541
21542 enum class TestCase {
21543 kUseFirstPreconnect,
21544 kUseSecondPreconnect,
21545 kDontUsePreconnect,
21546 };
21547
Shivani Sharma8ae506c2019-07-21 21:08:2721548 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21549 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21550 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
21551 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
21552 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
21553 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2521554
21555 // Test that only preconnects with
21556 for (TestCase test_case :
21557 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
21558 TestCase::kDontUsePreconnect}) {
21559 SpdySessionDependencies session_deps;
21560 // Make DNS lookups completely synchronously, so preconnects complete
21561 // immediately.
21562 session_deps.host_resolver->set_synchronous_mode(true);
21563
21564 const MockWrite kMockWrites[] = {
21565 MockWrite(ASYNC, 0,
21566 "GET / HTTP/1.1\r\n"
21567 "Host: www.foo.com\r\n"
21568 "Connection: keep-alive\r\n\r\n"),
21569 };
21570
21571 const MockRead kMockReads[] = {
21572 MockRead(ASYNC, 1,
21573 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
21574 "hello"),
21575 };
21576
21577 // Used for the socket that will actually be used, which may or may not be
21578 // one of the preconnects
21579 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
21580 kMockReads, kMockWrites);
21581
21582 // Used for the preconnects that won't actually be used.
21583 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
21584 base::span<const MockRead>(),
21585 base::span<const MockWrite>());
21586 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
21587 base::span<const MockRead>(),
21588 base::span<const MockWrite>());
21589
21590 NetworkIsolationKey network_isolation_key_for_request;
21591
21592 switch (test_case) {
21593 case TestCase::kUseFirstPreconnect:
21594 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21595 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21596 network_isolation_key_for_request = preconnect1_isolation_key;
21597 break;
21598 case TestCase::kUseSecondPreconnect:
21599 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21600 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21601 network_isolation_key_for_request = preconnect2_isolation_key;
21602 break;
21603 case TestCase::kDontUsePreconnect:
21604 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21605 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21606 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21607 network_isolation_key_for_request = not_preconnected_isolation_key;
21608 break;
21609 }
21610
21611 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
21612
21613 // Preconnect sockets.
21614 HttpRequestInfo request;
21615 request.method = "GET";
21616 request.url = GURL("http://www.foo.com/");
21617 request.traffic_annotation =
21618 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21619
21620 request.network_isolation_key = preconnect1_isolation_key;
21621 session->http_stream_factory()->PreconnectStreams(1, request);
21622
21623 request.network_isolation_key = preconnect2_isolation_key;
21624 session->http_stream_factory()->PreconnectStreams(1, request);
21625
21626 request.network_isolation_key = network_isolation_key_for_request;
21627
21628 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21629
21630 // Make the request.
21631 TestCompletionCallback callback;
21632
21633 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21634
21635 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
21636 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21637
21638 rv = callback.WaitForResult();
21639 EXPECT_THAT(rv, IsOk());
21640
21641 const HttpResponseInfo* response = trans.GetResponseInfo();
21642 ASSERT_TRUE(response);
21643 ASSERT_TRUE(response->headers);
21644 EXPECT_EQ(200, response->headers->response_code());
21645
21646 std::string response_data;
21647 rv = ReadTransaction(&trans, &response_data);
21648 EXPECT_THAT(rv, IsOk());
21649 EXPECT_EQ("hello", response_data);
21650
21651 if (test_case != TestCase::kDontUsePreconnect) {
21652 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21653 } else {
21654 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
21655 }
21656 }
21657}
21658
David Benjamin6f2da652019-06-26 23:36:3521659// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21660// cache is isolated.
21661TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
21662 base::test::ScopedFeatureList feature_list;
21663 feature_list.InitWithFeatures(
21664 {features::kPartitionConnectionsByNetworkIsolationKey,
21665 features::kPartitionSSLSessionsByNetworkIsolationKey},
21666 {});
21667
Shivani Sharma8ae506c2019-07-21 21:08:2721668 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21669 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21670 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
21671 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3521672 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21673
21674 // The server always sends Connection: close, so each request goes over a
21675 // distinct socket.
21676
21677 const MockWrite kWrites1[] = {
21678 MockWrite("GET /1 HTTP/1.1\r\n"
21679 "Host: foo.test\r\n"
21680 "Connection: keep-alive\r\n\r\n")};
21681
21682 const MockRead kReads1[] = {
21683 MockRead("HTTP/1.1 200 OK\r\n"
21684 "Connection: close\r\n"
21685 "Content-Length: 1\r\n\r\n"
21686 "1")};
21687
21688 const MockWrite kWrites2[] = {
21689 MockWrite("GET /2 HTTP/1.1\r\n"
21690 "Host: foo.test\r\n"
21691 "Connection: keep-alive\r\n\r\n")};
21692
21693 const MockRead kReads2[] = {
21694 MockRead("HTTP/1.1 200 OK\r\n"
21695 "Connection: close\r\n"
21696 "Content-Length: 1\r\n\r\n"
21697 "2")};
21698
21699 const MockWrite kWrites3[] = {
21700 MockWrite("GET /3 HTTP/1.1\r\n"
21701 "Host: foo.test\r\n"
21702 "Connection: keep-alive\r\n\r\n")};
21703
21704 const MockRead kReads3[] = {
21705 MockRead("HTTP/1.1 200 OK\r\n"
21706 "Connection: close\r\n"
21707 "Content-Length: 1\r\n\r\n"
21708 "3")};
21709
21710 StaticSocketDataProvider data1(kReads1, kWrites1);
21711 StaticSocketDataProvider data2(kReads2, kWrites2);
21712 StaticSocketDataProvider data3(kReads3, kWrites3);
21713 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21714 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21715 session_deps_.socket_factory->AddSocketDataProvider(&data3);
21716
21717 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21718 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
21719 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
21720 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21721 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
21722 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
21723 SSLSocketDataProvider ssl_data3(ASYNC, OK);
21724 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
21725 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
21726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21728 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
21729
21730 TestCompletionCallback callback;
21731 HttpRequestInfo request1;
21732 request1.method = "GET";
21733 request1.url = GURL("https://foo.test/1");
21734 request1.traffic_annotation =
21735 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21736 request1.network_isolation_key = kNetworkIsolationKey1;
21737 auto trans1 =
21738 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21739 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21740 EXPECT_THAT(callback.GetResult(rv), IsOk());
21741 std::string response_data1;
21742 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21743 EXPECT_EQ("1", response_data1);
21744 trans1.reset();
21745
21746 HttpRequestInfo request2;
21747 request2.method = "GET";
21748 request2.url = GURL("https://foo.test/2");
21749 request2.traffic_annotation =
21750 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21751 request2.network_isolation_key = kNetworkIsolationKey2;
21752 auto trans2 =
21753 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21754 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21755 EXPECT_THAT(callback.GetResult(rv), IsOk());
21756 std::string response_data2;
21757 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21758 EXPECT_EQ("2", response_data2);
21759 trans2.reset();
21760
21761 HttpRequestInfo request3;
21762 request3.method = "GET";
21763 request3.url = GURL("https://foo.test/3");
21764 request3.traffic_annotation =
21765 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21766 request3.network_isolation_key = kNetworkIsolationKey1;
21767 auto trans3 =
21768 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21769 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21770 EXPECT_THAT(callback.GetResult(rv), IsOk());
21771 std::string response_data3;
21772 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21773 EXPECT_EQ("3", response_data3);
21774 trans3.reset();
21775}
21776
21777// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21778// cache is isolated, for both origins and proxies.
21779TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
21780 base::test::ScopedFeatureList feature_list;
21781 feature_list.InitWithFeatures(
21782 {features::kPartitionConnectionsByNetworkIsolationKey,
21783 features::kPartitionSSLSessionsByNetworkIsolationKey},
21784 {});
21785
21786 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21787 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21788
Shivani Sharma8ae506c2019-07-21 21:08:2721789 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21790 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21791 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
21792 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3521793 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21794
21795 // Make both a tunneled and non-tunneled request.
21796 HttpRequestInfo request1;
21797 request1.method = "GET";
21798 request1.url = GURL("https://foo.test/1");
21799 request1.traffic_annotation =
21800 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21801 request1.network_isolation_key = kNetworkIsolationKey1;
21802
21803 HttpRequestInfo request2;
21804 request2.method = "GET";
21805 request2.url = GURL("http://foo.test/2");
21806 request2.traffic_annotation =
21807 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21808 request2.network_isolation_key = kNetworkIsolationKey2;
21809
21810 const MockWrite kWrites1[] = {
21811 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
21812 "Host: foo.test:443\r\n"
21813 "Proxy-Connection: keep-alive\r\n\r\n"),
21814 MockWrite("GET /1 HTTP/1.1\r\n"
21815 "Host: foo.test\r\n"
21816 "Connection: keep-alive\r\n\r\n")};
21817
21818 const MockRead kReads1[] = {
21819 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
21820 MockRead("HTTP/1.1 200 OK\r\n"
21821 "Connection: close\r\n"
21822 "Content-Length: 1\r\n\r\n"
21823 "1")};
21824
21825 const MockWrite kWrites2[] = {
21826 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
21827 "Host: foo.test\r\n"
21828 "Proxy-Connection: keep-alive\r\n\r\n")};
21829
21830 const MockRead kReads2[] = {
21831 MockRead("HTTP/1.1 200 OK\r\n"
21832 "Connection: close\r\n"
21833 "Content-Length: 1\r\n\r\n"
21834 "2")};
21835
21836 StaticSocketDataProvider data1(kReads1, kWrites1);
21837 StaticSocketDataProvider data2(kReads2, kWrites2);
21838 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21839 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21840 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21841
21842 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21843 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
21844 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
21845 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
21846 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
21847 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
21848 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21849 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
21850 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
21851 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21852 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21853 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21854
21855 TestCompletionCallback callback;
21856 auto trans1 =
21857 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21858 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21859 EXPECT_THAT(callback.GetResult(rv), IsOk());
21860 std::string response_data1;
21861 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21862 EXPECT_EQ("1", response_data1);
21863 trans1.reset();
21864
21865 auto trans2 =
21866 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21867 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21868 EXPECT_THAT(callback.GetResult(rv), IsOk());
21869 std::string response_data2;
21870 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21871 EXPECT_EQ("2", response_data2);
21872 trans2.reset();
21873}
21874
David Benjaminef2f2a5a2019-07-16 19:21:3121875// Test that SSLConfig changes from SSLConfigService are picked up even when
21876// there are live sockets.
21877TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5221878 SSLContextConfig ssl_context_config;
21879 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21880 auto ssl_config_service =
21881 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121882 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21883
21884 session_deps_.ssl_config_service = std::move(ssl_config_service);
21885
21886 // Make three requests. Between the second and third, the SSL config will
21887 // change.
21888 HttpRequestInfo request1;
21889 request1.method = "GET";
21890 request1.url = GURL("https://foo.test/1");
21891 request1.traffic_annotation =
21892 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21893
21894 HttpRequestInfo request2;
21895 request2.method = "GET";
21896 request2.url = GURL("https://foo.test/2");
21897 request2.traffic_annotation =
21898 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21899
21900 HttpRequestInfo request3;
21901 request3.method = "GET";
21902 request3.url = GURL("https://foo.test/3");
21903 request3.traffic_annotation =
21904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21905
21906 const MockWrite kWrites1[] = {
21907 MockWrite("GET /1 HTTP/1.1\r\n"
21908 "Host: foo.test\r\n"
21909 "Connection: keep-alive\r\n\r\n"),
21910 MockWrite("GET /2 HTTP/1.1\r\n"
21911 "Host: foo.test\r\n"
21912 "Connection: keep-alive\r\n\r\n"),
21913 };
21914
21915 const MockRead kReads1[] = {
21916 MockRead("HTTP/1.1 200 OK\r\n"
21917 "Connection: keep-alive\r\n"
21918 "Content-Length: 1\r\n\r\n"
21919 "1"),
21920 MockRead("HTTP/1.1 200 OK\r\n"
21921 "Connection: keep-alive\r\n"
21922 "Content-Length: 1\r\n\r\n"
21923 "2"),
21924 };
21925
21926 // The third request goes on a different socket because the SSL config has
21927 // changed.
21928 const MockWrite kWrites2[] = {
21929 MockWrite("GET /3 HTTP/1.1\r\n"
21930 "Host: foo.test\r\n"
21931 "Connection: keep-alive\r\n\r\n")};
21932
21933 const MockRead kReads2[] = {
21934 MockRead("HTTP/1.1 200 OK\r\n"
21935 "Connection: keep-alive\r\n"
21936 "Content-Length: 1\r\n\r\n"
21937 "3")};
21938
21939 StaticSocketDataProvider data1(kReads1, kWrites1);
21940 StaticSocketDataProvider data2(kReads2, kWrites2);
21941 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21942 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21943
21944 SSLSocketDataProvider ssl1(ASYNC, OK);
21945 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21946 SSLSocketDataProvider ssl2(ASYNC, OK);
21947 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21948 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21949 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21950
21951 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21952
21953 TestCompletionCallback callback;
21954 auto trans1 =
21955 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21956 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21957 EXPECT_THAT(callback.GetResult(rv), IsOk());
21958 std::string response_data1;
21959 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21960 EXPECT_EQ("1", response_data1);
21961 trans1.reset();
21962
21963 auto trans2 =
21964 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21965 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21966 EXPECT_THAT(callback.GetResult(rv), IsOk());
21967 std::string response_data2;
21968 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21969 EXPECT_EQ("2", response_data2);
21970 trans2.reset();
21971
David Benjamin151ec6b2019-08-02 19:38:5221972 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21973 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121974
21975 auto trans3 =
21976 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21977 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21978 EXPECT_THAT(callback.GetResult(rv), IsOk());
21979 std::string response_data3;
21980 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21981 EXPECT_EQ("3", response_data3);
21982 trans3.reset();
21983}
21984
21985TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5221986 SSLContextConfig ssl_context_config;
21987 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21988 auto ssl_config_service =
21989 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121990 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21991
21992 session_deps_.ssl_config_service = std::move(ssl_config_service);
21993
21994 HttpRequestInfo request;
21995 request.method = "GET";
21996 request.url = GURL("https://foo.test/1");
21997 request.traffic_annotation =
21998 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21999
22000 // Make a socket which never connects.
22001 StaticSocketDataProvider data({}, {});
22002 session_deps_.socket_factory->AddSocketDataProvider(&data);
22003 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
22004 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22005 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
22006
22007 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22008
22009 TestCompletionCallback callback;
22010 auto trans =
22011 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22012 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
22013 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22014
David Benjamin151ec6b2019-08-02 19:38:5222015 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22016 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122017
22018 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
22019}
22020
David Benjaminbac8dff2019-08-07 01:30:4122021// Test that HttpNetworkTransaction correctly handles existing sockets when the
22022// server requests a client certificate post-handshake (via a TLS
22023// renegotiation). This is a regression test for https://crbug.com/829184.
22024TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
22025 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
22026 TRAFFIC_ANNOTATION_FOR_TESTS);
22027
22028 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
22029 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
22030
22031 std::unique_ptr<FakeClientCertIdentity> identity =
22032 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22033 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
22034 ASSERT_TRUE(identity);
22035
22036 // This test will make several requests so that, when the client certificate
22037 // request comes in, we have a socket in use, an idle socket, and a socket for
22038 // an unrelated host.
22039 //
22040 // First, two long-lived requests which do not complete until after the client
22041 // certificate request. This arranges for sockets to be in use during the
22042 // request. They should not be interrupted.
22043 HttpRequestInfo request_long_lived;
22044 request_long_lived.method = "GET";
22045 request_long_lived.url = GURL("https://foo.test/long-lived");
22046 request_long_lived.traffic_annotation = kTrafficAnnotation;
22047
22048 HttpRequestInfo request_long_lived_bar;
22049 request_long_lived_bar.method = "GET";
22050 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
22051 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
22052
22053 // Next, make a request that needs client certificates.
22054 HttpRequestInfo request_auth;
22055 request_auth.method = "GET";
22056 request_auth.url = GURL("https://foo.test/auth");
22057 request_auth.traffic_annotation = kTrafficAnnotation;
22058
22059 // Before responding to the challenge, make a request to an unauthenticated
22060 // endpoint. This will result in an idle socket when the client certificate
22061 // challenge is resolved.
22062 HttpRequestInfo request_unauth;
22063 request_unauth.method = "GET";
22064 request_unauth.url = GURL("https://foo.test/unauth");
22065 request_unauth.traffic_annotation = kTrafficAnnotation;
22066
22067 // After all the preceding requests complete, end with two additional requests
22068 // to ensure pre-authentication foo.test sockets are not used and bar.test
22069 // sockets are unaffected.
22070 HttpRequestInfo request_post_auth;
22071 request_post_auth.method = "GET";
22072 request_post_auth.url = GURL("https://foo.test/post-auth");
22073 request_post_auth.traffic_annotation = kTrafficAnnotation;
22074
22075 HttpRequestInfo request_post_auth_bar;
22076 request_post_auth_bar.method = "GET";
22077 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
22078 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
22079
22080 // The sockets for /long-lived and /unauth complete their request but are
22081 // not allocated for /post-auth or /retry because SSL state has since changed.
22082 const MockWrite kLongLivedWrites[] = {
22083 MockWrite(ASYNC, 0,
22084 "GET /long-lived HTTP/1.1\r\n"
22085 "Host: foo.test\r\n"
22086 "Connection: keep-alive\r\n\r\n"),
22087 };
22088 const MockRead kLongLivedReads[] = {
22089 // Pause so /long-lived completes after the client presents client
22090 // certificates.
22091 MockRead(ASYNC, ERR_IO_PENDING, 1),
22092 MockRead(ASYNC, 2,
22093 "HTTP/1.1 200 OK\r\n"
22094 "Connection: keep-alive\r\n"
22095 "Content-Length: 10\r\n\r\n"
22096 "long-lived"),
22097 };
22098 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
22099 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
22100 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
22101 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
22102
22103 // Requests for bar.test should be unaffected by foo.test and get allocated
22104 // a single socket.
22105 const MockWrite kBarWrites[] = {
22106 MockWrite(ASYNC, 0,
22107 "GET /long-lived HTTP/1.1\r\n"
22108 "Host: bar.test\r\n"
22109 "Connection: keep-alive\r\n\r\n"),
22110 MockWrite(ASYNC, 3,
22111 "GET /post-auth HTTP/1.1\r\n"
22112 "Host: bar.test\r\n"
22113 "Connection: keep-alive\r\n\r\n"),
22114 };
22115 const MockRead kBarReads[] = {
22116 // Pause on /long-lived so it completes after foo.test's authentication.
22117 MockRead(ASYNC, ERR_IO_PENDING, 1),
22118 MockRead(ASYNC, 2,
22119 "HTTP/1.1 200 OK\r\n"
22120 "Connection: keep-alive\r\n"
22121 "Content-Length: 10\r\n\r\n"
22122 "long-lived"),
22123 MockRead(ASYNC, 4,
22124 "HTTP/1.1 200 OK\r\n"
22125 "Connection: keep-alive\r\n"
22126 "Content-Length: 9\r\n\r\n"
22127 "post-auth"),
22128 };
22129 SequencedSocketData data_bar(kBarReads, kBarWrites);
22130 SSLSocketDataProvider ssl_bar(ASYNC, OK);
22131 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
22132 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
22133
22134 // Requesting /auth results in a post-handshake client certificate challenge.
22135 const MockWrite kAuthWrites[] = {
22136 MockWrite(ASYNC, 0,
22137 "GET /auth HTTP/1.1\r\n"
22138 "Host: foo.test\r\n"
22139 "Connection: keep-alive\r\n\r\n"),
22140 };
22141 const MockRead kAuthReads[] = {
22142 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
22143 };
22144 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
22145 SSLSocketDataProvider ssl_auth(ASYNC, OK);
22146 ssl_auth.cert_request_info = cert_request_info.get();
22147 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
22148 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
22149
22150 // Requesting /unauth completes.
22151 const MockWrite kUnauthWrites[] = {
22152 MockWrite(ASYNC, 0,
22153 "GET /unauth HTTP/1.1\r\n"
22154 "Host: foo.test\r\n"
22155 "Connection: keep-alive\r\n\r\n"),
22156 };
22157 const MockRead kUnauthReads[] = {
22158 MockRead(ASYNC, 1,
22159 "HTTP/1.1 200 OK\r\n"
22160 "Connection: keep-alive\r\n"
22161 "Content-Length: 6\r\n\r\n"
22162 "unauth"),
22163 };
22164 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
22165 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
22166 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
22167 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
22168
22169 // When the client certificate is selected, /auth is retried on a new
22170 // connection. In particular, it should not be retried on |data_unauth|,
22171 // which would not honor the new client certificate configuration.
22172 const MockWrite kRetryWrites[] = {
22173 MockWrite(ASYNC, 0,
22174 "GET /auth HTTP/1.1\r\n"
22175 "Host: foo.test\r\n"
22176 "Connection: keep-alive\r\n\r\n"),
22177 };
22178 const MockRead kRetryReads[] = {
22179 MockRead(ASYNC, 1,
22180 "HTTP/1.1 200 OK\r\n"
22181 // Close the connection so we test that /post-auth is not
22182 // allocated to |data_unauth| or |data_long_lived|.
22183 "Connection: close\r\n"
22184 "Content-Length: 4\r\n\r\n"
22185 "auth"),
22186 };
22187 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
22188 SSLSocketDataProvider ssl_retry(ASYNC, OK);
22189 ssl_retry.expected_send_client_cert = true;
22190 ssl_retry.expected_client_cert = identity->certificate();
22191 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
22192 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
22193
22194 // /post-auth gets its own socket.
22195 const MockWrite kPostAuthWrites[] = {
22196 MockWrite(ASYNC, 0,
22197 "GET /post-auth HTTP/1.1\r\n"
22198 "Host: foo.test\r\n"
22199 "Connection: keep-alive\r\n\r\n"),
22200 };
22201 const MockRead kPostAuthReads[] = {
22202 MockRead(ASYNC, 1,
22203 "HTTP/1.1 200 OK\r\n"
22204 "Connection: keep-alive\r\n"
22205 "Content-Length: 9\r\n\r\n"
22206 "post-auth"),
22207 };
22208 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
22209 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
22210 ssl_post_auth.expected_send_client_cert = true;
22211 ssl_post_auth.expected_client_cert = identity->certificate();
22212 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
22213 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
22214
22215 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22216
22217 // Start the two long-lived requests.
22218 TestCompletionCallback callback_long_lived;
22219 auto trans_long_lived =
22220 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22221 int rv = trans_long_lived->Start(
22222 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
22223 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22224 data_long_lived.RunUntilPaused();
22225
22226 TestCompletionCallback callback_long_lived_bar;
22227 auto trans_long_lived_bar =
22228 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22229 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
22230 callback_long_lived_bar.callback(),
22231 NetLogWithSource());
22232 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22233 data_bar.RunUntilPaused();
22234
22235 // Request /auth. This gives a client certificate challenge.
22236 TestCompletionCallback callback_auth;
22237 auto trans_auth =
22238 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22239 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
22240 NetLogWithSource());
22241 EXPECT_THAT(callback_auth.GetResult(rv),
22242 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22243
22244 // Make an unauthenticated request. This completes.
22245 TestCompletionCallback callback_unauth;
22246 auto trans_unauth =
22247 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22248 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
22249 NetLogWithSource());
22250 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
22251 std::string response_unauth;
22252 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
22253 EXPECT_EQ("unauth", response_unauth);
22254 trans_unauth.reset();
22255
22256 // Complete the authenticated request.
22257 rv = trans_auth->RestartWithCertificate(identity->certificate(),
22258 identity->ssl_private_key(),
22259 callback_auth.callback());
22260 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
22261 std::string response_auth;
22262 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
22263 EXPECT_EQ("auth", response_auth);
22264 trans_auth.reset();
22265
22266 // Complete the long-lived requests.
22267 data_long_lived.Resume();
22268 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
22269 std::string response_long_lived;
22270 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
22271 IsOk());
22272 EXPECT_EQ("long-lived", response_long_lived);
22273 trans_long_lived.reset();
22274
22275 data_bar.Resume();
22276 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
22277 std::string response_long_lived_bar;
22278 EXPECT_THAT(
22279 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
22280 IsOk());
22281 EXPECT_EQ("long-lived", response_long_lived_bar);
22282 trans_long_lived_bar.reset();
22283
22284 // Run the post-authentication requests.
22285 TestCompletionCallback callback_post_auth;
22286 auto trans_post_auth =
22287 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22288 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
22289 NetLogWithSource());
22290 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
22291 std::string response_post_auth;
22292 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
22293 IsOk());
22294 EXPECT_EQ("post-auth", response_post_auth);
22295 trans_post_auth.reset();
22296
22297 TestCompletionCallback callback_post_auth_bar;
22298 auto trans_post_auth_bar =
22299 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22300 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
22301 callback_post_auth_bar.callback(),
22302 NetLogWithSource());
22303 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
22304 std::string response_post_auth_bar;
22305 EXPECT_THAT(
22306 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
22307 IsOk());
22308 EXPECT_EQ("post-auth", response_post_auth_bar);
22309 trans_post_auth_bar.reset();
22310}
22311
[email protected]89ceba9a2009-03-21 03:46:0622312} // namespace net