blob: 8e96e2b36839c7c59d417933da16ea88b6a356d9 [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
David Benjaminbae08ba2019-10-18 21:06:15547 base::RepeatingClosure FastForwardByCallback(base::TimeDelta delta) {
548 return base::BindRepeating(&HttpNetworkTransactionTest::FastForwardBy,
549 base::Unretained(this), delta);
550 }
551
Matt Menked6fd2a52019-03-20 06:14:36552 const CommonConnectJobParams dummy_connect_job_params_;
553
Douglas Creager134b52e2018-11-09 18:00:14554 // These clocks are defined here, even though they're only used in the
555 // Reporting tests below, since they need to be destroyed after
556 // |session_deps_|.
557 base::SimpleTestClock clock_;
558 base::SimpleTestTickClock tick_clock_;
559
[email protected]4bd46222013-05-14 19:32:23560 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07561 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15562 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03563
564 // Original socket limits. Some tests set these. Safest to always restore
565 // them once each test has been run.
566 int old_max_group_sockets_;
567 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15568};
[email protected]231d5a32008-09-13 00:45:27569
[email protected]448d4ca52012-03-04 04:12:23570namespace {
571
ryansturm49a8cb12016-06-15 16:51:09572class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27573 public:
ryansturm49a8cb12016-06-15 16:51:09574 BeforeHeadersSentHandler()
575 : observed_before_headers_sent_with_proxy_(false),
576 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27577
ryansturm49a8cb12016-06-15 16:51:09578 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
579 HttpRequestHeaders* request_headers) {
580 observed_before_headers_sent_ = true;
581 if (!proxy_info.is_http() && !proxy_info.is_https() &&
582 !proxy_info.is_quic()) {
583 return;
584 }
585 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27586 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
587 }
588
ryansturm49a8cb12016-06-15 16:51:09589 bool observed_before_headers_sent_with_proxy() const {
590 return observed_before_headers_sent_with_proxy_;
591 }
592
593 bool observed_before_headers_sent() const {
594 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27595 }
596
597 std::string observed_proxy_server_uri() const {
598 return observed_proxy_server_uri_;
599 }
600
601 private:
ryansturm49a8cb12016-06-15 16:51:09602 bool observed_before_headers_sent_with_proxy_;
603 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27604 std::string observed_proxy_server_uri_;
605
ryansturm49a8cb12016-06-15 16:51:09606 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27607};
608
[email protected]15a5ccf82008-10-23 19:57:43609// Fill |str| with a long header list that consumes >= |size| bytes.
610void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51611 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19612 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
613 const int sizeof_row = strlen(row);
614 const int num_rows = static_cast<int>(
615 ceil(static_cast<float>(size) / sizeof_row));
616 const int sizeof_data = num_rows * sizeof_row;
617 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43618 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51619
[email protected]4ddaf2502008-10-23 18:26:19620 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43621 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19622}
623
thakis84dff942015-07-28 20:47:38624#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09625uint64_t MockGetMSTime() {
626 // Tue, 23 May 2017 20:13:07 +0000
627 return 131400439870000000;
628}
629
[email protected]385a4672009-03-11 22:21:29630// Alternative functions that eliminate randomness and dependency on the local
631// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37632void MockGenerateRandom(uint8_t* output, size_t n) {
633 // This is set to 0xaa because the client challenge for testing in
634 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
635 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29636}
637
[email protected]fe2bc6a2009-03-23 16:52:20638std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37639 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29640}
thakis84dff942015-07-28 20:47:38641#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29642
Matt Menked6fd2a52019-03-20 06:14:36643class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31644 public:
Matt Menked6fd2a52019-03-20 06:14:36645 explicit CaptureGroupIdTransportSocketPool(
646 const CommonConnectJobParams* common_connect_job_params)
647 : TransportClientSocketPool(0,
648 0,
649 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36650 ProxyServer::Direct(),
651 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52652 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18653
Matt Menkef6edce752019-03-19 17:21:56654 const ClientSocketPool::GroupId& last_group_id_received() const {
655 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49656 }
657
Tarun Bansal162eabe52018-01-20 01:16:39658 bool socket_requested() const { return socket_requested_; }
659
Matt Menke28ac03e2019-02-25 22:25:50660 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56661 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03662 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28663 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50664 RequestPriority priority,
665 const SocketTag& socket_tag,
666 ClientSocketPool::RespectLimits respect_limits,
667 ClientSocketHandle* handle,
668 CompletionOnceCallback callback,
669 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
670 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56671 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39672 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31673 return ERR_IO_PENDING;
674 }
Matt Menkef6edce752019-03-19 17:21:56675 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21676 ClientSocketHandle* handle,
677 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56678 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09679 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24680 int64_t generation) override {}
dmichaeld6e570d2014-12-18 22:30:57681 void CloseIdleSockets() override {}
Matt Menkef6edce752019-03-19 17:21:56682 void CloseIdleSocketsInGroup(
683 const ClientSocketPool::GroupId& group_id) override {}
dmichaeld6e570d2014-12-18 22:30:57684 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56685 size_t IdleSocketCountInGroup(
686 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31687 return 0;
688 }
Matt Menkef6edce752019-03-19 17:21:56689 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57690 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31691 return LOAD_STATE_IDLE;
692 }
[email protected]d80a4322009-08-14 07:07:49693
694 private:
Matt Menkef6edce752019-03-19 17:21:56695 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39696 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31697};
698
[email protected]231d5a32008-09-13 00:45:27699//-----------------------------------------------------------------------------
700
[email protected]79cb5c12011-09-12 13:12:04701// Helper functions for validating that AuthChallengeInfo's are correctly
702// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58703bool CheckBasicServerAuth(
704 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04705 if (!auth_challenge)
706 return false;
707 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43708 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04709 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19710 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04711 return true;
712}
713
David Benjamin2eb827f2019-04-29 18:31:04714bool CheckBasicSecureServerAuth(
715 const base::Optional<AuthChallengeInfo>& auth_challenge) {
716 if (!auth_challenge)
717 return false;
718 EXPECT_FALSE(auth_challenge->is_proxy);
719 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
720 EXPECT_EQ("MyRealm1", auth_challenge->realm);
721 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
722 return true;
723}
724
Emily Starkf2c9bbd2019-04-09 17:08:58725bool CheckBasicProxyAuth(
726 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04727 if (!auth_challenge)
728 return false;
729 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43730 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
731 EXPECT_EQ("MyRealm1", auth_challenge->realm);
732 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
733 return true;
734}
735
Emily Starkf2c9bbd2019-04-09 17:08:58736bool CheckBasicSecureProxyAuth(
737 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43738 if (!auth_challenge)
739 return false;
740 EXPECT_TRUE(auth_challenge->is_proxy);
741 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04742 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19743 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04744 return true;
745}
746
Emily Starkf2c9bbd2019-04-09 17:08:58747bool CheckDigestServerAuth(
748 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04749 if (!auth_challenge)
750 return false;
751 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43752 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04753 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19754 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04755 return true;
756}
757
thakis84dff942015-07-28 20:47:38758#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58759bool CheckNTLMServerAuth(
760 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04761 if (!auth_challenge)
762 return false;
763 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55764 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04765 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19766 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04767 return true;
768}
David Benjamin5cb91132018-04-06 05:54:49769
Emily Starkf2c9bbd2019-04-09 17:08:58770bool CheckNTLMProxyAuth(
771 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49772 if (!auth_challenge)
773 return false;
774 EXPECT_TRUE(auth_challenge->is_proxy);
775 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
776 EXPECT_EQ(std::string(), auth_challenge->realm);
777 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
778 return true;
779}
thakis84dff942015-07-28 20:47:38780#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04781
[email protected]448d4ca52012-03-04 04:12:23782} // namespace
783
Shivani Sharma8ae506c2019-07-21 21:08:27784// TODO(950069): Add testing for frame_origin in NetworkIsolationKey
785// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
786
bncd16676a2016-07-20 16:23:01787TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09788 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16789 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27790}
791
bncd16676a2016-07-20 16:23:01792TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27793 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35794 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
795 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06796 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27797 };
Ryan Sleevib8d7ea02018-05-07 20:01:01798 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01799 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27800 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
801 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01802 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22803 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47804 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59805
806 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27807}
808
809// Response with no status line.
bncd16676a2016-07-20 16:23:01810TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27811 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35812 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06813 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27814 };
Ryan Sleevib8d7ea02018-05-07 20:01:01815 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41816 EXPECT_THAT(out.rv, IsOk());
817 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
818 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01819 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41820 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27821}
822
mmenkea7da6da2016-09-01 21:56:52823// Response with no status line, and a weird port. Should fail by default.
824TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
825 MockRead data_reads[] = {
826 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
827 };
828
Ryan Sleevib8d7ea02018-05-07 20:01:01829 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52830 session_deps_.socket_factory->AddSocketDataProvider(&data);
831
832 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
833
krasinc06a72a2016-12-21 03:42:46834 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58835 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19836 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52837
mmenkea7da6da2016-09-01 21:56:52838 request.method = "GET";
839 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10840 request.traffic_annotation =
841 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
842
mmenkea7da6da2016-09-01 21:56:52843 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20844 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52845 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
846}
847
Shivani Sharmafdcaefd2017-11-02 00:12:26848// Tests that request info can be destroyed after the headers phase is complete.
849TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
850 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
851 auto trans =
852 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
853
854 MockRead data_reads[] = {
855 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
856 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
857 };
Ryan Sleevib8d7ea02018-05-07 20:01:01858 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26859 session_deps_.socket_factory->AddSocketDataProvider(&data);
860
861 TestCompletionCallback callback;
862
863 {
864 auto request = std::make_unique<HttpRequestInfo>();
865 request->method = "GET";
866 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10867 request->traffic_annotation =
868 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26869
870 int rv =
871 trans->Start(request.get(), callback.callback(), NetLogWithSource());
872
873 EXPECT_THAT(callback.GetResult(rv), IsOk());
874 } // Let request info be destroyed.
875
876 trans.reset();
877}
878
[email protected]231d5a32008-09-13 00:45:27879// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01880TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27881 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35882 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06883 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27884 };
Ryan Sleevib8d7ea02018-05-07 20:01:01885 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01886 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27887 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
888 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01889 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22890 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27891}
892
893// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01894TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27895 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35896 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06897 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27898 };
Ryan Sleevib8d7ea02018-05-07 20:01:01899 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01900 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27901 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
902 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01903 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22904 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27905}
906
907// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01908TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27909 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35910 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06911 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27912 };
Ryan Sleevib8d7ea02018-05-07 20:01:01913 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41914 EXPECT_THAT(out.rv, IsOk());
915 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
916 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01917 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41918 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27919}
920
921// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01922TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27923 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35924 MockRead("\n"),
925 MockRead("\n"),
926 MockRead("Q"),
927 MockRead("J"),
928 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06929 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27930 };
Ryan Sleevib8d7ea02018-05-07 20:01:01931 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01932 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27933 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
934 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01935 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22936 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27937}
938
939// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01940TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27941 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35942 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06943 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27944 };
Ryan Sleevib8d7ea02018-05-07 20:01:01945 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41946 EXPECT_THAT(out.rv, IsOk());
947 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
948 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01949 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41950 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52951}
952
[email protected]f9d44aa2008-09-23 23:57:17953// Simulate a 204 response, lacking a Content-Length header, sent over a
954// persistent connection. The response should still terminate since a 204
955// cannot have a response body.
bncd16676a2016-07-20 16:23:01956TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19957 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17958 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35959 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19960 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06961 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17962 };
Ryan Sleevib8d7ea02018-05-07 20:01:01963 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01964 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:17965 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
966 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01967 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22968 int64_t response_size = reads_size - strlen(junk);
969 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17970}
971
[email protected]0877e3d2009-10-17 22:29:57972// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:01973TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19974 std::string final_chunk = "0\r\n\r\n";
975 std::string extra_data = "HTTP/1.1 200 OK\r\n";
976 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57977 MockRead data_reads[] = {
978 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
979 MockRead("5\r\nHello\r\n"),
980 MockRead("1\r\n"),
981 MockRead(" \r\n"),
982 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19983 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06984 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57985 };
Ryan Sleevib8d7ea02018-05-07 20:01:01986 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01987 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:57988 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
989 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01990 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22991 int64_t response_size = reads_size - extra_data.size();
992 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57993}
994
[email protected]9fe44f52010-09-23 18:36:00995// Next tests deal with http://crbug.com/56344.
996
bncd16676a2016-07-20 16:23:01997TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00998 MultipleContentLengthHeadersNoTransferEncoding) {
999 MockRead data_reads[] = {
1000 MockRead("HTTP/1.1 200 OK\r\n"),
1001 MockRead("Content-Length: 10\r\n"),
1002 MockRead("Content-Length: 5\r\n\r\n"),
1003 };
Ryan Sleevib8d7ea02018-05-07 20:01:011004 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011005 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001006}
1007
bncd16676a2016-07-20 16:23:011008TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041009 DuplicateContentLengthHeadersNoTransferEncoding) {
1010 MockRead data_reads[] = {
1011 MockRead("HTTP/1.1 200 OK\r\n"),
1012 MockRead("Content-Length: 5\r\n"),
1013 MockRead("Content-Length: 5\r\n\r\n"),
1014 MockRead("Hello"),
1015 };
Ryan Sleevib8d7ea02018-05-07 20:01:011016 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011017 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041018 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1019 EXPECT_EQ("Hello", out.response_data);
1020}
1021
bncd16676a2016-07-20 16:23:011022TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041023 ComplexContentLengthHeadersNoTransferEncoding) {
1024 // More than 2 dupes.
1025 {
1026 MockRead data_reads[] = {
1027 MockRead("HTTP/1.1 200 OK\r\n"),
1028 MockRead("Content-Length: 5\r\n"),
1029 MockRead("Content-Length: 5\r\n"),
1030 MockRead("Content-Length: 5\r\n\r\n"),
1031 MockRead("Hello"),
1032 };
Ryan Sleevib8d7ea02018-05-07 20:01:011033 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011034 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041035 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1036 EXPECT_EQ("Hello", out.response_data);
1037 }
1038 // HTTP/1.0
1039 {
1040 MockRead data_reads[] = {
1041 MockRead("HTTP/1.0 200 OK\r\n"),
1042 MockRead("Content-Length: 5\r\n"),
1043 MockRead("Content-Length: 5\r\n"),
1044 MockRead("Content-Length: 5\r\n\r\n"),
1045 MockRead("Hello"),
1046 };
Ryan Sleevib8d7ea02018-05-07 20:01:011047 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011048 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041049 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1050 EXPECT_EQ("Hello", out.response_data);
1051 }
1052 // 2 dupes and one mismatched.
1053 {
1054 MockRead data_reads[] = {
1055 MockRead("HTTP/1.1 200 OK\r\n"),
1056 MockRead("Content-Length: 10\r\n"),
1057 MockRead("Content-Length: 10\r\n"),
1058 MockRead("Content-Length: 5\r\n\r\n"),
1059 };
Ryan Sleevib8d7ea02018-05-07 20:01:011060 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011061 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041062 }
1063}
1064
bncd16676a2016-07-20 16:23:011065TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001066 MultipleContentLengthHeadersTransferEncoding) {
1067 MockRead data_reads[] = {
1068 MockRead("HTTP/1.1 200 OK\r\n"),
1069 MockRead("Content-Length: 666\r\n"),
1070 MockRead("Content-Length: 1337\r\n"),
1071 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1072 MockRead("5\r\nHello\r\n"),
1073 MockRead("1\r\n"),
1074 MockRead(" \r\n"),
1075 MockRead("5\r\nworld\r\n"),
1076 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061077 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001078 };
Ryan Sleevib8d7ea02018-05-07 20:01:011079 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011080 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001081 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1082 EXPECT_EQ("Hello world", out.response_data);
1083}
1084
[email protected]1628fe92011-10-04 23:04:551085// Next tests deal with http://crbug.com/98895.
1086
1087// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011088TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551089 MockRead data_reads[] = {
1090 MockRead("HTTP/1.1 200 OK\r\n"),
1091 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1092 MockRead("Content-Length: 5\r\n\r\n"),
1093 MockRead("Hello"),
1094 };
Ryan Sleevib8d7ea02018-05-07 20:01:011095 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011096 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551097 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1098 EXPECT_EQ("Hello", out.response_data);
1099}
1100
[email protected]54a9c6e52012-03-21 20:10:591101// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011102TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551103 MockRead data_reads[] = {
1104 MockRead("HTTP/1.1 200 OK\r\n"),
1105 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1106 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1107 MockRead("Content-Length: 5\r\n\r\n"),
1108 MockRead("Hello"),
1109 };
Ryan Sleevib8d7ea02018-05-07 20:01:011110 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011111 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591112 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1113 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551114}
1115
1116// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011117TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551118 MockRead data_reads[] = {
1119 MockRead("HTTP/1.1 200 OK\r\n"),
1120 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1121 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1122 MockRead("Content-Length: 5\r\n\r\n"),
1123 MockRead("Hello"),
1124 };
Ryan Sleevib8d7ea02018-05-07 20:01:011125 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011126 EXPECT_THAT(out.rv,
1127 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551128}
1129
[email protected]54a9c6e52012-03-21 20:10:591130// Checks that two identical Location headers result in no error.
1131// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011132TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551133 MockRead data_reads[] = {
1134 MockRead("HTTP/1.1 302 Redirect\r\n"),
1135 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591136 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551137 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061138 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551139 };
1140
1141 HttpRequestInfo request;
1142 request.method = "GET";
1143 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101144 request.traffic_annotation =
1145 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551146
danakj1fd259a02016-04-16 03:17:091147 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161148 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551149
Ryan Sleevib8d7ea02018-05-07 20:01:011150 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071151 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551152
[email protected]49639fa2011-12-20 23:22:411153 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551154
tfarina42834112016-09-22 13:38:201155 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011156 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551157
robpercival214763f2016-07-01 23:27:011158 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551159
bnc691fda62016-08-12 00:43:161160 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521161 ASSERT_TRUE(response);
1162 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551163 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1164 std::string url;
1165 EXPECT_TRUE(response->headers->IsRedirect(&url));
1166 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471167 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551168}
1169
[email protected]1628fe92011-10-04 23:04:551170// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011171TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551172 MockRead data_reads[] = {
1173 MockRead("HTTP/1.1 302 Redirect\r\n"),
1174 MockRead("Location: http://good.com/\r\n"),
1175 MockRead("Location: http://evil.com/\r\n"),
1176 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061177 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551178 };
Ryan Sleevib8d7ea02018-05-07 20:01:011179 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011180 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551181}
1182
[email protected]ef0faf2e72009-03-05 23:27:231183// Do a request using the HEAD method. Verify that we don't try to read the
1184// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011185TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421186 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231187 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231188 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101189 request.traffic_annotation =
1190 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231191
danakj1fd259a02016-04-16 03:17:091192 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161193 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091194 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161195 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091196 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1197 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271198
[email protected]ef0faf2e72009-03-05 23:27:231199 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131200 MockWrite("HEAD / HTTP/1.1\r\n"
1201 "Host: www.example.org\r\n"
1202 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231203 };
1204 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231205 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1206 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231207
mmenked39192ee2015-12-09 00:57:231208 // No response body because the test stops reading here.
1209 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231210 };
1211
Ryan Sleevib8d7ea02018-05-07 20:01:011212 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071213 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231214
[email protected]49639fa2011-12-20 23:22:411215 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231216
tfarina42834112016-09-22 13:38:201217 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011218 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231219
1220 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011221 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231222
bnc691fda62016-08-12 00:43:161223 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521224 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231225
1226 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521227 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231228 EXPECT_EQ(1234, response->headers->GetContentLength());
1229 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471230 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091231 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1232 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231233
1234 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101235 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231236 bool has_server_header = response->headers->EnumerateHeader(
1237 &iter, "Server", &server_header);
1238 EXPECT_TRUE(has_server_header);
1239 EXPECT_EQ("Blah", server_header);
1240
1241 // Reading should give EOF right away, since there is no message body
1242 // (despite non-zero content-length).
1243 std::string response_data;
bnc691fda62016-08-12 00:43:161244 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011245 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231246 EXPECT_EQ("", response_data);
1247}
1248
bncd16676a2016-07-20 16:23:011249TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091250 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521251
1252 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351253 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1254 MockRead("hello"),
1255 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1256 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061257 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521258 };
Ryan Sleevib8d7ea02018-05-07 20:01:011259 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071260 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521261
[email protected]0b0bf032010-09-21 18:08:501262 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521263 "hello", "world"
1264 };
1265
1266 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421267 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521268 request.method = "GET";
bncce36dca22015-04-21 22:11:231269 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101270 request.traffic_annotation =
1271 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521272
bnc691fda62016-08-12 00:43:161273 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271274
[email protected]49639fa2011-12-20 23:22:411275 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521276
tfarina42834112016-09-22 13:38:201277 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011278 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521279
1280 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011281 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521282
bnc691fda62016-08-12 00:43:161283 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521284 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521285
wezca1070932016-05-26 20:30:521286 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251287 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471288 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521289
1290 std::string response_data;
bnc691fda62016-08-12 00:43:161291 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011292 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251293 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521294 }
1295}
1296
bncd16676a2016-07-20 16:23:011297TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091298 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221299 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191300 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221301 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271302
[email protected]1c773ea12009-04-28 19:58:421303 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521304 request.method = "POST";
1305 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271306 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:101307 request.traffic_annotation =
1308 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521309
shivanishab9a143952016-09-19 17:23:411310 // Check the upload progress returned before initialization is correct.
1311 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1312 EXPECT_EQ(0u, progress.size());
1313 EXPECT_EQ(0u, progress.position());
1314
danakj1fd259a02016-04-16 03:17:091315 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161316 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271317
initial.commit586acc5fe2008-07-26 22:42:521318 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351319 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1320 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1321 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061322 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521323 };
Ryan Sleevib8d7ea02018-05-07 20:01:011324 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071325 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521326
[email protected]49639fa2011-12-20 23:22:411327 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521328
tfarina42834112016-09-22 13:38:201329 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521331
1332 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011333 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521334
bnc691fda62016-08-12 00:43:161335 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521336 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521337
wezca1070932016-05-26 20:30:521338 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251339 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521340
1341 std::string response_data;
bnc691fda62016-08-12 00:43:161342 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011343 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251344 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521345}
1346
[email protected]3a2d3662009-03-27 03:49:141347// This test is almost the same as Ignores100 above, but the response contains
1348// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571349// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011350TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421351 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141352 request.method = "GET";
1353 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101354 request.traffic_annotation =
1355 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141356
danakj1fd259a02016-04-16 03:17:091357 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161358 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271359
[email protected]3a2d3662009-03-27 03:49:141360 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571361 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1362 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141363 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061364 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141365 };
Ryan Sleevib8d7ea02018-05-07 20:01:011366 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071367 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141368
[email protected]49639fa2011-12-20 23:22:411369 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141370
tfarina42834112016-09-22 13:38:201371 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011372 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141373
1374 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011375 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141376
bnc691fda62016-08-12 00:43:161377 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521378 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141379
wezca1070932016-05-26 20:30:521380 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141381 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1382
1383 std::string response_data;
bnc691fda62016-08-12 00:43:161384 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011385 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141386 EXPECT_EQ("hello world", response_data);
1387}
1388
Andrew Comminos517a92c2019-01-14 17:49:561389TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1390 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381391 base::TimeDelta::FromMilliseconds(10);
1392
1393 HttpRequestInfo request;
1394 request.method = "GET";
1395 request.url = GURL("http://www.foo.com/");
1396 request.traffic_annotation =
1397 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1398
1399 std::vector<MockWrite> data_writes = {
1400 MockWrite(ASYNC, 0,
1401 "GET / HTTP/1.1\r\n"
1402 "Host: www.foo.com\r\n"
1403 "Connection: keep-alive\r\n\r\n"),
1404 };
1405
1406 std::vector<MockRead> data_reads = {
1407 // Write one byte of the status line, followed by a pause.
1408 MockRead(ASYNC, 1, "H"),
1409 MockRead(ASYNC, ERR_IO_PENDING, 2),
1410 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1411 MockRead(ASYNC, 4, "hello world"),
1412 MockRead(SYNCHRONOUS, OK, 5),
1413 };
1414
1415 SequencedSocketData data(data_reads, data_writes);
1416 session_deps_.socket_factory->AddSocketDataProvider(&data);
1417
1418 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1419
1420 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1421
1422 TestCompletionCallback callback;
1423
1424 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1425 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1426
1427 data.RunUntilPaused();
1428 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561429 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381430 data.Resume();
1431
1432 rv = callback.WaitForResult();
1433 EXPECT_THAT(rv, IsOk());
1434
1435 const HttpResponseInfo* response = trans.GetResponseInfo();
1436 ASSERT_TRUE(response);
1437
1438 EXPECT_TRUE(response->headers);
1439 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1440
1441 LoadTimingInfo load_timing_info;
1442 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1443 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1444 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561445 // Ensure we didn't include the delay in the TTFB time.
1446 EXPECT_EQ(load_timing_info.receive_headers_start,
1447 load_timing_info.connect_timing.connect_end);
1448 // Ensure that the mock clock advanced at all.
1449 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1450 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381451
1452 std::string response_data;
1453 rv = ReadTransaction(&trans, &response_data);
1454 EXPECT_THAT(rv, IsOk());
1455 EXPECT_EQ("hello world", response_data);
1456}
1457
1458// Tests that the time-to-first-byte reported in a transaction's load timing
1459// info uses the first response, even if 1XX/informational.
1460void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561461 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381462 base::TimeDelta::FromMilliseconds(10);
1463
1464 HttpRequestInfo request;
1465 request.method = "GET";
1466 request.url = GURL("https://www.foo.com/");
1467 request.traffic_annotation =
1468 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1469
1470 SSLSocketDataProvider ssl(ASYNC, OK);
1471 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1472
1473 std::vector<MockWrite> data_writes;
1474 std::vector<MockRead> data_reads;
1475
1476 spdy::SpdySerializedFrame spdy_req(
1477 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1478
1479 spdy::SpdyHeaderBlock spdy_resp1_headers;
1480 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1481 spdy::SpdySerializedFrame spdy_resp1(
1482 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1483 spdy::SpdySerializedFrame spdy_resp2(
1484 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1485 spdy::SpdySerializedFrame spdy_data(
1486 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1487
1488 if (use_spdy) {
1489 ssl.next_proto = kProtoHTTP2;
1490
1491 data_writes = {CreateMockWrite(spdy_req, 0)};
1492
1493 data_reads = {
1494 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1495 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1496 MockRead(SYNCHRONOUS, OK, 5),
1497 };
1498 } else {
1499 data_writes = {
1500 MockWrite(ASYNC, 0,
1501 "GET / HTTP/1.1\r\n"
1502 "Host: www.foo.com\r\n"
1503 "Connection: keep-alive\r\n\r\n"),
1504 };
1505
1506 data_reads = {
1507 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1508 MockRead(ASYNC, ERR_IO_PENDING, 2),
1509
1510 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1511 MockRead(ASYNC, 4, "hello world"),
1512 MockRead(SYNCHRONOUS, OK, 5),
1513 };
1514 }
1515
1516 SequencedSocketData data(data_reads, data_writes);
1517 session_deps_.socket_factory->AddSocketDataProvider(&data);
1518
1519 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1520
1521 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1522
1523 TestCompletionCallback callback;
1524
1525 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1527
1528 data.RunUntilPaused();
1529 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1530 // the delay before parsing the 200 response.
1531 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561532 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381533 data.Resume();
1534
1535 rv = callback.WaitForResult();
1536 EXPECT_THAT(rv, IsOk());
1537
1538 const HttpResponseInfo* response = trans.GetResponseInfo();
1539 ASSERT_TRUE(response);
1540
1541 LoadTimingInfo load_timing_info;
1542 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1543 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1544 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561545 // Ensure we didn't include the delay in the TTFB time.
1546 EXPECT_EQ(load_timing_info.receive_headers_start,
1547 load_timing_info.connect_timing.connect_end);
1548 // Ensure that the mock clock advanced at all.
1549 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1550 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381551
1552 std::string response_data;
1553 rv = ReadTransaction(&trans, &response_data);
1554 EXPECT_THAT(rv, IsOk());
1555 EXPECT_EQ("hello world", response_data);
1556}
1557
Andrew Comminos517a92c2019-01-14 17:49:561558TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381559 Check100ResponseTiming(false /* use_spdy */);
1560}
1561
Andrew Comminos517a92c2019-01-14 17:49:561562TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381563 Check100ResponseTiming(true /* use_spdy */);
1564}
1565
bncd16676a2016-07-20 16:23:011566TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081567 HttpRequestInfo request;
1568 request.method = "POST";
1569 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101570 request.traffic_annotation =
1571 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081572
danakj1fd259a02016-04-16 03:17:091573 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161574 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081575
1576 MockRead data_reads[] = {
1577 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1578 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381579 };
Ryan Sleevib8d7ea02018-05-07 20:01:011580 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081581 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381582
zmo9528c9f42015-08-04 22:12:081583 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381584
tfarina42834112016-09-22 13:38:201585 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011586 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381587
zmo9528c9f42015-08-04 22:12:081588 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011589 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381590
zmo9528c9f42015-08-04 22:12:081591 std::string response_data;
bnc691fda62016-08-12 00:43:161592 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011593 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081594 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381595}
1596
bncd16676a2016-07-20 16:23:011597TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381598 HttpRequestInfo request;
1599 request.method = "POST";
1600 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101601 request.traffic_annotation =
1602 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381603
danakj1fd259a02016-04-16 03:17:091604 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161605 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271606
[email protected]ee9410e72010-01-07 01:42:381607 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061608 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381609 };
Ryan Sleevib8d7ea02018-05-07 20:01:011610 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071611 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381612
[email protected]49639fa2011-12-20 23:22:411613 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381614
tfarina42834112016-09-22 13:38:201615 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011616 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381617
1618 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011619 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381620}
1621
[email protected]23e482282013-06-14 16:08:021622void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511623 const MockWrite* write_failure,
1624 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421625 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521626 request.method = "GET";
1627 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101628 request.traffic_annotation =
1629 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521630
vishal.b62985ca92015-04-17 08:45:511631 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071632 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091633 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271634
[email protected]202965992011-12-07 23:04:511635 // Written data for successfully sending both requests.
1636 MockWrite data1_writes[] = {
1637 MockWrite("GET / HTTP/1.1\r\n"
1638 "Host: www.foo.com\r\n"
1639 "Connection: keep-alive\r\n\r\n"),
1640 MockWrite("GET / HTTP/1.1\r\n"
1641 "Host: www.foo.com\r\n"
1642 "Connection: keep-alive\r\n\r\n")
1643 };
1644
1645 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521646 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351647 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1648 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061649 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521650 };
[email protected]202965992011-12-07 23:04:511651
1652 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491653 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511654 data1_writes[1] = *write_failure;
1655 } else {
1656 ASSERT_TRUE(read_failure);
1657 data1_reads[2] = *read_failure;
1658 }
1659
Ryan Sleevib8d7ea02018-05-07 20:01:011660 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071661 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521662
1663 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351664 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1665 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061666 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521667 };
Ryan Sleevib8d7ea02018-05-07 20:01:011668 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071669 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521670
thestig9d3bb0c2015-01-24 00:49:511671 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521672 "hello", "world"
1673 };
1674
mikecironef22f9812016-10-04 03:40:191675 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521676 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411677 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521678
bnc691fda62016-08-12 00:43:161679 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521680
tfarina42834112016-09-22 13:38:201681 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011682 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521683
1684 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011685 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521686
[email protected]58e32bb2013-01-21 18:23:251687 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161688 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251689 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1690 if (i == 0) {
1691 first_socket_log_id = load_timing_info.socket_log_id;
1692 } else {
1693 // The second request should be using a new socket.
1694 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1695 }
1696
bnc691fda62016-08-12 00:43:161697 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521698 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521699
wezca1070932016-05-26 20:30:521700 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471701 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251702 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521703
1704 std::string response_data;
bnc691fda62016-08-12 00:43:161705 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011706 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251707 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521708 }
1709}
[email protected]3d2a59b2008-09-26 19:44:251710
[email protected]a34f61ee2014-03-18 20:59:491711void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1712 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101713 const MockRead* read_failure,
1714 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491715 HttpRequestInfo request;
1716 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101717 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101718 request.traffic_annotation =
1719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491720
vishal.b62985ca92015-04-17 08:45:511721 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491722 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091723 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491724
[email protected]09356c652014-03-25 15:36:101725 SSLSocketDataProvider ssl1(ASYNC, OK);
1726 SSLSocketDataProvider ssl2(ASYNC, OK);
1727 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361728 ssl1.next_proto = kProtoHTTP2;
1729 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101730 }
1731 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1732 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491733
[email protected]09356c652014-03-25 15:36:101734 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131735 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491736 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131737 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351738 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131739 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191740 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491741
[email protected]09356c652014-03-25 15:36:101742 // HTTP/1.1 versions of the request and response.
1743 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1744 "Host: www.foo.com\r\n"
1745 "Connection: keep-alive\r\n\r\n";
1746 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1747 const char kHttpData[] = "hello";
1748
1749 std::vector<MockRead> data1_reads;
1750 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491751 if (write_failure) {
1752 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101753 data1_writes.push_back(*write_failure);
1754 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491755 } else {
1756 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101757 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411758 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101759 } else {
1760 data1_writes.push_back(MockWrite(kHttpRequest));
1761 }
1762 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491763 }
1764
Ryan Sleevib8d7ea02018-05-07 20:01:011765 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491766 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1767
[email protected]09356c652014-03-25 15:36:101768 std::vector<MockRead> data2_reads;
1769 std::vector<MockWrite> data2_writes;
1770
1771 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411772 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101773
bncdf80d44fd2016-07-15 20:27:411774 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1775 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101776 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1777 } else {
1778 data2_writes.push_back(
1779 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1780
1781 data2_reads.push_back(
1782 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1783 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1784 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1785 }
Ryan Sleevib8d7ea02018-05-07 20:01:011786 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491787 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1788
1789 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591790 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491791 // Wait for the preconnect to complete.
1792 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1793 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231794 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491795
1796 // Make the request.
1797 TestCompletionCallback callback;
1798
bnc691fda62016-08-12 00:43:161799 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491800
tfarina42834112016-09-22 13:38:201801 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011802 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491803
1804 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011805 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491806
1807 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161808 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101809 TestLoadTimingNotReused(
1810 load_timing_info,
1811 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491812
bnc691fda62016-08-12 00:43:161813 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521814 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491815
wezca1070932016-05-26 20:30:521816 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021817 if (response->was_fetched_via_spdy) {
1818 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1819 } else {
1820 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1821 }
[email protected]a34f61ee2014-03-18 20:59:491822
1823 std::string response_data;
bnc691fda62016-08-12 00:43:161824 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011825 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101826 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491827}
1828
Biljith Jayan45a41722017-08-16 18:43:141829// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:181830// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:141831// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1832TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1833 HttpRequestInfo request;
1834 request.method = "GET";
1835 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101836 request.traffic_annotation =
1837 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141838
1839 // Check whether we give up after the third try.
1840
1841 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131842 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141843 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131844 spdy::SpdySerializedFrame spdy_response_go_away(
1845 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011846 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1847 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141848
1849 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011850 StaticSocketDataProvider data1(data_read1, data_write);
1851 StaticSocketDataProvider data2(data_read1, data_write);
1852 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141853
1854 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1855 AddSSLSocketData();
1856 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1857 AddSSLSocketData();
1858 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1859 AddSSLSocketData();
1860
1861 TestCompletionCallback callback;
1862 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1863 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1864
1865 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1866 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1867
1868 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:181869 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:141870}
1871
1872TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1873 HttpRequestInfo request;
1874 request.method = "GET";
1875 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101876 request.traffic_annotation =
1877 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141878
1879 // Check whether we try atleast thrice before giving up.
1880
1881 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131882 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141883 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131884 spdy::SpdySerializedFrame spdy_response_go_away(
1885 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011886 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1887 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141888
1889 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131890 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141891 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131892 spdy::SpdySerializedFrame spdy_data(
1893 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141894 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1895 CreateMockRead(spdy_data, 2)};
1896
1897 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011898 StaticSocketDataProvider data1(data_read1, data_write);
1899 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141900 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011901 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141902
1903 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1904 AddSSLSocketData();
1905 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1906 AddSSLSocketData();
1907 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1908 AddSSLSocketData();
1909
1910 TestCompletionCallback callback;
1911 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1912 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1913
1914 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1915 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1916
1917 rv = callback.WaitForResult();
1918 EXPECT_THAT(rv, IsOk());
1919}
1920
bncd16676a2016-07-20 16:23:011921TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061922 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351923 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511924}
1925
bncd16676a2016-07-20 16:23:011926TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061927 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351928 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251929}
1930
bncd16676a2016-07-20 16:23:011931TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061932 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351933 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251934}
1935
[email protected]d58ceea82014-06-04 10:55:541936// Make sure that on a 408 response (Request Timeout), the request is retried,
1937// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011938TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541939 MockRead read_failure(SYNCHRONOUS,
1940 "HTTP/1.1 408 Request Timeout\r\n"
1941 "Connection: Keep-Alive\r\n"
1942 "Content-Length: 6\r\n\r\n"
1943 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351944 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:541945}
1946
bncd16676a2016-07-20 16:23:011947TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:491948 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351949 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:491950}
1951
bncd16676a2016-07-20 16:23:011952TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:491953 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351954 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491955}
1956
bncd16676a2016-07-20 16:23:011957TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:491958 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351959 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101960}
1961
bncd16676a2016-07-20 16:23:011962TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101963 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351964 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101965}
1966
[email protected]d58ceea82014-06-04 10:55:541967// Make sure that on a 408 response (Request Timeout), the request is retried,
1968// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:011969TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:541970 MockRead read_failure(SYNCHRONOUS,
1971 "HTTP/1.1 408 Request Timeout\r\n"
1972 "Connection: Keep-Alive\r\n"
1973 "Content-Length: 6\r\n\r\n"
1974 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351975 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
1976 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:541977}
1978
bncd16676a2016-07-20 16:23:011979TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:101980 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351981 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:101982}
1983
bncd16676a2016-07-20 16:23:011984TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:101985 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
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, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:101990 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351991 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101992}
1993
bncd16676a2016-07-20 16:23:011994TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101995 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351996 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491997}
1998
bncd16676a2016-07-20 16:23:011999TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:422000 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:252001 request.method = "GET";
bncce36dca22015-04-21 22:11:232002 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102003 request.traffic_annotation =
2004 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252005
danakj1fd259a02016-04-16 03:17:092006 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162007 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272008
[email protected]3d2a59b2008-09-26 19:44:252009 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062010 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352011 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2012 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062013 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252014 };
Ryan Sleevib8d7ea02018-05-07 20:01:012015 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072016 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252017
[email protected]49639fa2011-12-20 23:22:412018 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252019
tfarina42834112016-09-22 13:38:202020 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012021 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252022
2023 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012024 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592025
2026 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162027 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592028 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252029}
2030
2031// What do various browsers do when the server closes a non-keepalive
2032// connection without sending any response header or body?
2033//
2034// IE7: error page
2035// Safari 3.1.2 (Windows): error page
2036// Firefox 3.0.1: blank page
2037// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422038// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2039// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012040TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252041 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062042 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352043 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2044 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062045 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252046 };
Ryan Sleevib8d7ea02018-05-07 20:01:012047 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012048 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252049}
[email protected]1826a402014-01-08 15:40:482050
[email protected]7a5378b2012-11-04 03:25:172051// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2052// tests. There was a bug causing HttpNetworkTransaction to hang in the
2053// destructor in such situations.
2054// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012055TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172056 HttpRequestInfo request;
2057 request.method = "GET";
bncce36dca22015-04-21 22:11:232058 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102059 request.traffic_annotation =
2060 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172061
danakj1fd259a02016-04-16 03:17:092062 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582063 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192064 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172065
2066 MockRead data_reads[] = {
2067 MockRead("HTTP/1.0 200 OK\r\n"),
2068 MockRead("Connection: keep-alive\r\n"),
2069 MockRead("Content-Length: 100\r\n\r\n"),
2070 MockRead("hello"),
2071 MockRead(SYNCHRONOUS, 0),
2072 };
Ryan Sleevib8d7ea02018-05-07 20:01:012073 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072074 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172075
2076 TestCompletionCallback callback;
2077
tfarina42834112016-09-22 13:38:202078 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012079 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172080
2081 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012082 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172083
Victor Costan9c7302b2018-08-27 16:39:442084 scoped_refptr<IOBufferWithSize> io_buf =
2085 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502086 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172087 if (rv == ERR_IO_PENDING)
2088 rv = callback.WaitForResult();
2089 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502090 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012091 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172092
2093 trans.reset();
fdoray92e35a72016-06-10 15:54:552094 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172095 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2096}
2097
bncd16676a2016-07-20 16:23:012098TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172099 HttpRequestInfo request;
2100 request.method = "GET";
bncce36dca22015-04-21 22:11:232101 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102102 request.traffic_annotation =
2103 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172104
danakj1fd259a02016-04-16 03:17:092105 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582106 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192107 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172108
2109 MockRead data_reads[] = {
2110 MockRead("HTTP/1.0 200 OK\r\n"),
2111 MockRead("Connection: keep-alive\r\n"),
2112 MockRead("Content-Length: 100\r\n\r\n"),
2113 MockRead(SYNCHRONOUS, 0),
2114 };
Ryan Sleevib8d7ea02018-05-07 20:01:012115 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072116 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172117
2118 TestCompletionCallback callback;
2119
tfarina42834112016-09-22 13:38:202120 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012121 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172122
2123 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012124 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172125
Victor Costan9c7302b2018-08-27 16:39:442126 scoped_refptr<IOBufferWithSize> io_buf(
2127 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502128 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172129 if (rv == ERR_IO_PENDING)
2130 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012131 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172132
2133 trans.reset();
fdoray92e35a72016-06-10 15:54:552134 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172135 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2136}
2137
[email protected]0b0bf032010-09-21 18:08:502138// Test that we correctly reuse a keep-alive connection after not explicitly
2139// reading the body.
bncd16676a2016-07-20 16:23:012140TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132141 HttpRequestInfo request;
2142 request.method = "GET";
2143 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102144 request.traffic_annotation =
2145 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132146
vishal.b62985ca92015-04-17 08:45:512147 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072148 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092149 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272150
mmenkecc2298e2015-12-07 18:20:182151 const char* request_data =
2152 "GET / HTTP/1.1\r\n"
2153 "Host: www.foo.com\r\n"
2154 "Connection: keep-alive\r\n\r\n";
2155 MockWrite data_writes[] = {
2156 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2157 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2158 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2159 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2160 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2161 };
2162
[email protected]0b0bf032010-09-21 18:08:502163 // Note that because all these reads happen in the same
2164 // StaticSocketDataProvider, it shows that the same socket is being reused for
2165 // all transactions.
mmenkecc2298e2015-12-07 18:20:182166 MockRead data_reads[] = {
2167 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2168 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2169 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2170 MockRead(ASYNC, 7,
2171 "HTTP/1.1 302 Found\r\n"
2172 "Content-Length: 0\r\n\r\n"),
2173 MockRead(ASYNC, 9,
2174 "HTTP/1.1 302 Found\r\n"
2175 "Content-Length: 5\r\n\r\n"
2176 "hello"),
2177 MockRead(ASYNC, 11,
2178 "HTTP/1.1 301 Moved Permanently\r\n"
2179 "Content-Length: 0\r\n\r\n"),
2180 MockRead(ASYNC, 13,
2181 "HTTP/1.1 301 Moved Permanently\r\n"
2182 "Content-Length: 5\r\n\r\n"
2183 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132184
mmenkecc2298e2015-12-07 18:20:182185 // In the next two rounds, IsConnectedAndIdle returns false, due to
2186 // the set_busy_before_sync_reads(true) call, while the
2187 // HttpNetworkTransaction is being shut down, but the socket is still
2188 // reuseable. See http://crbug.com/544255.
2189 MockRead(ASYNC, 15,
2190 "HTTP/1.1 200 Hunky-Dory\r\n"
2191 "Content-Length: 5\r\n\r\n"),
2192 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132193
mmenkecc2298e2015-12-07 18:20:182194 MockRead(ASYNC, 18,
2195 "HTTP/1.1 200 Hunky-Dory\r\n"
2196 "Content-Length: 5\r\n\r\n"
2197 "he"),
2198 MockRead(SYNCHRONOUS, 19, "llo"),
2199
2200 // The body of the final request is actually read.
2201 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2202 MockRead(ASYNC, 22, "hello"),
2203 };
Ryan Sleevib8d7ea02018-05-07 20:01:012204 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182205 data.set_busy_before_sync_reads(true);
2206 session_deps_.socket_factory->AddSocketDataProvider(&data);
2207
Avi Drissman4365a4782018-12-28 19:26:242208 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502209 std::string response_lines[kNumUnreadBodies];
2210
mikecironef22f9812016-10-04 03:40:192211 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182212 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412213 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132214
Jeremy Roman0579ed62017-08-29 15:56:192215 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582216 session.get());
[email protected]fc31d6a42010-06-24 18:05:132217
tfarina42834112016-09-22 13:38:202218 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012219 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132220
[email protected]58e32bb2013-01-21 18:23:252221 LoadTimingInfo load_timing_info;
2222 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2223 if (i == 0) {
2224 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2225 first_socket_log_id = load_timing_info.socket_log_id;
2226 } else {
2227 TestLoadTimingReused(load_timing_info);
2228 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2229 }
2230
[email protected]fc31d6a42010-06-24 18:05:132231 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182232 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132233
mmenkecc2298e2015-12-07 18:20:182234 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502235 response_lines[i] = response->headers->GetStatusLine();
2236
mmenkecc2298e2015-12-07 18:20:182237 // Delete the transaction without reading the response bodies. Then spin
2238 // the message loop, so the response bodies are drained.
2239 trans.reset();
2240 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132241 }
[email protected]0b0bf032010-09-21 18:08:502242
2243 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182244 "HTTP/1.1 204 No Content",
2245 "HTTP/1.1 205 Reset Content",
2246 "HTTP/1.1 304 Not Modified",
2247 "HTTP/1.1 302 Found",
2248 "HTTP/1.1 302 Found",
2249 "HTTP/1.1 301 Moved Permanently",
2250 "HTTP/1.1 301 Moved Permanently",
2251 "HTTP/1.1 200 Hunky-Dory",
2252 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502253 };
2254
Avi Drissman4365a4782018-12-28 19:26:242255 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272256 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502257
2258 for (int i = 0; i < kNumUnreadBodies; ++i)
2259 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2260
[email protected]49639fa2011-12-20 23:22:412261 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162262 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202263 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012264 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162265 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182266 ASSERT_TRUE(response);
2267 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502268 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2269 std::string response_data;
bnc691fda62016-08-12 00:43:162270 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012271 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502272 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132273}
2274
mmenke5f94fda2016-06-02 20:54:132275// Sockets that receive extra data after a response is complete should not be
2276// reused.
bncd16676a2016-07-20 16:23:012277TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132278 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2279 MockWrite data_writes1[] = {
2280 MockWrite("HEAD / HTTP/1.1\r\n"
2281 "Host: www.borked.com\r\n"
2282 "Connection: keep-alive\r\n\r\n"),
2283 };
2284
2285 MockRead data_reads1[] = {
2286 MockRead("HTTP/1.1 200 OK\r\n"
2287 "Connection: keep-alive\r\n"
2288 "Content-Length: 22\r\n\r\n"
2289 "This server is borked."),
2290 };
2291
2292 MockWrite data_writes2[] = {
2293 MockWrite("GET /foo HTTP/1.1\r\n"
2294 "Host: www.borked.com\r\n"
2295 "Connection: keep-alive\r\n\r\n"),
2296 };
2297
2298 MockRead data_reads2[] = {
2299 MockRead("HTTP/1.1 200 OK\r\n"
2300 "Content-Length: 3\r\n\r\n"
2301 "foo"),
2302 };
Ryan Sleevib8d7ea02018-05-07 20:01:012303 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132304 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012305 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132306 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2307
2308 TestCompletionCallback callback;
2309 HttpRequestInfo request1;
2310 request1.method = "HEAD";
2311 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102312 request1.traffic_annotation =
2313 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132314
bnc87dcefc2017-05-25 12:47:582315 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192316 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202317 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012318 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132319
2320 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2321 ASSERT_TRUE(response1);
2322 ASSERT_TRUE(response1->headers);
2323 EXPECT_EQ(200, response1->headers->response_code());
2324 EXPECT_TRUE(response1->headers->IsKeepAlive());
2325
2326 std::string response_data1;
robpercival214763f2016-07-01 23:27:012327 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132328 EXPECT_EQ("", response_data1);
2329 // Deleting the transaction attempts to release the socket back into the
2330 // socket pool.
2331 trans1.reset();
2332
2333 HttpRequestInfo request2;
2334 request2.method = "GET";
2335 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102336 request2.traffic_annotation =
2337 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132338
bnc87dcefc2017-05-25 12:47:582339 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192340 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202341 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012342 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132343
2344 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2345 ASSERT_TRUE(response2);
2346 ASSERT_TRUE(response2->headers);
2347 EXPECT_EQ(200, response2->headers->response_code());
2348
2349 std::string response_data2;
robpercival214763f2016-07-01 23:27:012350 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132351 EXPECT_EQ("foo", response_data2);
2352}
2353
bncd16676a2016-07-20 16:23:012354TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132355 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2356 MockWrite data_writes1[] = {
2357 MockWrite("GET / HTTP/1.1\r\n"
2358 "Host: www.borked.com\r\n"
2359 "Connection: keep-alive\r\n\r\n"),
2360 };
2361
2362 MockRead data_reads1[] = {
2363 MockRead("HTTP/1.1 200 OK\r\n"
2364 "Connection: keep-alive\r\n"
2365 "Content-Length: 22\r\n\r\n"
2366 "This server is borked."
2367 "Bonus data!"),
2368 };
2369
2370 MockWrite data_writes2[] = {
2371 MockWrite("GET /foo HTTP/1.1\r\n"
2372 "Host: www.borked.com\r\n"
2373 "Connection: keep-alive\r\n\r\n"),
2374 };
2375
2376 MockRead data_reads2[] = {
2377 MockRead("HTTP/1.1 200 OK\r\n"
2378 "Content-Length: 3\r\n\r\n"
2379 "foo"),
2380 };
Ryan Sleevib8d7ea02018-05-07 20:01:012381 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132382 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012383 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132384 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2385
2386 TestCompletionCallback callback;
2387 HttpRequestInfo request1;
2388 request1.method = "GET";
2389 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102390 request1.traffic_annotation =
2391 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132392
bnc87dcefc2017-05-25 12:47:582393 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192394 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202395 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012396 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132397
2398 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2399 ASSERT_TRUE(response1);
2400 ASSERT_TRUE(response1->headers);
2401 EXPECT_EQ(200, response1->headers->response_code());
2402 EXPECT_TRUE(response1->headers->IsKeepAlive());
2403
2404 std::string response_data1;
robpercival214763f2016-07-01 23:27:012405 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132406 EXPECT_EQ("This server is borked.", response_data1);
2407 // Deleting the transaction attempts to release the socket back into the
2408 // socket pool.
2409 trans1.reset();
2410
2411 HttpRequestInfo request2;
2412 request2.method = "GET";
2413 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102414 request2.traffic_annotation =
2415 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132416
bnc87dcefc2017-05-25 12:47:582417 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192418 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202419 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012420 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132421
2422 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2423 ASSERT_TRUE(response2);
2424 ASSERT_TRUE(response2->headers);
2425 EXPECT_EQ(200, response2->headers->response_code());
2426
2427 std::string response_data2;
robpercival214763f2016-07-01 23:27:012428 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132429 EXPECT_EQ("foo", response_data2);
2430}
2431
bncd16676a2016-07-20 16:23:012432TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132433 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2434 MockWrite data_writes1[] = {
2435 MockWrite("GET / HTTP/1.1\r\n"
2436 "Host: www.borked.com\r\n"
2437 "Connection: keep-alive\r\n\r\n"),
2438 };
2439
2440 MockRead data_reads1[] = {
2441 MockRead("HTTP/1.1 200 OK\r\n"
2442 "Connection: keep-alive\r\n"
2443 "Transfer-Encoding: chunked\r\n\r\n"),
2444 MockRead("16\r\nThis server is borked.\r\n"),
2445 MockRead("0\r\n\r\nBonus data!"),
2446 };
2447
2448 MockWrite data_writes2[] = {
2449 MockWrite("GET /foo HTTP/1.1\r\n"
2450 "Host: www.borked.com\r\n"
2451 "Connection: keep-alive\r\n\r\n"),
2452 };
2453
2454 MockRead data_reads2[] = {
2455 MockRead("HTTP/1.1 200 OK\r\n"
2456 "Content-Length: 3\r\n\r\n"
2457 "foo"),
2458 };
Ryan Sleevib8d7ea02018-05-07 20:01:012459 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132460 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012461 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132462 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2463
2464 TestCompletionCallback callback;
2465 HttpRequestInfo request1;
2466 request1.method = "GET";
2467 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102468 request1.traffic_annotation =
2469 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132470
bnc87dcefc2017-05-25 12:47:582471 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192472 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202473 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012474 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132475
2476 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2477 ASSERT_TRUE(response1);
2478 ASSERT_TRUE(response1->headers);
2479 EXPECT_EQ(200, response1->headers->response_code());
2480 EXPECT_TRUE(response1->headers->IsKeepAlive());
2481
2482 std::string response_data1;
robpercival214763f2016-07-01 23:27:012483 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132484 EXPECT_EQ("This server is borked.", response_data1);
2485 // Deleting the transaction attempts to release the socket back into the
2486 // socket pool.
2487 trans1.reset();
2488
2489 HttpRequestInfo request2;
2490 request2.method = "GET";
2491 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102492 request2.traffic_annotation =
2493 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132494
bnc87dcefc2017-05-25 12:47:582495 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192496 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202497 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012498 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132499
2500 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2501 ASSERT_TRUE(response2);
2502 ASSERT_TRUE(response2->headers);
2503 EXPECT_EQ(200, response2->headers->response_code());
2504
2505 std::string response_data2;
robpercival214763f2016-07-01 23:27:012506 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132507 EXPECT_EQ("foo", response_data2);
2508}
2509
2510// This is a little different from the others - it tests the case that the
2511// HttpStreamParser doesn't know if there's extra data on a socket or not when
2512// the HttpNetworkTransaction is torn down, because the response body hasn't
2513// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012514TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132515 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2516 MockWrite data_writes1[] = {
2517 MockWrite("GET / HTTP/1.1\r\n"
2518 "Host: www.borked.com\r\n"
2519 "Connection: keep-alive\r\n\r\n"),
2520 };
2521
2522 MockRead data_reads1[] = {
2523 MockRead("HTTP/1.1 200 OK\r\n"
2524 "Connection: keep-alive\r\n"
2525 "Transfer-Encoding: chunked\r\n\r\n"),
2526 MockRead("16\r\nThis server is borked.\r\n"),
2527 MockRead("0\r\n\r\nBonus data!"),
2528 };
Ryan Sleevib8d7ea02018-05-07 20:01:012529 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132530 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2531
2532 TestCompletionCallback callback;
2533 HttpRequestInfo request1;
2534 request1.method = "GET";
2535 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102536 request1.traffic_annotation =
2537 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132538
bnc87dcefc2017-05-25 12:47:582539 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192540 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582541 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012542 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132543
bnc87dcefc2017-05-25 12:47:582544 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132545 ASSERT_TRUE(response1);
2546 ASSERT_TRUE(response1->headers);
2547 EXPECT_EQ(200, response1->headers->response_code());
2548 EXPECT_TRUE(response1->headers->IsKeepAlive());
2549
2550 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2551 // response body.
bnc87dcefc2017-05-25 12:47:582552 trans.reset();
mmenke5f94fda2016-06-02 20:54:132553
2554 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2555 // socket can't be reused, rather than returning it to the socket pool.
2556 base::RunLoop().RunUntilIdle();
2557
2558 // There should be no idle sockets in the pool.
2559 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2560}
2561
[email protected]038e9a32008-10-08 22:40:162562// Test the request-challenge-retry sequence for basic auth.
2563// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012564TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422565 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162566 request.method = "GET";
bncce36dca22015-04-21 22:11:232567 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102568 request.traffic_annotation =
2569 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162570
vishal.b62985ca92015-04-17 08:45:512571 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072572 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092573 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162574 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272575
[email protected]f9ee6b52008-11-08 06:46:232576 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232577 MockWrite(
2578 "GET / HTTP/1.1\r\n"
2579 "Host: www.example.org\r\n"
2580 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232581 };
2582
[email protected]038e9a32008-10-08 22:40:162583 MockRead data_reads1[] = {
2584 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2585 // Give a couple authenticate options (only the middle one is actually
2586 // supported).
[email protected]22927ad2009-09-21 19:56:192587 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162588 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2589 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2590 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2591 // Large content-length -- won't matter, as connection will be reset.
2592 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062593 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162594 };
2595
2596 // After calling trans->RestartWithAuth(), this is the request we should
2597 // be issuing -- the final header line contains the credentials.
2598 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232599 MockWrite(
2600 "GET / HTTP/1.1\r\n"
2601 "Host: www.example.org\r\n"
2602 "Connection: keep-alive\r\n"
2603 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162604 };
2605
2606 // Lastly, the server responds with the actual content.
2607 MockRead data_reads2[] = {
2608 MockRead("HTTP/1.0 200 OK\r\n"),
2609 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2610 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062611 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162612 };
2613
Ryan Sleevib8d7ea02018-05-07 20:01:012614 StaticSocketDataProvider data1(data_reads1, data_writes1);
2615 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072616 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2617 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162618
[email protected]49639fa2011-12-20 23:22:412619 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162620
tfarina42834112016-09-22 13:38:202621 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012622 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162623
2624 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012625 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162626
[email protected]58e32bb2013-01-21 18:23:252627 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162628 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252629 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2630
Ryan Sleevib8d7ea02018-05-07 20:01:012631 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162632 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012633 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162634 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192635
bnc691fda62016-08-12 00:43:162636 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522637 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582638 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162639
[email protected]49639fa2011-12-20 23:22:412640 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162641
bnc691fda62016-08-12 00:43:162642 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012643 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162644
2645 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012646 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162647
[email protected]58e32bb2013-01-21 18:23:252648 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162649 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252650 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2651 // The load timing after restart should have a new socket ID, and times after
2652 // those of the first load timing.
2653 EXPECT_LE(load_timing_info1.receive_headers_end,
2654 load_timing_info2.connect_timing.connect_start);
2655 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2656
Ryan Sleevib8d7ea02018-05-07 20:01:012657 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162658 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012659 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162660 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192661
bnc691fda62016-08-12 00:43:162662 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522663 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582664 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162665 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162666}
2667
ttuttled9dbc652015-09-29 20:00:592668// Test the request-challenge-retry sequence for basic auth.
2669// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012670TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592671 HttpRequestInfo request;
2672 request.method = "GET";
2673 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102674 request.traffic_annotation =
2675 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592676
2677 TestNetLog log;
2678 MockHostResolver* resolver = new MockHostResolver();
2679 session_deps_.net_log = &log;
2680 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092681 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162682 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592683
2684 resolver->rules()->ClearRules();
2685 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2686
2687 MockWrite data_writes1[] = {
2688 MockWrite("GET / HTTP/1.1\r\n"
2689 "Host: www.example.org\r\n"
2690 "Connection: keep-alive\r\n\r\n"),
2691 };
2692
2693 MockRead data_reads1[] = {
2694 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2695 // Give a couple authenticate options (only the middle one is actually
2696 // supported).
2697 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2698 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2699 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2700 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2701 // Large content-length -- won't matter, as connection will be reset.
2702 MockRead("Content-Length: 10000\r\n\r\n"),
2703 MockRead(SYNCHRONOUS, ERR_FAILED),
2704 };
2705
2706 // After calling trans->RestartWithAuth(), this is the request we should
2707 // be issuing -- the final header line contains the credentials.
2708 MockWrite data_writes2[] = {
2709 MockWrite("GET / HTTP/1.1\r\n"
2710 "Host: www.example.org\r\n"
2711 "Connection: keep-alive\r\n"
2712 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2713 };
2714
2715 // Lastly, the server responds with the actual content.
2716 MockRead data_reads2[] = {
2717 MockRead("HTTP/1.0 200 OK\r\n"),
2718 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2719 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2720 };
2721
Ryan Sleevib8d7ea02018-05-07 20:01:012722 StaticSocketDataProvider data1(data_reads1, data_writes1);
2723 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592724 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2725 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2726
2727 TestCompletionCallback callback1;
2728
bnc691fda62016-08-12 00:43:162729 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202730 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592731
2732 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162733 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592734 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2735
Ryan Sleevib8d7ea02018-05-07 20:01:012736 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162737 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012738 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162739 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592740
bnc691fda62016-08-12 00:43:162741 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592742 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582743 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592744
2745 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162746 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592747 ASSERT_FALSE(endpoint.address().empty());
2748 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2749
2750 resolver->rules()->ClearRules();
2751 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2752
2753 TestCompletionCallback callback2;
2754
bnc691fda62016-08-12 00:43:162755 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592756 AuthCredentials(kFoo, kBar), callback2.callback())));
2757
2758 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162759 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592760 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2761 // The load timing after restart should have a new socket ID, and times after
2762 // those of the first load timing.
2763 EXPECT_LE(load_timing_info1.receive_headers_end,
2764 load_timing_info2.connect_timing.connect_start);
2765 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2766
Ryan Sleevib8d7ea02018-05-07 20:01:012767 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162768 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012769 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162770 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592771
bnc691fda62016-08-12 00:43:162772 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592773 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582774 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592775 EXPECT_EQ(100, response->headers->GetContentLength());
2776
bnc691fda62016-08-12 00:43:162777 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592778 ASSERT_FALSE(endpoint.address().empty());
2779 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2780}
2781
David Benjamin83ddfb32018-03-30 01:07:522782// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2783// will eventually give up.
2784TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2785 HttpRequestInfo request;
2786 request.method = "GET";
2787 request.url = GURL("http://www.example.org/");
2788 request.traffic_annotation =
2789 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2790
2791 TestNetLog log;
2792 session_deps_.net_log = &log;
2793 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2794 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2795
2796 MockWrite data_writes[] = {
2797 MockWrite("GET / HTTP/1.1\r\n"
2798 "Host: www.example.org\r\n"
2799 "Connection: keep-alive\r\n\r\n"),
2800 };
2801
2802 MockRead data_reads[] = {
2803 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2804 // Give a couple authenticate options (only the middle one is actually
2805 // supported).
2806 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2807 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2808 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2809 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2810 // Large content-length -- won't matter, as connection will be reset.
2811 MockRead("Content-Length: 10000\r\n\r\n"),
2812 MockRead(SYNCHRONOUS, ERR_FAILED),
2813 };
2814
2815 // After calling trans->RestartWithAuth(), this is the request we should
2816 // be issuing -- the final header line contains the credentials.
2817 MockWrite data_writes_restart[] = {
2818 MockWrite("GET / HTTP/1.1\r\n"
2819 "Host: www.example.org\r\n"
2820 "Connection: keep-alive\r\n"
2821 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2822 };
2823
Ryan Sleevib8d7ea02018-05-07 20:01:012824 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522825 session_deps_.socket_factory->AddSocketDataProvider(&data);
2826
2827 TestCompletionCallback callback;
2828 int rv = callback.GetResult(
2829 trans.Start(&request, callback.callback(), NetLogWithSource()));
2830
2831 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2832 for (int i = 0; i < 32; i++) {
2833 // Check the previous response was a 401.
2834 EXPECT_THAT(rv, IsOk());
2835 const HttpResponseInfo* response = trans.GetResponseInfo();
2836 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582837 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522838
2839 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012840 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522841 session_deps_.socket_factory->AddSocketDataProvider(
2842 data_restarts.back().get());
2843 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2844 callback.callback()));
2845 }
2846
2847 // After too many tries, the transaction should have given up.
2848 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2849}
2850
bncd16676a2016-07-20 16:23:012851TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462852 HttpRequestInfo request;
2853 request.method = "GET";
bncce36dca22015-04-21 22:11:232854 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292855 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:102856 request.traffic_annotation =
2857 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462858
danakj1fd259a02016-04-16 03:17:092859 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162860 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272861
[email protected]861fcd52009-08-26 02:33:462862 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232863 MockWrite(
2864 "GET / HTTP/1.1\r\n"
2865 "Host: www.example.org\r\n"
2866 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462867 };
2868
2869 MockRead data_reads[] = {
2870 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2871 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2872 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2873 // Large content-length -- won't matter, as connection will be reset.
2874 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062875 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462876 };
2877
Ryan Sleevib8d7ea02018-05-07 20:01:012878 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072879 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412880 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462881
tfarina42834112016-09-22 13:38:202882 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012883 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462884
2885 rv = callback.WaitForResult();
2886 EXPECT_EQ(0, rv);
2887
Ryan Sleevib8d7ea02018-05-07 20:01:012888 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162889 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012890 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162891 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192892
bnc691fda62016-08-12 00:43:162893 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522894 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582895 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462896}
2897
[email protected]2d2697f92009-02-18 21:00:322898// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2899// connection.
bncd16676a2016-07-20 16:23:012900TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182901 // On the second pass, the body read of the auth challenge is synchronous, so
2902 // IsConnectedAndIdle returns false. The socket should still be drained and
2903 // reused. See http://crbug.com/544255.
2904 for (int i = 0; i < 2; ++i) {
2905 HttpRequestInfo request;
2906 request.method = "GET";
2907 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102908 request.traffic_annotation =
2909 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322910
mmenkecc2298e2015-12-07 18:20:182911 TestNetLog log;
2912 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092913 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272914
mmenkecc2298e2015-12-07 18:20:182915 MockWrite data_writes[] = {
2916 MockWrite(ASYNC, 0,
2917 "GET / HTTP/1.1\r\n"
2918 "Host: www.example.org\r\n"
2919 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322920
bnc691fda62016-08-12 00:43:162921 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182922 // be issuing -- the final header line contains the credentials.
2923 MockWrite(ASYNC, 6,
2924 "GET / HTTP/1.1\r\n"
2925 "Host: www.example.org\r\n"
2926 "Connection: keep-alive\r\n"
2927 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2928 };
[email protected]2d2697f92009-02-18 21:00:322929
mmenkecc2298e2015-12-07 18:20:182930 MockRead data_reads[] = {
2931 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2932 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2933 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2934 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2935 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322936
mmenkecc2298e2015-12-07 18:20:182937 // Lastly, the server responds with the actual content.
2938 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2939 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2940 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2941 MockRead(ASYNC, 10, "Hello"),
2942 };
[email protected]2d2697f92009-02-18 21:00:322943
Ryan Sleevib8d7ea02018-05-07 20:01:012944 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182945 data.set_busy_before_sync_reads(true);
2946 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462947
mmenkecc2298e2015-12-07 18:20:182948 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322949
bnc691fda62016-08-12 00:43:162950 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202951 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012952 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322953
mmenkecc2298e2015-12-07 18:20:182954 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162955 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:182956 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322957
bnc691fda62016-08-12 00:43:162958 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182959 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582960 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:322961
mmenkecc2298e2015-12-07 18:20:182962 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252963
bnc691fda62016-08-12 00:43:162964 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2965 callback2.callback());
robpercival214763f2016-07-01 23:27:012966 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322967
mmenkecc2298e2015-12-07 18:20:182968 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162969 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:182970 TestLoadTimingReused(load_timing_info2);
2971 // The load timing after restart should have the same socket ID, and times
2972 // those of the first load timing.
2973 EXPECT_LE(load_timing_info1.receive_headers_end,
2974 load_timing_info2.send_start);
2975 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322976
bnc691fda62016-08-12 00:43:162977 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182978 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582979 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:182980 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322981
mmenkecc2298e2015-12-07 18:20:182982 std::string response_data;
bnc691fda62016-08-12 00:43:162983 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:322984
Ryan Sleevib8d7ea02018-05-07 20:01:012985 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162986 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012987 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162988 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:182989 }
[email protected]2d2697f92009-02-18 21:00:322990}
2991
2992// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2993// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:012994TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422995 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322996 request.method = "GET";
bncce36dca22015-04-21 22:11:232997 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102998 request.traffic_annotation =
2999 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323000
danakj1fd259a02016-04-16 03:17:093001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273002
[email protected]2d2697f92009-02-18 21:00:323003 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163004 MockWrite("GET / HTTP/1.1\r\n"
3005 "Host: www.example.org\r\n"
3006 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323007
bnc691fda62016-08-12 00:43:163008 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233009 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163010 MockWrite("GET / HTTP/1.1\r\n"
3011 "Host: www.example.org\r\n"
3012 "Connection: keep-alive\r\n"
3013 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323014 };
3015
[email protected]2d2697f92009-02-18 21:00:323016 MockRead data_reads1[] = {
3017 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3018 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313019 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323020
3021 // Lastly, the server responds with the actual content.
3022 MockRead("HTTP/1.1 200 OK\r\n"),
3023 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503024 MockRead("Content-Length: 5\r\n\r\n"),
3025 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323026 };
3027
[email protected]2d0a4f92011-05-05 16:38:463028 // An incorrect reconnect would cause this to be read.
3029 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063030 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463031 };
3032
Ryan Sleevib8d7ea02018-05-07 20:01:013033 StaticSocketDataProvider data1(data_reads1, data_writes1);
3034 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073035 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3036 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323037
[email protected]49639fa2011-12-20 23:22:413038 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323039
bnc691fda62016-08-12 00:43:163040 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203041 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013042 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323043
3044 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013045 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323046
bnc691fda62016-08-12 00:43:163047 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523048 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583049 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323050
[email protected]49639fa2011-12-20 23:22:413051 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323052
bnc691fda62016-08-12 00:43:163053 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323055
3056 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013057 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323058
bnc691fda62016-08-12 00:43:163059 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523060 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583061 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503062 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323063}
3064
3065// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3066// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013067TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423068 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323069 request.method = "GET";
bncce36dca22015-04-21 22:11:233070 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103071 request.traffic_annotation =
3072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323073
danakj1fd259a02016-04-16 03:17:093074 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273075
[email protected]2d2697f92009-02-18 21:00:323076 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163077 MockWrite("GET / HTTP/1.1\r\n"
3078 "Host: www.example.org\r\n"
3079 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323080
bnc691fda62016-08-12 00:43:163081 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233082 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163083 MockWrite("GET / HTTP/1.1\r\n"
3084 "Host: www.example.org\r\n"
3085 "Connection: keep-alive\r\n"
3086 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323087 };
3088
3089 // Respond with 5 kb of response body.
3090 std::string large_body_string("Unauthorized");
3091 large_body_string.append(5 * 1024, ' ');
3092 large_body_string.append("\r\n");
3093
3094 MockRead data_reads1[] = {
3095 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3096 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3097 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3098 // 5134 = 12 + 5 * 1024 + 2
3099 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063100 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323101
3102 // Lastly, the server responds with the actual content.
3103 MockRead("HTTP/1.1 200 OK\r\n"),
3104 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503105 MockRead("Content-Length: 5\r\n\r\n"),
3106 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323107 };
3108
[email protected]2d0a4f92011-05-05 16:38:463109 // An incorrect reconnect would cause this to be read.
3110 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063111 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463112 };
3113
Ryan Sleevib8d7ea02018-05-07 20:01:013114 StaticSocketDataProvider data1(data_reads1, data_writes1);
3115 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073116 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3117 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323118
[email protected]49639fa2011-12-20 23:22:413119 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323120
bnc691fda62016-08-12 00:43:163121 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203122 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013123 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323124
3125 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013126 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323127
bnc691fda62016-08-12 00:43:163128 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523129 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583130 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323131
[email protected]49639fa2011-12-20 23:22:413132 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323133
bnc691fda62016-08-12 00:43:163134 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013135 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323136
3137 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013138 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323139
bnc691fda62016-08-12 00:43:163140 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523141 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583142 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503143 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323144}
3145
3146// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313147// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013148TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313149 HttpRequestInfo request;
3150 request.method = "GET";
bncce36dca22015-04-21 22:11:233151 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103152 request.traffic_annotation =
3153 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313154
danakj1fd259a02016-04-16 03:17:093155 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273156
[email protected]11203f012009-11-12 23:02:313157 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233158 MockWrite(
3159 "GET / HTTP/1.1\r\n"
3160 "Host: www.example.org\r\n"
3161 "Connection: keep-alive\r\n\r\n"),
3162 // This simulates the seemingly successful write to a closed connection
3163 // if the bug is not fixed.
3164 MockWrite(
3165 "GET / HTTP/1.1\r\n"
3166 "Host: www.example.org\r\n"
3167 "Connection: keep-alive\r\n"
3168 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313169 };
3170
3171 MockRead data_reads1[] = {
3172 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3173 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3174 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3175 MockRead("Content-Length: 14\r\n\r\n"),
3176 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063177 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313178 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063179 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313180 };
3181
bnc691fda62016-08-12 00:43:163182 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313183 // be issuing -- the final header line contains the credentials.
3184 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233185 MockWrite(
3186 "GET / HTTP/1.1\r\n"
3187 "Host: www.example.org\r\n"
3188 "Connection: keep-alive\r\n"
3189 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313190 };
3191
3192 // Lastly, the server responds with the actual content.
3193 MockRead data_reads2[] = {
3194 MockRead("HTTP/1.1 200 OK\r\n"),
3195 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503196 MockRead("Content-Length: 5\r\n\r\n"),
3197 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313198 };
3199
Ryan Sleevib8d7ea02018-05-07 20:01:013200 StaticSocketDataProvider data1(data_reads1, data_writes1);
3201 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073202 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3203 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313204
[email protected]49639fa2011-12-20 23:22:413205 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313206
bnc691fda62016-08-12 00:43:163207 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203208 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013209 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313210
3211 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013212 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313213
bnc691fda62016-08-12 00:43:163214 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523215 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583216 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313217
[email protected]49639fa2011-12-20 23:22:413218 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313219
bnc691fda62016-08-12 00:43:163220 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013221 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313222
3223 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013224 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313225
bnc691fda62016-08-12 00:43:163226 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523227 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583228 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503229 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313230}
3231
[email protected]394816e92010-08-03 07:38:593232// Test the request-challenge-retry sequence for basic auth, over a connection
3233// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013234TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013235 HttpRequestInfo request;
3236 request.method = "GET";
bncce36dca22015-04-21 22:11:233237 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013238 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293239 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103240 request.traffic_annotation =
3241 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013242
3243 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593244 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493245 ProxyResolutionService::CreateFixedFromPacResult(
3246 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513247 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013248 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093249 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013250
3251 // Since we have proxy, should try to establish tunnel.
3252 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543253 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173254 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543255 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013256 };
3257
mmenkee71e15332015-10-07 16:39:543258 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013259 // connection.
3260 MockRead data_reads1[] = {
3261 // No credentials.
3262 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3263 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543264 };
ttuttle34f63b52015-03-05 04:33:013265
mmenkee71e15332015-10-07 16:39:543266 // Since the first connection couldn't be reused, need to establish another
3267 // once given credentials.
3268 MockWrite data_writes2[] = {
3269 // After calling trans->RestartWithAuth(), this is the request we should
3270 // be issuing -- the final header line contains the credentials.
3271 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173272 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543273 "Proxy-Connection: keep-alive\r\n"
3274 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3275
3276 MockWrite("GET / HTTP/1.1\r\n"
3277 "Host: www.example.org\r\n"
3278 "Connection: keep-alive\r\n\r\n"),
3279 };
3280
3281 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013282 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3283
3284 MockRead("HTTP/1.1 200 OK\r\n"),
3285 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3286 MockRead("Content-Length: 5\r\n\r\n"),
3287 MockRead(SYNCHRONOUS, "hello"),
3288 };
3289
Ryan Sleevib8d7ea02018-05-07 20:01:013290 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013291 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013292 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543293 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013294 SSLSocketDataProvider ssl(ASYNC, OK);
3295 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3296
3297 TestCompletionCallback callback1;
3298
bnc87dcefc2017-05-25 12:47:583299 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193300 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013301
3302 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013303 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013304
3305 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013306 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543307 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013308 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003309 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3310 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013311 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003312 entries, pos,
3313 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3314 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013315
3316 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523317 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013318 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523319 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013320 EXPECT_EQ(407, response->headers->response_code());
3321 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583322 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013323
3324 LoadTimingInfo load_timing_info;
3325 // CONNECT requests and responses are handled at the connect job level, so
3326 // the transaction does not yet have a connection.
3327 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3328
3329 TestCompletionCallback callback2;
3330
3331 rv =
3332 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013333 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013334
3335 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013336 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013337
3338 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523339 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013340
3341 EXPECT_TRUE(response->headers->IsKeepAlive());
3342 EXPECT_EQ(200, response->headers->response_code());
3343 EXPECT_EQ(5, response->headers->GetContentLength());
3344 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3345
Matt Menke96092e62019-10-18 04:09:333346 // Check that credentials were successfully cached, with the right target.
3347 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
3348 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:263349 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:333350 ASSERT_TRUE(entry);
3351 ASSERT_EQ(kFoo, entry->credentials().username());
3352 ASSERT_EQ(kBar, entry->credentials().password());
3353
ttuttle34f63b52015-03-05 04:33:013354 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583355 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013356
3357 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3358 TestLoadTimingNotReusedWithPac(load_timing_info,
3359 CONNECT_TIMING_HAS_SSL_TIMES);
3360
3361 trans.reset();
3362 session->CloseAllConnections();
3363}
3364
3365// Test the request-challenge-retry sequence for basic auth, over a connection
3366// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013367TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593368 HttpRequestInfo request;
3369 request.method = "GET";
bncce36dca22015-04-21 22:11:233370 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593371 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293372 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103373 request.traffic_annotation =
3374 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593375
[email protected]cb9bf6ca2011-01-28 13:15:273376 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593377 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493378 ProxyResolutionService::CreateFixedFromPacResult(
3379 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513380 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073381 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093382 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273383
[email protected]394816e92010-08-03 07:38:593384 // Since we have proxy, should try to establish tunnel.
3385 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543386 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173387 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543388 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113389 };
3390
mmenkee71e15332015-10-07 16:39:543391 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083392 // connection.
3393 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543394 // No credentials.
3395 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3396 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3397 MockRead("Proxy-Connection: close\r\n\r\n"),
3398 };
mmenkee0b5c882015-08-26 20:29:113399
mmenkee71e15332015-10-07 16:39:543400 MockWrite data_writes2[] = {
3401 // After calling trans->RestartWithAuth(), this is the request we should
3402 // be issuing -- the final header line contains the credentials.
3403 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173404 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543405 "Proxy-Connection: keep-alive\r\n"
3406 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083407
mmenkee71e15332015-10-07 16:39:543408 MockWrite("GET / HTTP/1.1\r\n"
3409 "Host: www.example.org\r\n"
3410 "Connection: keep-alive\r\n\r\n"),
3411 };
3412
3413 MockRead data_reads2[] = {
3414 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3415
3416 MockRead("HTTP/1.1 200 OK\r\n"),
3417 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3418 MockRead("Content-Length: 5\r\n\r\n"),
3419 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593420 };
3421
Ryan Sleevib8d7ea02018-05-07 20:01:013422 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073423 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013424 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543425 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063426 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073427 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593428
[email protected]49639fa2011-12-20 23:22:413429 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593430
bnc87dcefc2017-05-25 12:47:583431 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193432 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503433
[email protected]49639fa2011-12-20 23:22:413434 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013435 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593436
3437 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013438 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543439 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593440 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003441 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3442 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593443 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403444 entries, pos,
mikecirone8b85c432016-09-08 19:11:003445 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3446 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593447
3448 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523449 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013450 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523451 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593452 EXPECT_EQ(407, response->headers->response_code());
3453 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583454 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593455
[email protected]029c83b62013-01-24 05:28:203456 LoadTimingInfo load_timing_info;
3457 // CONNECT requests and responses are handled at the connect job level, so
3458 // the transaction does not yet have a connection.
3459 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3460
[email protected]49639fa2011-12-20 23:22:413461 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593462
[email protected]49639fa2011-12-20 23:22:413463 rv = trans->RestartWithAuth(
3464 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013465 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593466
3467 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013468 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593469
3470 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523471 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593472
3473 EXPECT_TRUE(response->headers->IsKeepAlive());
3474 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503475 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593476 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3477
3478 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583479 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503480
[email protected]029c83b62013-01-24 05:28:203481 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3482 TestLoadTimingNotReusedWithPac(load_timing_info,
3483 CONNECT_TIMING_HAS_SSL_TIMES);
3484
[email protected]0b0bf032010-09-21 18:08:503485 trans.reset();
[email protected]102e27c2011-02-23 01:01:313486 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:593487}
3488
[email protected]11203f012009-11-12 23:02:313489// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013490// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013491TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233492 // On the second pass, the body read of the auth challenge is synchronous, so
3493 // IsConnectedAndIdle returns false. The socket should still be drained and
3494 // reused. See http://crbug.com/544255.
3495 for (int i = 0; i < 2; ++i) {
3496 HttpRequestInfo request;
3497 request.method = "GET";
3498 request.url = GURL("https://www.example.org/");
3499 // Ensure that proxy authentication is attempted even
3500 // when the no authentication data flag is set.
3501 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103502 request.traffic_annotation =
3503 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013504
mmenked39192ee2015-12-09 00:57:233505 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593506 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493507 ProxyResolutionService::CreateFixed("myproxy:70",
3508 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233509 BoundTestNetLog log;
3510 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093511 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013512
bnc691fda62016-08-12 00:43:163513 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013514
mmenked39192ee2015-12-09 00:57:233515 // Since we have proxy, should try to establish tunnel.
3516 MockWrite data_writes1[] = {
3517 MockWrite(ASYNC, 0,
3518 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3519 "Host: www.example.org:443\r\n"
3520 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013521
bnc691fda62016-08-12 00:43:163522 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233523 // be issuing -- the final header line contains the credentials.
3524 MockWrite(ASYNC, 3,
3525 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3526 "Host: www.example.org:443\r\n"
3527 "Proxy-Connection: keep-alive\r\n"
3528 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3529 };
ttuttle34f63b52015-03-05 04:33:013530
mmenked39192ee2015-12-09 00:57:233531 // The proxy responds to the connect with a 407, using a persistent
3532 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3533 MockRead data_reads1[] = {
3534 // No credentials.
3535 MockRead(ASYNC, 1,
3536 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3537 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3538 "Proxy-Connection: keep-alive\r\n"
3539 "Content-Length: 10\r\n\r\n"),
3540 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013541
mmenked39192ee2015-12-09 00:57:233542 // Wrong credentials (wrong password).
3543 MockRead(ASYNC, 4,
3544 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3545 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3546 "Proxy-Connection: keep-alive\r\n"
3547 "Content-Length: 10\r\n\r\n"),
3548 // No response body because the test stops reading here.
3549 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3550 };
ttuttle34f63b52015-03-05 04:33:013551
Ryan Sleevib8d7ea02018-05-07 20:01:013552 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233553 data1.set_busy_before_sync_reads(true);
3554 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013555
mmenked39192ee2015-12-09 00:57:233556 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013557
bnc691fda62016-08-12 00:43:163558 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013559 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013560
Eric Roman79cc7552019-07-19 02:17:543561 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233562 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003563 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3564 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233565 ExpectLogContainsSomewhere(
3566 entries, pos,
mikecirone8b85c432016-09-08 19:11:003567 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3568 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013569
bnc691fda62016-08-12 00:43:163570 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233571 ASSERT_TRUE(response);
3572 ASSERT_TRUE(response->headers);
3573 EXPECT_TRUE(response->headers->IsKeepAlive());
3574 EXPECT_EQ(407, response->headers->response_code());
3575 EXPECT_EQ(10, response->headers->GetContentLength());
3576 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583577 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013578
mmenked39192ee2015-12-09 00:57:233579 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013580
mmenked39192ee2015-12-09 00:57:233581 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163582 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3583 callback2.callback());
robpercival214763f2016-07-01 23:27:013584 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013585
bnc691fda62016-08-12 00:43:163586 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233587 ASSERT_TRUE(response);
3588 ASSERT_TRUE(response->headers);
3589 EXPECT_TRUE(response->headers->IsKeepAlive());
3590 EXPECT_EQ(407, response->headers->response_code());
3591 EXPECT_EQ(10, response->headers->GetContentLength());
3592 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583593 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013594
mmenked39192ee2015-12-09 00:57:233595 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3596 // out of scope.
3597 session->CloseAllConnections();
3598 }
ttuttle34f63b52015-03-05 04:33:013599}
3600
3601// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3602// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013603TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233604 // On the second pass, the body read of the auth challenge is synchronous, so
3605 // IsConnectedAndIdle returns false. The socket should still be drained and
3606 // reused. See http://crbug.com/544255.
3607 for (int i = 0; i < 2; ++i) {
3608 HttpRequestInfo request;
3609 request.method = "GET";
3610 request.url = GURL("https://www.example.org/");
3611 // Ensure that proxy authentication is attempted even
3612 // when the no authentication data flag is set.
3613 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103614 request.traffic_annotation =
3615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233616
3617 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593618 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493619 ProxyResolutionService::CreateFixed("myproxy:70",
3620 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233621 BoundTestNetLog log;
3622 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093623 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233624
bnc691fda62016-08-12 00:43:163625 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233626
3627 // Since we have proxy, should try to establish tunnel.
3628 MockWrite data_writes1[] = {
3629 MockWrite(ASYNC, 0,
3630 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3631 "Host: www.example.org:443\r\n"
3632 "Proxy-Connection: keep-alive\r\n\r\n"),
3633
bnc691fda62016-08-12 00:43:163634 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233635 // be issuing -- the final header line contains the credentials.
3636 MockWrite(ASYNC, 3,
3637 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3638 "Host: www.example.org:443\r\n"
3639 "Proxy-Connection: keep-alive\r\n"
3640 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3641 };
3642
3643 // The proxy responds to the connect with a 407, using a persistent
3644 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3645 MockRead data_reads1[] = {
3646 // No credentials.
3647 MockRead(ASYNC, 1,
3648 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3649 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3650 "Content-Length: 10\r\n\r\n"),
3651 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3652
3653 // Wrong credentials (wrong password).
3654 MockRead(ASYNC, 4,
3655 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3656 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3657 "Content-Length: 10\r\n\r\n"),
3658 // No response body because the test stops reading here.
3659 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3660 };
3661
Ryan Sleevib8d7ea02018-05-07 20:01:013662 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233663 data1.set_busy_before_sync_reads(true);
3664 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3665
3666 TestCompletionCallback callback1;
3667
bnc691fda62016-08-12 00:43:163668 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013669 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233670
Eric Roman79cc7552019-07-19 02:17:543671 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233672 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003673 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3674 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233675 ExpectLogContainsSomewhere(
3676 entries, pos,
mikecirone8b85c432016-09-08 19:11:003677 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3678 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233679
bnc691fda62016-08-12 00:43:163680 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233681 ASSERT_TRUE(response);
3682 ASSERT_TRUE(response->headers);
3683 EXPECT_TRUE(response->headers->IsKeepAlive());
3684 EXPECT_EQ(407, response->headers->response_code());
3685 EXPECT_EQ(10, response->headers->GetContentLength());
3686 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583687 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503688 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233689
3690 TestCompletionCallback callback2;
3691
3692 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163693 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3694 callback2.callback());
robpercival214763f2016-07-01 23:27:013695 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233696
bnc691fda62016-08-12 00:43:163697 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233698 ASSERT_TRUE(response);
3699 ASSERT_TRUE(response->headers);
3700 EXPECT_TRUE(response->headers->IsKeepAlive());
3701 EXPECT_EQ(407, response->headers->response_code());
3702 EXPECT_EQ(10, response->headers->GetContentLength());
3703 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583704 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503705 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233706
3707 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3708 // out of scope.
3709 session->CloseAllConnections();
3710 }
3711}
3712
3713// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3714// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3715// the case the server sends extra data on the original socket, so it can't be
3716// reused.
bncd16676a2016-07-20 16:23:013717TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273718 HttpRequestInfo request;
3719 request.method = "GET";
bncce36dca22015-04-21 22:11:233720 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273721 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293722 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103723 request.traffic_annotation =
3724 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273725
[email protected]2d2697f92009-02-18 21:00:323726 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593727 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493728 ProxyResolutionService::CreateFixedFromPacResult(
3729 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513730 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073731 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093732 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323733
[email protected]2d2697f92009-02-18 21:00:323734 // Since we have proxy, should try to establish tunnel.
3735 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233736 MockWrite(ASYNC, 0,
3737 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173738 "Host: www.example.org:443\r\n"
3739 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233740 };
[email protected]2d2697f92009-02-18 21:00:323741
mmenked39192ee2015-12-09 00:57:233742 // The proxy responds to the connect with a 407, using a persistent, but sends
3743 // extra data, so the socket cannot be reused.
3744 MockRead data_reads1[] = {
3745 // No credentials.
3746 MockRead(ASYNC, 1,
3747 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3748 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3749 "Content-Length: 10\r\n\r\n"),
3750 MockRead(SYNCHRONOUS, 2, "0123456789"),
3751 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3752 };
3753
3754 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233755 // After calling trans->RestartWithAuth(), this is the request we should
3756 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233757 MockWrite(ASYNC, 0,
3758 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173759 "Host: www.example.org:443\r\n"
3760 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233761 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3762
3763 MockWrite(ASYNC, 2,
3764 "GET / HTTP/1.1\r\n"
3765 "Host: www.example.org\r\n"
3766 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323767 };
3768
mmenked39192ee2015-12-09 00:57:233769 MockRead data_reads2[] = {
3770 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323771
mmenked39192ee2015-12-09 00:57:233772 MockRead(ASYNC, 3,
3773 "HTTP/1.1 200 OK\r\n"
3774 "Content-Type: text/html; charset=iso-8859-1\r\n"
3775 "Content-Length: 5\r\n\r\n"),
3776 // No response body because the test stops reading here.
3777 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323778 };
3779
Ryan Sleevib8d7ea02018-05-07 20:01:013780 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233781 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073782 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013783 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233784 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3785 SSLSocketDataProvider ssl(ASYNC, OK);
3786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323787
[email protected]49639fa2011-12-20 23:22:413788 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323789
bnc87dcefc2017-05-25 12:47:583790 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193791 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323792
mmenked39192ee2015-12-09 00:57:233793 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013794 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233795
Eric Roman79cc7552019-07-19 02:17:543796 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393797 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003798 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3799 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393800 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403801 entries, pos,
mikecirone8b85c432016-09-08 19:11:003802 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3803 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323804
[email protected]1c773ea12009-04-28 19:58:423805 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243806 ASSERT_TRUE(response);
3807 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323808 EXPECT_TRUE(response->headers->IsKeepAlive());
3809 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423810 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583811 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323812
mmenked39192ee2015-12-09 00:57:233813 LoadTimingInfo load_timing_info;
3814 // CONNECT requests and responses are handled at the connect job level, so
3815 // the transaction does not yet have a connection.
3816 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3817
[email protected]49639fa2011-12-20 23:22:413818 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323819
mmenked39192ee2015-12-09 00:57:233820 rv =
3821 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013822 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323823
[email protected]2d2697f92009-02-18 21:00:323824 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233825 EXPECT_EQ(200, response->headers->response_code());
3826 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423827 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133828
mmenked39192ee2015-12-09 00:57:233829 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583830 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233831
3832 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3833 TestLoadTimingNotReusedWithPac(load_timing_info,
3834 CONNECT_TIMING_HAS_SSL_TIMES);
3835
3836 trans.reset();
[email protected]102e27c2011-02-23 01:01:313837 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323838}
3839
mmenkee71e15332015-10-07 16:39:543840// Test the case a proxy closes a socket while the challenge body is being
3841// drained.
bncd16676a2016-07-20 16:23:013842TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543843 HttpRequestInfo request;
3844 request.method = "GET";
3845 request.url = GURL("https://www.example.org/");
3846 // Ensure that proxy authentication is attempted even
3847 // when the no authentication data flag is set.
3848 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103849 request.traffic_annotation =
3850 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543851
3852 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493853 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3854 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093855 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543856
bnc691fda62016-08-12 00:43:163857 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543858
3859 // Since we have proxy, should try to establish tunnel.
3860 MockWrite data_writes1[] = {
3861 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173862 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543863 "Proxy-Connection: keep-alive\r\n\r\n"),
3864 };
3865
3866 // The proxy responds to the connect with a 407, using a persistent
3867 // connection.
3868 MockRead data_reads1[] = {
3869 // No credentials.
3870 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3871 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3872 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3873 // Server hands up in the middle of the body.
3874 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3875 };
3876
3877 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163878 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543879 // be issuing -- the final header line contains the credentials.
3880 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173881 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543882 "Proxy-Connection: keep-alive\r\n"
3883 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3884
3885 MockWrite("GET / HTTP/1.1\r\n"
3886 "Host: www.example.org\r\n"
3887 "Connection: keep-alive\r\n\r\n"),
3888 };
3889
3890 MockRead data_reads2[] = {
3891 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3892
3893 MockRead("HTTP/1.1 200 OK\r\n"),
3894 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3895 MockRead("Content-Length: 5\r\n\r\n"),
3896 MockRead(SYNCHRONOUS, "hello"),
3897 };
3898
Ryan Sleevib8d7ea02018-05-07 20:01:013899 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543900 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013901 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543902 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3903 SSLSocketDataProvider ssl(ASYNC, OK);
3904 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3905
3906 TestCompletionCallback callback;
3907
tfarina42834112016-09-22 13:38:203908 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013909 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543910
bnc691fda62016-08-12 00:43:163911 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543912 ASSERT_TRUE(response);
3913 ASSERT_TRUE(response->headers);
3914 EXPECT_TRUE(response->headers->IsKeepAlive());
3915 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583916 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543917
bnc691fda62016-08-12 00:43:163918 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013919 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543920
bnc691fda62016-08-12 00:43:163921 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543922 ASSERT_TRUE(response);
3923 ASSERT_TRUE(response->headers);
3924 EXPECT_TRUE(response->headers->IsKeepAlive());
3925 EXPECT_EQ(200, response->headers->response_code());
3926 std::string body;
bnc691fda62016-08-12 00:43:163927 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543928 EXPECT_EQ("hello", body);
3929}
3930
[email protected]a8e9b162009-03-12 00:06:443931// Test that we don't read the response body when we fail to establish a tunnel,
3932// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013933TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273934 HttpRequestInfo request;
3935 request.method = "GET";
bncce36dca22015-04-21 22:11:233936 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103937 request.traffic_annotation =
3938 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273939
[email protected]a8e9b162009-03-12 00:06:443940 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493941 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3942 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443943
danakj1fd259a02016-04-16 03:17:093944 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443945
bnc691fda62016-08-12 00:43:163946 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443947
[email protected]a8e9b162009-03-12 00:06:443948 // Since we have proxy, should try to establish tunnel.
3949 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173950 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3951 "Host: www.example.org:443\r\n"
3952 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443953 };
3954
3955 // The proxy responds to the connect with a 407.
3956 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243957 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3958 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3959 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233960 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243961 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443962 };
3963
Ryan Sleevib8d7ea02018-05-07 20:01:013964 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073965 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443966
[email protected]49639fa2011-12-20 23:22:413967 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443968
tfarina42834112016-09-22 13:38:203969 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013970 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:443971
3972 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013973 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:443974
bnc691fda62016-08-12 00:43:163975 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243976 ASSERT_TRUE(response);
3977 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443978 EXPECT_TRUE(response->headers->IsKeepAlive());
3979 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423980 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443981
3982 std::string response_data;
bnc691fda62016-08-12 00:43:163983 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:013984 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:183985
3986 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313987 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443988}
3989
Matt Menke96092e62019-10-18 04:09:333990// Test the no-tunnel HTTP auth case where proxy and server origins and realms
3991// are the same, but the user/passwords are different. Serves to verify
3992// credentials are correctly separated based on HttpAuth::Target.
3993TEST_F(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
3994 HttpRequestInfo request;
3995 request.method = "GET";
3996 request.url = GURL("http://myproxy:70/");
3997 request.traffic_annotation =
3998 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3999
4000 // Proxy matches request URL.
4001 session_deps_.proxy_resolution_service =
4002 ProxyResolutionService::CreateFixedFromPacResult(
4003 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4004 BoundTestNetLog log;
4005 session_deps_.net_log = log.bound().net_log();
4006 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4007
4008 MockWrite data_writes[] = {
4009 // Initial request gets a proxy auth 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\r\n"),
Matt Menkebe090422019-10-18 20:25:264013 // Retry with proxy auth credentials, which will result in a server auth
Matt Menke96092e62019-10-18 04:09:334014 // challenge.
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\r\n"),
Matt Menkebe090422019-10-18 20:25:264019 // Retry with proxy and server auth credentials, which gets a response.
Matt Menke96092e62019-10-18 04:09:334020 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4021 "Host: myproxy:70\r\n"
4022 "Proxy-Connection: keep-alive\r\n"
4023 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4024 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4025 // A second request should preemptively send the correct proxy and server
4026 // auth headers.
4027 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4028 "Host: myproxy:70\r\n"
4029 "Proxy-Connection: keep-alive\r\n"
4030 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4031 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4032 };
4033
4034 MockRead data_reads[] = {
4035 // Proxy auth challenge.
4036 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4037 "Proxy-Connection: keep-alive\r\n"
4038 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4039 "Content-Length: 0\r\n\r\n"),
4040 // Server auth challenge.
4041 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4042 "Proxy-Connection: keep-alive\r\n"
4043 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4044 "Content-Length: 0\r\n\r\n"),
4045 // Response.
4046 MockRead("HTTP/1.1 200 OK\r\n"
4047 "Proxy-Connection: keep-alive\r\n"
4048 "Content-Length: 5\r\n\r\n"
4049 "hello"),
4050 // Response to second request.
4051 MockRead("HTTP/1.1 200 OK\r\n"
4052 "Proxy-Connection: keep-alive\r\n"
4053 "Content-Length: 2\r\n\r\n"
4054 "hi"),
4055 };
4056
4057 StaticSocketDataProvider data(data_reads, data_writes);
4058 session_deps_.socket_factory->AddSocketDataProvider(&data);
4059
4060 TestCompletionCallback callback;
4061
4062 auto trans =
4063 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4064 int rv = trans->Start(&request, callback.callback(), log.bound());
4065 EXPECT_THAT(callback.GetResult(rv), IsOk());
4066 const HttpResponseInfo* response = trans->GetResponseInfo();
4067 ASSERT_TRUE(response);
4068 ASSERT_TRUE(response->headers);
4069 EXPECT_EQ(407, response->headers->response_code());
4070 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4071
4072 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4073 EXPECT_THAT(callback.GetResult(rv), IsOk());
4074 response = trans->GetResponseInfo();
4075 ASSERT_TRUE(response);
4076 EXPECT_EQ(401, response->headers->response_code());
4077 EXPECT_FALSE(response->auth_challenge->is_proxy);
4078 EXPECT_EQ("http://myproxy:70",
4079 response->auth_challenge->challenger.Serialize());
4080 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4081 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4082
4083 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4084 callback.callback());
4085 EXPECT_THAT(callback.GetResult(rv), IsOk());
4086 response = trans->GetResponseInfo();
4087 ASSERT_TRUE(response);
4088 EXPECT_EQ(200, response->headers->response_code());
4089 // The password prompt info should not be set.
4090 EXPECT_FALSE(response->auth_challenge.has_value());
4091
4092 std::string response_data;
4093 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4094 EXPECT_EQ("hello", response_data);
4095
4096 // Check that the credentials were cached correctly.
4097 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4098 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:264099 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334100 ASSERT_TRUE(entry);
4101 ASSERT_EQ(kFoo, entry->credentials().username());
4102 ASSERT_EQ(kBar, entry->credentials().password());
Matt Menkebe090422019-10-18 20:25:264103 entry = session->http_auth_cache()->Lookup(
4104 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4105 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334106 ASSERT_TRUE(entry);
4107 ASSERT_EQ(kFoo2, entry->credentials().username());
4108 ASSERT_EQ(kBar2, entry->credentials().password());
4109
4110 // Make another request, which should automatically send the correct proxy and
4111 // server auth credentials and get another response.
4112 trans =
4113 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4114 rv = trans->Start(&request, callback.callback(), log.bound());
4115 EXPECT_THAT(callback.GetResult(rv), IsOk());
4116 response = trans->GetResponseInfo();
4117 ASSERT_TRUE(response);
4118 EXPECT_EQ(200, response->headers->response_code());
4119 // The password prompt info should not be set.
4120 EXPECT_FALSE(response->auth_challenge.has_value());
4121
4122 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4123 EXPECT_EQ("hi", response_data);
4124
4125 trans.reset();
4126 session->CloseAllConnections();
4127}
4128
Matt Menkebe090422019-10-18 20:25:264129// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4130// are the same, but the user/passwords are different, and with different
4131// NetworkIsolationKeys. Sends one request with a NIK, response to both proxy
4132// and auth challenges, sends another request with another NIK, expecting only
4133// the proxy credentials to be cached, and thus sees only a server auth
4134// challenge. Then sends a request with the original NIK, expecting cached proxy
4135// and auth credentials that match the ones used in the first request.
4136//
4137// Serves to verify credentials are correctly separated based on
4138// HttpAuth::Target and NetworkIsolationKeys, but NetworkIsolationKey only
4139// affects server credentials, not proxy credentials.
4140TEST_F(HttpNetworkTransactionTest,
4141 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyNoTunnel) {
4142 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4143 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4144 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4145 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4146
4147 // This test would need to use a single socket without this option enabled.
4148 // Best to use this option when it would affect a test, as it will eventually
4149 // become the default behavior.
4150 base::test::ScopedFeatureList feature_list;
4151 feature_list.InitAndEnableFeature(
4152 features::kPartitionConnectionsByNetworkIsolationKey);
4153
4154 // Proxy matches request URL.
4155 session_deps_.proxy_resolution_service =
4156 ProxyResolutionService::CreateFixedFromPacResult(
4157 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4158 BoundTestNetLog log;
4159 session_deps_.net_log = log.bound().net_log();
4160 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4161 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4162
4163 MockWrite data_writes[] = {
4164 // Initial request gets a proxy auth challenge.
4165 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4166 "Host: myproxy:70\r\n"
4167 "Proxy-Connection: keep-alive\r\n\r\n"),
4168 // Retry with proxy auth credentials, which will result in a server auth
4169 // challenge.
4170 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4171 "Host: myproxy:70\r\n"
4172 "Proxy-Connection: keep-alive\r\n"
4173 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4174 // Retry with proxy and server auth credentials, which gets a response.
4175 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4176 "Host: myproxy:70\r\n"
4177 "Proxy-Connection: keep-alive\r\n"
4178 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4179 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4180 // Another request to the same server and using the same NIK should
4181 // preemptively send the correct cached proxy and server
4182 // auth headers.
4183 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4184 "Host: myproxy:70\r\n"
4185 "Proxy-Connection: keep-alive\r\n"
4186 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4187 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4188 };
4189
4190 MockRead data_reads[] = {
4191 // Proxy auth challenge.
4192 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4193 "Proxy-Connection: keep-alive\r\n"
4194 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4195 "Content-Length: 0\r\n\r\n"),
4196 // Server auth challenge.
4197 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4198 "Proxy-Connection: keep-alive\r\n"
4199 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4200 "Content-Length: 0\r\n\r\n"),
4201 // Response.
4202 MockRead("HTTP/1.1 200 OK\r\n"
4203 "Proxy-Connection: keep-alive\r\n"
4204 "Content-Length: 5\r\n\r\n"
4205 "hello"),
4206 // Response to second request.
4207 MockRead("HTTP/1.1 200 OK\r\n"
4208 "Proxy-Connection: keep-alive\r\n"
4209 "Content-Length: 2\r\n\r\n"
4210 "hi"),
4211 };
4212
4213 StaticSocketDataProvider data(data_reads, data_writes);
4214 session_deps_.socket_factory->AddSocketDataProvider(&data);
4215
4216 MockWrite data_writes2[] = {
4217 // Initial request using a different NetworkIsolationKey includes the
4218 // cached proxy credentials, but not server credentials.
4219 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4220 "Host: myproxy:70\r\n"
4221 "Proxy-Connection: keep-alive\r\n"
4222 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4223 // Retry with proxy and new server auth credentials, which gets a
4224 // response.
4225 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4226 "Host: myproxy:70\r\n"
4227 "Proxy-Connection: keep-alive\r\n"
4228 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4229 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4230 };
4231
4232 MockRead data_reads2[] = {
4233 // Server auth challenge.
4234 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4235 "Proxy-Connection: keep-alive\r\n"
4236 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4237 "Content-Length: 0\r\n\r\n"),
4238 // Response.
4239 MockRead("HTTP/1.1 200 OK\r\n"
4240 "Proxy-Connection: keep-alive\r\n"
4241 "Content-Length: 9\r\n\r\n"
4242 "greetings"),
4243 };
4244
4245 StaticSocketDataProvider data2(data_reads2, data_writes2);
4246 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4247
4248 TestCompletionCallback callback;
4249
4250 HttpRequestInfo request;
4251 request.method = "GET";
4252 request.url = GURL("http://myproxy:70/");
4253 request.traffic_annotation =
4254 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4255 request.network_isolation_key = kNetworkIsolationKey1;
4256
4257 auto trans =
4258 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4259 int rv = trans->Start(&request, callback.callback(), log.bound());
4260 EXPECT_THAT(callback.GetResult(rv), IsOk());
4261 const HttpResponseInfo* response = trans->GetResponseInfo();
4262 ASSERT_TRUE(response);
4263 ASSERT_TRUE(response->headers);
4264 EXPECT_EQ(407, response->headers->response_code());
4265 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4266
4267 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4268 EXPECT_THAT(callback.GetResult(rv), IsOk());
4269 response = trans->GetResponseInfo();
4270 ASSERT_TRUE(response);
4271 EXPECT_EQ(401, response->headers->response_code());
4272 EXPECT_FALSE(response->auth_challenge->is_proxy);
4273 EXPECT_EQ("http://myproxy:70",
4274 response->auth_challenge->challenger.Serialize());
4275 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4276 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4277
4278 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4279 callback.callback());
4280 EXPECT_THAT(callback.GetResult(rv), IsOk());
4281 response = trans->GetResponseInfo();
4282 ASSERT_TRUE(response);
4283 EXPECT_EQ(200, response->headers->response_code());
4284 // The password prompt info should not be set.
4285 EXPECT_FALSE(response->auth_challenge.has_value());
4286 std::string response_data;
4287 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4288 EXPECT_EQ("hello", response_data);
4289
4290 // Check that the proxy credentials were cached correctly. The should be
4291 // accessible with any NetworkIsolationKey.
4292 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4293 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4294 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4295 ASSERT_TRUE(entry);
4296 ASSERT_EQ(kFoo, entry->credentials().username());
4297 ASSERT_EQ(kBar, entry->credentials().password());
4298 EXPECT_EQ(entry,
4299 session->http_auth_cache()->Lookup(
4300 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4301 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4302
4303 // Check that the server credentials were cached correctly. The should be
4304 // accessible with only kNetworkIsolationKey1.
4305 entry = session->http_auth_cache()->Lookup(
4306 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4307 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4308 ASSERT_TRUE(entry);
4309 ASSERT_EQ(kFoo2, entry->credentials().username());
4310 ASSERT_EQ(kBar2, entry->credentials().password());
4311 // Looking up the server entry with another NetworkIsolationKey should fail.
4312 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4313 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4314 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4315
4316 // Make another request with a different NetworkIsolationKey. It should use
4317 // another socket, reuse the cached proxy credentials, but result in a server
4318 // auth challenge.
4319 request.network_isolation_key = kNetworkIsolationKey2;
4320 trans =
4321 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4322 rv = trans->Start(&request, callback.callback(), log.bound());
4323 EXPECT_THAT(callback.GetResult(rv), IsOk());
4324 response = trans->GetResponseInfo();
4325 ASSERT_TRUE(response);
4326 EXPECT_EQ(401, response->headers->response_code());
4327 EXPECT_FALSE(response->auth_challenge->is_proxy);
4328 EXPECT_EQ("http://myproxy:70",
4329 response->auth_challenge->challenger.Serialize());
4330 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4331 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4332
4333 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4334 callback.callback());
4335 EXPECT_THAT(callback.GetResult(rv), IsOk());
4336 response = trans->GetResponseInfo();
4337 ASSERT_TRUE(response);
4338 EXPECT_EQ(200, response->headers->response_code());
4339 // The password prompt info should not be set.
4340 EXPECT_FALSE(response->auth_challenge.has_value());
4341 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4342 EXPECT_EQ("greetings", response_data);
4343
4344 // Check that the proxy credentials are still cached.
4345 entry = session->http_auth_cache()->Lookup(
4346 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4347 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4348 ASSERT_TRUE(entry);
4349 ASSERT_EQ(kFoo, entry->credentials().username());
4350 ASSERT_EQ(kBar, entry->credentials().password());
4351 EXPECT_EQ(entry,
4352 session->http_auth_cache()->Lookup(
4353 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4354 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4355
4356 // Check that the correct server credentials are cached for each
4357 // NetworkIsolationKey.
4358 entry = session->http_auth_cache()->Lookup(
4359 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4360 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4361 ASSERT_TRUE(entry);
4362 ASSERT_EQ(kFoo2, entry->credentials().username());
4363 ASSERT_EQ(kBar2, entry->credentials().password());
4364 entry = session->http_auth_cache()->Lookup(
4365 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4366 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4367 ASSERT_TRUE(entry);
4368 ASSERT_EQ(kFoo3, entry->credentials().username());
4369 ASSERT_EQ(kBar3, entry->credentials().password());
4370
4371 // Make a request with the original NetworkIsolationKey. It should reuse the
4372 // first socket, and the proxy credentials sent on the first socket.
4373 request.network_isolation_key = kNetworkIsolationKey1;
4374 trans =
4375 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4376 rv = trans->Start(&request, callback.callback(), log.bound());
4377 EXPECT_THAT(callback.GetResult(rv), IsOk());
4378 response = trans->GetResponseInfo();
4379 ASSERT_TRUE(response);
4380 EXPECT_EQ(200, response->headers->response_code());
4381 // The password prompt info should not be set.
4382 EXPECT_FALSE(response->auth_challenge.has_value());
4383 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4384 EXPECT_EQ("hi", response_data);
4385
4386 trans.reset();
4387 session->CloseAllConnections();
4388}
4389
4390// Much like the test above, but uses tunnelled connections.
4391TEST_F(HttpNetworkTransactionTest,
4392 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyWithTunnel) {
4393 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4394 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4395 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4396 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4397
4398 // This test would need to use a single socket without this option enabled.
4399 // Best to use this option when it would affect a test, as it will eventually
4400 // become the default behavior.
4401 base::test::ScopedFeatureList feature_list;
4402 feature_list.InitAndEnableFeature(
4403 features::kPartitionConnectionsByNetworkIsolationKey);
4404
4405 // Proxy matches request URL.
4406 session_deps_.proxy_resolution_service =
4407 ProxyResolutionService::CreateFixedFromPacResult(
4408 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4409 BoundTestNetLog log;
4410 session_deps_.net_log = log.bound().net_log();
4411 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4412 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4413
4414 MockWrite data_writes[] = {
4415 // Initial tunnel request gets a proxy auth challenge.
4416 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4417 "Host: myproxy:70\r\n"
4418 "Proxy-Connection: keep-alive\r\n\r\n"),
4419 // Retry with proxy auth credentials, which will result in establishing a
4420 // tunnel.
4421 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4422 "Host: myproxy:70\r\n"
4423 "Proxy-Connection: keep-alive\r\n"
4424 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4425 // Request over the tunnel, which gets a server auth challenge.
4426 MockWrite("GET / HTTP/1.1\r\n"
4427 "Host: myproxy:70\r\n"
4428 "Connection: keep-alive\r\n\r\n"),
4429 // Retry with server auth credentials, which gets a response.
4430 MockWrite("GET / HTTP/1.1\r\n"
4431 "Host: myproxy:70\r\n"
4432 "Connection: keep-alive\r\n"
4433 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4434 // Another request to the same server and using the same NIK should
4435 // preemptively send the correct cached server
4436 // auth header. Since a tunnel was already established, the proxy headers
4437 // won't be sent again except when establishing another tunnel.
4438 MockWrite("GET / HTTP/1.1\r\n"
4439 "Host: myproxy:70\r\n"
4440 "Connection: keep-alive\r\n"
4441 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4442 };
4443
4444 MockRead data_reads[] = {
4445 // Proxy auth challenge.
4446 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4447 "Proxy-Connection: keep-alive\r\n"
4448 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4449 "Content-Length: 0\r\n\r\n"),
4450 // Tunnel success
4451 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4452 // Server auth challenge.
4453 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4454 "Connection: keep-alive\r\n"
4455 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4456 "Content-Length: 0\r\n\r\n"),
4457 // Response.
4458 MockRead("HTTP/1.1 200 OK\r\n"
4459 "Connection: keep-alive\r\n"
4460 "Content-Length: 5\r\n\r\n"
4461 "hello"),
4462 // Response to second request.
4463 MockRead("HTTP/1.1 200 OK\r\n"
4464 "Connection: keep-alive\r\n"
4465 "Content-Length: 2\r\n\r\n"
4466 "hi"),
4467 };
4468
4469 StaticSocketDataProvider data(data_reads, data_writes);
4470 session_deps_.socket_factory->AddSocketDataProvider(&data);
4471 // One for the proxy connection, one of the server connection.
4472 SSLSocketDataProvider ssl(ASYNC, OK);
4473 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4474 SSLSocketDataProvider ssl2(ASYNC, OK);
4475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4476
4477 MockWrite data_writes2[] = {
4478 // Initial request using a different NetworkIsolationKey includes the
4479 // cached proxy credentials when establishing a tunnel.
4480 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4481 "Host: myproxy:70\r\n"
4482 "Proxy-Connection: keep-alive\r\n"
4483 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4484 // Request over the tunnel, which gets a server auth challenge. Cached
4485 // credentials cannot be used, since the NIK is different.
4486 MockWrite("GET / HTTP/1.1\r\n"
4487 "Host: myproxy:70\r\n"
4488 "Connection: keep-alive\r\n\r\n"),
4489 // Retry with server auth credentials, which gets a response.
4490 MockWrite("GET / HTTP/1.1\r\n"
4491 "Host: myproxy:70\r\n"
4492 "Connection: keep-alive\r\n"
4493 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4494 };
4495
4496 MockRead data_reads2[] = {
4497 // Tunnel success
4498 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4499 // Server auth challenge.
4500 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4501 "Connection: keep-alive\r\n"
4502 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4503 "Content-Length: 0\r\n\r\n"),
4504 // Response.
4505 MockRead("HTTP/1.1 200 OK\r\n"
4506 "Connection: keep-alive\r\n"
4507 "Content-Length: 9\r\n\r\n"
4508 "greetings"),
4509 };
4510
4511 StaticSocketDataProvider data2(data_reads2, data_writes2);
4512 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4513 // One for the proxy connection, one of the server connection.
4514 SSLSocketDataProvider ssl3(ASYNC, OK);
4515 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
4516 SSLSocketDataProvider ssl4(ASYNC, OK);
4517 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
4518
4519 TestCompletionCallback callback;
4520
4521 HttpRequestInfo request;
4522 request.method = "GET";
4523 request.url = GURL("https://myproxy:70/");
4524 request.traffic_annotation =
4525 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4526 request.network_isolation_key = kNetworkIsolationKey1;
4527
4528 auto trans =
4529 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4530 int rv = trans->Start(&request, callback.callback(), log.bound());
4531 EXPECT_THAT(callback.GetResult(rv), IsOk());
4532 const HttpResponseInfo* response = trans->GetResponseInfo();
4533 ASSERT_TRUE(response);
4534 ASSERT_TRUE(response->headers);
4535 EXPECT_EQ(407, response->headers->response_code());
4536 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
4537
4538 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4539 EXPECT_THAT(callback.GetResult(rv), IsOk());
4540 response = trans->GetResponseInfo();
4541 ASSERT_TRUE(response);
4542 EXPECT_EQ(401, response->headers->response_code());
4543 EXPECT_FALSE(response->auth_challenge->is_proxy);
4544 EXPECT_EQ("https://myproxy:70",
4545 response->auth_challenge->challenger.Serialize());
4546 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4547 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4548
4549 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4550 callback.callback());
4551 EXPECT_THAT(callback.GetResult(rv), IsOk());
4552 response = trans->GetResponseInfo();
4553 ASSERT_TRUE(response);
4554 EXPECT_EQ(200, response->headers->response_code());
4555 // The password prompt info should not be set.
4556 EXPECT_FALSE(response->auth_challenge.has_value());
4557 std::string response_data;
4558 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4559 EXPECT_EQ("hello", response_data);
4560
4561 // Check that the proxy credentials were cached correctly. The should be
4562 // accessible with any NetworkIsolationKey.
4563 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4564 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4565 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4566 ASSERT_TRUE(entry);
4567 ASSERT_EQ(kFoo, entry->credentials().username());
4568 ASSERT_EQ(kBar, entry->credentials().password());
4569 EXPECT_EQ(entry,
4570 session->http_auth_cache()->Lookup(
4571 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4572 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4573
4574 // Check that the server credentials were cached correctly. The should be
4575 // accessible with only kNetworkIsolationKey1.
4576 entry = session->http_auth_cache()->Lookup(
4577 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4578 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4579 ASSERT_TRUE(entry);
4580 ASSERT_EQ(kFoo2, entry->credentials().username());
4581 ASSERT_EQ(kBar2, entry->credentials().password());
4582 // Looking up the server entry with another NetworkIsolationKey should fail.
4583 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4584 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4585 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4586
4587 // Make another request with a different NetworkIsolationKey. It should use
4588 // another socket, reuse the cached proxy credentials, but result in a server
4589 // auth challenge.
4590 request.network_isolation_key = kNetworkIsolationKey2;
4591 trans =
4592 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4593 rv = trans->Start(&request, callback.callback(), log.bound());
4594 EXPECT_THAT(callback.GetResult(rv), IsOk());
4595 response = trans->GetResponseInfo();
4596 ASSERT_TRUE(response);
4597 EXPECT_EQ(401, response->headers->response_code());
4598 EXPECT_FALSE(response->auth_challenge->is_proxy);
4599 EXPECT_EQ("https://myproxy:70",
4600 response->auth_challenge->challenger.Serialize());
4601 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4602 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4603
4604 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4605 callback.callback());
4606 EXPECT_THAT(callback.GetResult(rv), IsOk());
4607 response = trans->GetResponseInfo();
4608 ASSERT_TRUE(response);
4609 EXPECT_EQ(200, response->headers->response_code());
4610 // The password prompt info should not be set.
4611 EXPECT_FALSE(response->auth_challenge.has_value());
4612 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4613 EXPECT_EQ("greetings", response_data);
4614
4615 // Check that the proxy credentials are still cached.
4616 entry = session->http_auth_cache()->Lookup(
4617 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4618 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4619 ASSERT_TRUE(entry);
4620 ASSERT_EQ(kFoo, entry->credentials().username());
4621 ASSERT_EQ(kBar, entry->credentials().password());
4622 EXPECT_EQ(entry,
4623 session->http_auth_cache()->Lookup(
4624 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4625 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4626
4627 // Check that the correct server credentials are cached for each
4628 // NetworkIsolationKey.
4629 entry = session->http_auth_cache()->Lookup(
4630 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4631 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4632 ASSERT_TRUE(entry);
4633 ASSERT_EQ(kFoo2, entry->credentials().username());
4634 ASSERT_EQ(kBar2, entry->credentials().password());
4635 entry = session->http_auth_cache()->Lookup(
4636 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4637 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4638 ASSERT_TRUE(entry);
4639 ASSERT_EQ(kFoo3, entry->credentials().username());
4640 ASSERT_EQ(kBar3, entry->credentials().password());
4641
4642 // Make a request with the original NetworkIsolationKey. It should reuse the
4643 // first socket, and the proxy credentials sent on the first socket.
4644 request.network_isolation_key = kNetworkIsolationKey1;
4645 trans =
4646 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4647 rv = trans->Start(&request, callback.callback(), log.bound());
4648 EXPECT_THAT(callback.GetResult(rv), IsOk());
4649 response = trans->GetResponseInfo();
4650 ASSERT_TRUE(response);
4651 EXPECT_EQ(200, response->headers->response_code());
4652 // The password prompt info should not be set.
4653 EXPECT_FALSE(response->auth_challenge.has_value());
4654 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4655 EXPECT_EQ("hi", response_data);
4656
4657 trans.reset();
4658 session->CloseAllConnections();
4659}
4660
ttuttle7933c112015-01-06 00:55:244661// Test that we don't pass extraneous headers from the proxy's response to the
4662// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014663TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244664 HttpRequestInfo request;
4665 request.method = "GET";
bncce36dca22015-04-21 22:11:234666 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104667 request.traffic_annotation =
4668 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244669
4670 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:494671 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4672 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244673
danakj1fd259a02016-04-16 03:17:094674 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244675
bnc691fda62016-08-12 00:43:164676 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244677
4678 // Since we have proxy, should try to establish tunnel.
4679 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174680 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4681 "Host: www.example.org:443\r\n"
4682 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244683 };
4684
4685 // The proxy responds to the connect with a 407.
4686 MockRead data_reads[] = {
4687 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4688 MockRead("X-Foo: bar\r\n"),
4689 MockRead("Set-Cookie: foo=bar\r\n"),
4690 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4691 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234692 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244693 };
4694
Ryan Sleevib8d7ea02018-05-07 20:01:014695 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244696 session_deps_.socket_factory->AddSocketDataProvider(&data);
4697
4698 TestCompletionCallback callback;
4699
tfarina42834112016-09-22 13:38:204700 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014701 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244702
4703 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014704 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244705
bnc691fda62016-08-12 00:43:164706 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244707 ASSERT_TRUE(response);
4708 ASSERT_TRUE(response->headers);
4709 EXPECT_TRUE(response->headers->IsKeepAlive());
4710 EXPECT_EQ(407, response->headers->response_code());
4711 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4712 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4713 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4714
4715 std::string response_data;
bnc691fda62016-08-12 00:43:164716 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014717 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244718
4719 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4720 session->CloseAllConnections();
4721}
4722
[email protected]8fdbcd22010-05-05 02:54:524723// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4724// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014725TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524726 HttpRequestInfo request;
4727 request.method = "GET";
bncce36dca22015-04-21 22:11:234728 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104729 request.traffic_annotation =
4730 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524731
[email protected]cb9bf6ca2011-01-28 13:15:274732 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094733 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164734 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274735
[email protected]8fdbcd22010-05-05 02:54:524736 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234737 MockWrite(
4738 "GET / HTTP/1.1\r\n"
4739 "Host: www.example.org\r\n"
4740 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524741 };
4742
4743 MockRead data_reads1[] = {
4744 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4745 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4746 // Large content-length -- won't matter, as connection will be reset.
4747 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064748 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524749 };
4750
Ryan Sleevib8d7ea02018-05-07 20:01:014751 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074752 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524753
[email protected]49639fa2011-12-20 23:22:414754 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524755
tfarina42834112016-09-22 13:38:204756 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014757 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524758
4759 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014760 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524761}
4762
[email protected]7a67a8152010-11-05 18:31:104763// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4764// through a non-authenticating proxy. The request should fail with
4765// ERR_UNEXPECTED_PROXY_AUTH.
4766// Note that it is impossible to detect if an HTTP server returns a 407 through
4767// a non-authenticating proxy - there is nothing to indicate whether the
4768// response came from the proxy or the server, so it is treated as if the proxy
4769// issued the challenge.
bncd16676a2016-07-20 16:23:014770TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274771 HttpRequestInfo request;
4772 request.method = "GET";
bncce36dca22015-04-21 22:11:234773 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104774 request.traffic_annotation =
4775 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274776
Ramin Halavatica8d5252018-03-12 05:33:494777 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4778 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514779 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074780 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094781 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104782
[email protected]7a67a8152010-11-05 18:31:104783 // Since we have proxy, should try to establish tunnel.
4784 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174785 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4786 "Host: www.example.org:443\r\n"
4787 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104788
rsleevidb16bb02015-11-12 23:47:174789 MockWrite("GET / HTTP/1.1\r\n"
4790 "Host: www.example.org\r\n"
4791 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104792 };
4793
4794 MockRead data_reads1[] = {
4795 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4796
4797 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4798 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4799 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064800 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104801 };
4802
Ryan Sleevib8d7ea02018-05-07 20:01:014803 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074804 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064805 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074806 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104807
[email protected]49639fa2011-12-20 23:22:414808 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104809
bnc691fda62016-08-12 00:43:164810 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104811
bnc691fda62016-08-12 00:43:164812 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014813 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104814
4815 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014816 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544817 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104818 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004819 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4820 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104821 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404822 entries, pos,
mikecirone8b85c432016-09-08 19:11:004823 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4824 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104825}
[email protected]2df19bb2010-08-25 20:13:464826
mmenke2a1781d2015-10-07 19:25:334827// Test a proxy auth scheme that allows default credentials and a proxy server
4828// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014829TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334830 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4831 HttpRequestInfo request;
4832 request.method = "GET";
4833 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104834 request.traffic_annotation =
4835 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334836
4837 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594838 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494839 ProxyResolutionService::CreateFixedFromPacResult(
4840 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334841
Jeremy Roman0579ed62017-08-29 15:56:194842 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334843 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194844 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334845 mock_handler->set_allows_default_credentials(true);
4846 auth_handler_factory->AddMockHandler(mock_handler.release(),
4847 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484848 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334849
4850 // Add NetLog just so can verify load timing information gets a NetLog ID.
4851 NetLog net_log;
4852 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094853 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334854
4855 // Since we have proxy, should try to establish tunnel.
4856 MockWrite data_writes1[] = {
4857 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174858 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334859 "Proxy-Connection: keep-alive\r\n\r\n"),
4860 };
4861
4862 // The proxy responds to the connect with a 407, using a non-persistent
4863 // connection.
4864 MockRead data_reads1[] = {
4865 // No credentials.
4866 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4867 MockRead("Proxy-Authenticate: Mock\r\n"),
4868 MockRead("Proxy-Connection: close\r\n\r\n"),
4869 };
4870
4871 // Since the first connection couldn't be reused, need to establish another
4872 // once given credentials.
4873 MockWrite data_writes2[] = {
4874 // After calling trans->RestartWithAuth(), this is the request we should
4875 // be issuing -- the final header line contains the credentials.
4876 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174877 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334878 "Proxy-Connection: keep-alive\r\n"
4879 "Proxy-Authorization: auth_token\r\n\r\n"),
4880
4881 MockWrite("GET / HTTP/1.1\r\n"
4882 "Host: www.example.org\r\n"
4883 "Connection: keep-alive\r\n\r\n"),
4884 };
4885
4886 MockRead data_reads2[] = {
4887 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4888
4889 MockRead("HTTP/1.1 200 OK\r\n"),
4890 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4891 MockRead("Content-Length: 5\r\n\r\n"),
4892 MockRead(SYNCHRONOUS, "hello"),
4893 };
4894
Ryan Sleevib8d7ea02018-05-07 20:01:014895 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334896 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014897 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334898 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4899 SSLSocketDataProvider ssl(ASYNC, OK);
4900 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4901
bnc87dcefc2017-05-25 12:47:584902 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194903 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334904
4905 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204906 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014907 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334908
4909 const HttpResponseInfo* response = trans->GetResponseInfo();
4910 ASSERT_TRUE(response);
4911 ASSERT_TRUE(response->headers);
4912 EXPECT_FALSE(response->headers->IsKeepAlive());
4913 EXPECT_EQ(407, response->headers->response_code());
4914 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4915 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584916 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334917
4918 LoadTimingInfo load_timing_info;
4919 // CONNECT requests and responses are handled at the connect job level, so
4920 // the transaction does not yet have a connection.
4921 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4922
4923 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014924 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334925 response = trans->GetResponseInfo();
4926 ASSERT_TRUE(response);
4927 ASSERT_TRUE(response->headers);
4928 EXPECT_TRUE(response->headers->IsKeepAlive());
4929 EXPECT_EQ(200, response->headers->response_code());
4930 EXPECT_EQ(5, response->headers->GetContentLength());
4931 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4932
4933 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584934 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334935
4936 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4937 TestLoadTimingNotReusedWithPac(load_timing_info,
4938 CONNECT_TIMING_HAS_SSL_TIMES);
4939
4940 trans.reset();
4941 session->CloseAllConnections();
4942}
4943
4944// Test a proxy auth scheme that allows default credentials and a proxy server
4945// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014946TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334947 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4948 HttpRequestInfo request;
4949 request.method = "GET";
4950 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104951 request.traffic_annotation =
4952 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334953
4954 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594955 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494956 ProxyResolutionService::CreateFixedFromPacResult(
4957 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334958
Jeremy Roman0579ed62017-08-29 15:56:194959 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334960 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194961 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334962 mock_handler->set_allows_default_credentials(true);
4963 auth_handler_factory->AddMockHandler(mock_handler.release(),
4964 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484965 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334966
4967 // Add NetLog just so can verify load timing information gets a NetLog ID.
4968 NetLog net_log;
4969 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094970 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334971
4972 // Should try to establish tunnel.
4973 MockWrite data_writes1[] = {
4974 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174975 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334976 "Proxy-Connection: keep-alive\r\n\r\n"),
4977
4978 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174979 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334980 "Proxy-Connection: keep-alive\r\n"
4981 "Proxy-Authorization: auth_token\r\n\r\n"),
4982 };
4983
4984 // The proxy responds to the connect with a 407, using a non-persistent
4985 // connection.
4986 MockRead data_reads1[] = {
4987 // No credentials.
4988 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4989 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4990 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4991 };
4992
4993 // Since the first connection was closed, need to establish another once given
4994 // credentials.
4995 MockWrite data_writes2[] = {
4996 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174997 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334998 "Proxy-Connection: keep-alive\r\n"
4999 "Proxy-Authorization: auth_token\r\n\r\n"),
5000
5001 MockWrite("GET / HTTP/1.1\r\n"
5002 "Host: www.example.org\r\n"
5003 "Connection: keep-alive\r\n\r\n"),
5004 };
5005
5006 MockRead data_reads2[] = {
5007 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5008
5009 MockRead("HTTP/1.1 200 OK\r\n"),
5010 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5011 MockRead("Content-Length: 5\r\n\r\n"),
5012 MockRead(SYNCHRONOUS, "hello"),
5013 };
5014
Ryan Sleevib8d7ea02018-05-07 20:01:015015 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335016 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015017 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335018 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5019 SSLSocketDataProvider ssl(ASYNC, OK);
5020 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5021
bnc87dcefc2017-05-25 12:47:585022 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195023 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335024
5025 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205026 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015027 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335028
5029 const HttpResponseInfo* response = trans->GetResponseInfo();
5030 ASSERT_TRUE(response);
5031 ASSERT_TRUE(response->headers);
5032 EXPECT_TRUE(response->headers->IsKeepAlive());
5033 EXPECT_EQ(407, response->headers->response_code());
5034 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5035 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585036 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335037
5038 LoadTimingInfo load_timing_info;
5039 // CONNECT requests and responses are handled at the connect job level, so
5040 // the transaction does not yet have a connection.
5041 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5042
5043 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015044 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335045
5046 response = trans->GetResponseInfo();
5047 ASSERT_TRUE(response);
5048 ASSERT_TRUE(response->headers);
5049 EXPECT_TRUE(response->headers->IsKeepAlive());
5050 EXPECT_EQ(200, response->headers->response_code());
5051 EXPECT_EQ(5, response->headers->GetContentLength());
5052 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5053
5054 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585055 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335056
5057 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5058 TestLoadTimingNotReusedWithPac(load_timing_info,
5059 CONNECT_TIMING_HAS_SSL_TIMES);
5060
5061 trans.reset();
5062 session->CloseAllConnections();
5063}
5064
5065// Test a proxy auth scheme that allows default credentials and a proxy server
5066// that hangs up when credentials are initially sent, and hangs up again when
5067// they are retried.
bncd16676a2016-07-20 16:23:015068TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335069 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
5070 HttpRequestInfo request;
5071 request.method = "GET";
5072 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105073 request.traffic_annotation =
5074 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335075
5076 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595077 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495078 ProxyResolutionService::CreateFixedFromPacResult(
5079 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335080
Jeremy Roman0579ed62017-08-29 15:56:195081 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335082 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195083 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335084 mock_handler->set_allows_default_credentials(true);
5085 auth_handler_factory->AddMockHandler(mock_handler.release(),
5086 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485087 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335088
5089 // Add NetLog just so can verify load timing information gets a NetLog ID.
5090 NetLog net_log;
5091 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:095092 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335093
5094 // Should try to establish tunnel.
5095 MockWrite data_writes1[] = {
5096 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175097 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335098 "Proxy-Connection: keep-alive\r\n\r\n"),
5099
5100 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175101 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335102 "Proxy-Connection: keep-alive\r\n"
5103 "Proxy-Authorization: auth_token\r\n\r\n"),
5104 };
5105
5106 // The proxy responds to the connect with a 407, and then hangs up after the
5107 // second request is sent.
5108 MockRead data_reads1[] = {
5109 // No credentials.
5110 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5111 MockRead("Content-Length: 0\r\n"),
5112 MockRead("Proxy-Connection: keep-alive\r\n"),
5113 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5114 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5115 };
5116
5117 // HttpNetworkTransaction sees a reused connection that was closed with
5118 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
5119 // request.
5120 MockWrite data_writes2[] = {
5121 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175122 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335123 "Proxy-Connection: keep-alive\r\n\r\n"),
5124 };
5125
5126 // The proxy, having had more than enough of us, just hangs up.
5127 MockRead data_reads2[] = {
5128 // No credentials.
5129 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5130 };
5131
Ryan Sleevib8d7ea02018-05-07 20:01:015132 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335133 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015134 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335135 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5136
bnc87dcefc2017-05-25 12:47:585137 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195138 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335139
5140 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205141 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015142 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335143
5144 const HttpResponseInfo* response = trans->GetResponseInfo();
5145 ASSERT_TRUE(response);
5146 ASSERT_TRUE(response->headers);
5147 EXPECT_TRUE(response->headers->IsKeepAlive());
5148 EXPECT_EQ(407, response->headers->response_code());
5149 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5150 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585151 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335152
5153 LoadTimingInfo load_timing_info;
5154 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5155
5156 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015157 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:335158
5159 trans.reset();
5160 session->CloseAllConnections();
5161}
5162
Asanka Herathbc3f8f62018-11-16 23:08:305163// This test exercises an odd edge case where the proxy closes the connection
5164// after the authentication handshake is complete. Presumably this technique is
5165// used in lieu of returning a 403 or 5xx status code when the authentication
5166// succeeds, but the user is not authorized to connect to the destination
5167// server. There's no standard for what a proxy should do to indicate a blocked
5168// site.
5169TEST_F(HttpNetworkTransactionTest,
5170 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
5171 HttpRequestInfo request;
5172 request.method = "GET";
5173 request.url = GURL("https://www.example.org/");
5174 request.traffic_annotation =
5175 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5176
5177 // Configure against proxy server "myproxy:70".
5178 session_deps_.proxy_resolution_service =
5179 ProxyResolutionService::CreateFixedFromPacResult(
5180 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5181
Asanka Herathbc3f8f62018-11-16 23:08:305182 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5183 auth_handler_factory->set_do_init_from_challenge(true);
5184
5185 // Create two mock AuthHandlers. This is because the transaction gets retried
5186 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
5187 // was a real network error.
5188 //
5189 // The handlers support both default and explicit credentials. The retry
5190 // mentioned above should be able to reuse the default identity. Thus there
5191 // should never be a need to prompt for explicit credentials.
5192 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5193 mock_handler->set_allows_default_credentials(true);
5194 mock_handler->set_allows_explicit_credentials(true);
5195 mock_handler->set_connection_based(true);
5196 auth_handler_factory->AddMockHandler(mock_handler.release(),
5197 HttpAuth::AUTH_PROXY);
5198 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5199 mock_handler->set_allows_default_credentials(true);
5200 mock_handler->set_allows_explicit_credentials(true);
5201 mock_handler->set_connection_based(true);
5202 auth_handler_factory->AddMockHandler(mock_handler.release(),
5203 HttpAuth::AUTH_PROXY);
5204 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5205
5206 NetLog net_log;
5207 session_deps_.net_log = &net_log;
5208 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5209
5210 // Data for both sockets.
5211 //
5212 // Writes are for the tunnel establishment attempts and the
5213 // authentication handshake.
5214 MockWrite data_writes1[] = {
5215 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5216 "Host: www.example.org:443\r\n"
5217 "Proxy-Connection: keep-alive\r\n\r\n"),
5218
5219 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5220 "Host: www.example.org:443\r\n"
5221 "Proxy-Connection: keep-alive\r\n"
5222 "Proxy-Authorization: auth_token\r\n\r\n"),
5223
5224 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5225 "Host: www.example.org:443\r\n"
5226 "Proxy-Connection: keep-alive\r\n"
5227 "Proxy-Authorization: auth_token\r\n\r\n"),
5228 };
5229
5230 // The server side of the authentication handshake. Note that the response to
5231 // the final CONNECT request is ERR_CONNECTION_CLOSED.
5232 MockRead data_reads1[] = {
5233 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5234 MockRead("Content-Length: 0\r\n"),
5235 MockRead("Proxy-Connection: keep-alive\r\n"),
5236 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5237
5238 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5239 MockRead("Content-Length: 0\r\n"),
5240 MockRead("Proxy-Connection: keep-alive\r\n"),
5241 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
5242
5243 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5244 };
5245
5246 StaticSocketDataProvider data1(data_reads1, data_writes1);
5247 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5248
5249 // The second socket is for the reconnection attempt. Data is identical to the
5250 // first attempt.
5251 StaticSocketDataProvider data2(data_reads1, data_writes1);
5252 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5253
5254 auto trans =
5255 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5256
5257 TestCompletionCallback callback;
5258 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5259
5260 // Two rounds per handshake. After one retry, the error is propagated up the
5261 // stack.
5262 for (int i = 0; i < 4; ++i) {
5263 EXPECT_THAT(callback.GetResult(rv), IsOk());
5264
5265 const HttpResponseInfo* response = trans->GetResponseInfo();
5266 ASSERT_TRUE(response);
5267 ASSERT_TRUE(response->headers);
5268 EXPECT_EQ(407, response->headers->response_code());
5269 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
5270
5271 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5272 }
5273
5274 // One shall be the number thou shalt retry, and the number of the retrying
5275 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
5276 // that thou then proceed to one. Three is right out. Once the number one,
5277 // being the first number, be reached, then lobbest thou thy
5278 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
5279 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
5280
5281 trans.reset();
5282 session->CloseAllConnections();
5283}
5284
mmenke2a1781d2015-10-07 19:25:335285// Test a proxy auth scheme that allows default credentials and a proxy server
5286// that hangs up when credentials are initially sent, and sends a challenge
5287// again they are retried.
bncd16676a2016-07-20 16:23:015288TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335289 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
5290 HttpRequestInfo request;
5291 request.method = "GET";
5292 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105293 request.traffic_annotation =
5294 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335295
5296 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595297 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495298 ProxyResolutionService::CreateFixedFromPacResult(
5299 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335300
Jeremy Roman0579ed62017-08-29 15:56:195301 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335302 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195303 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335304 mock_handler->set_allows_default_credentials(true);
5305 auth_handler_factory->AddMockHandler(mock_handler.release(),
5306 HttpAuth::AUTH_PROXY);
5307 // Add another handler for the second challenge. It supports default
5308 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195309 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335310 mock_handler->set_allows_default_credentials(true);
5311 auth_handler_factory->AddMockHandler(mock_handler.release(),
5312 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485313 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335314
5315 // Add NetLog just so can verify load timing information gets a NetLog ID.
5316 NetLog net_log;
5317 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:095318 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335319
5320 // Should try to establish tunnel.
5321 MockWrite data_writes1[] = {
5322 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175323 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335324 "Proxy-Connection: keep-alive\r\n\r\n"),
5325 };
5326
5327 // The proxy responds to the connect with a 407, using a non-persistent
5328 // connection.
5329 MockRead data_reads1[] = {
5330 // No credentials.
5331 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5332 MockRead("Proxy-Authenticate: Mock\r\n"),
5333 MockRead("Proxy-Connection: close\r\n\r\n"),
5334 };
5335
5336 // Since the first connection was closed, need to establish another once given
5337 // credentials.
5338 MockWrite data_writes2[] = {
5339 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175340 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335341 "Proxy-Connection: keep-alive\r\n"
5342 "Proxy-Authorization: auth_token\r\n\r\n"),
5343 };
5344
5345 MockRead data_reads2[] = {
5346 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5347 MockRead("Proxy-Authenticate: Mock\r\n"),
5348 MockRead("Proxy-Connection: close\r\n\r\n"),
5349 };
5350
Ryan Sleevib8d7ea02018-05-07 20:01:015351 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335352 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015353 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335354 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5355 SSLSocketDataProvider ssl(ASYNC, OK);
5356 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5357
bnc87dcefc2017-05-25 12:47:585358 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195359 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335360
5361 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205362 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015363 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335364
5365 const HttpResponseInfo* response = trans->GetResponseInfo();
5366 ASSERT_TRUE(response);
5367 ASSERT_TRUE(response->headers);
5368 EXPECT_EQ(407, response->headers->response_code());
5369 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5370 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585371 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335372
5373 LoadTimingInfo load_timing_info;
5374 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5375
5376 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015377 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335378 response = trans->GetResponseInfo();
5379 ASSERT_TRUE(response);
5380 ASSERT_TRUE(response->headers);
5381 EXPECT_EQ(407, response->headers->response_code());
5382 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585383 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335384
5385 trans.reset();
5386 session->CloseAllConnections();
5387}
5388
asankae2257db2016-10-11 22:03:165389// A more nuanced test than GenerateAuthToken test which asserts that
5390// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
5391// unnecessarily invalidated, and that if the server co-operates, the
5392// authentication handshake can continue with the same scheme but with a
5393// different identity.
5394TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
5395 HttpRequestInfo request;
5396 request.method = "GET";
5397 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105398 request.traffic_annotation =
5399 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:165400
Jeremy Roman0579ed62017-08-29 15:56:195401 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:165402 auth_handler_factory->set_do_init_from_challenge(true);
5403
5404 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:195405 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165406 mock_handler->set_allows_default_credentials(true);
5407 mock_handler->set_allows_explicit_credentials(true);
5408 mock_handler->set_connection_based(true);
5409 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
5410 auth_handler_factory->AddMockHandler(mock_handler.release(),
5411 HttpAuth::AUTH_SERVER);
5412
5413 // Add another handler for the second challenge. It supports default
5414 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195415 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165416 mock_handler->set_allows_default_credentials(true);
5417 mock_handler->set_allows_explicit_credentials(true);
5418 mock_handler->set_connection_based(true);
5419 auth_handler_factory->AddMockHandler(mock_handler.release(),
5420 HttpAuth::AUTH_SERVER);
5421 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5422
5423 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5424
5425 MockWrite data_writes1[] = {
5426 MockWrite("GET / HTTP/1.1\r\n"
5427 "Host: www.example.org\r\n"
5428 "Connection: keep-alive\r\n\r\n"),
5429 };
5430
5431 MockRead data_reads1[] = {
5432 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5433 "WWW-Authenticate: Mock\r\n"
5434 "Connection: keep-alive\r\n\r\n"),
5435 };
5436
5437 // Identical to data_writes1[]. The AuthHandler encounters a
5438 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
5439 // transaction procceds without an authorization header.
5440 MockWrite data_writes2[] = {
5441 MockWrite("GET / HTTP/1.1\r\n"
5442 "Host: www.example.org\r\n"
5443 "Connection: keep-alive\r\n\r\n"),
5444 };
5445
5446 MockRead data_reads2[] = {
5447 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5448 "WWW-Authenticate: Mock\r\n"
5449 "Connection: keep-alive\r\n\r\n"),
5450 };
5451
5452 MockWrite data_writes3[] = {
5453 MockWrite("GET / HTTP/1.1\r\n"
5454 "Host: www.example.org\r\n"
5455 "Connection: keep-alive\r\n"
5456 "Authorization: auth_token\r\n\r\n"),
5457 };
5458
5459 MockRead data_reads3[] = {
5460 MockRead("HTTP/1.1 200 OK\r\n"
5461 "Content-Length: 5\r\n"
5462 "Content-Type: text/plain\r\n"
5463 "Connection: keep-alive\r\n\r\n"
5464 "Hello"),
5465 };
5466
Ryan Sleevib8d7ea02018-05-07 20:01:015467 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:165468 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5469
Ryan Sleevib8d7ea02018-05-07 20:01:015470 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:165471 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5472
Ryan Sleevib8d7ea02018-05-07 20:01:015473 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:165474 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5475
bnc87dcefc2017-05-25 12:47:585476 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195477 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:165478
5479 TestCompletionCallback callback;
5480 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5481 EXPECT_THAT(callback.GetResult(rv), IsOk());
5482
5483 const HttpResponseInfo* response = trans->GetResponseInfo();
5484 ASSERT_TRUE(response);
5485 ASSERT_TRUE(response->headers);
5486 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5487
5488 // The following three tests assert that an authentication challenge was
5489 // received and that the stack is ready to respond to the challenge using
5490 // ambient credentials.
5491 EXPECT_EQ(401, response->headers->response_code());
5492 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585493 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165494
5495 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5496 EXPECT_THAT(callback.GetResult(rv), IsOk());
5497 response = trans->GetResponseInfo();
5498 ASSERT_TRUE(response);
5499 ASSERT_TRUE(response->headers);
5500
5501 // The following three tests assert that an authentication challenge was
5502 // received and that the stack needs explicit credentials before it is ready
5503 // to respond to the challenge.
5504 EXPECT_EQ(401, response->headers->response_code());
5505 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585506 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165507
5508 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5509 EXPECT_THAT(callback.GetResult(rv), IsOk());
5510 response = trans->GetResponseInfo();
5511 ASSERT_TRUE(response);
5512 ASSERT_TRUE(response->headers);
5513 EXPECT_EQ(200, response->headers->response_code());
5514
5515 trans.reset();
5516 session->CloseAllConnections();
5517}
5518
Matt Menked1eb6d42018-01-17 04:54:065519// Proxy resolver that returns a proxy with the same host and port for different
5520// schemes, based on the path of the URL being requests.
5521class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
5522 public:
5523 SameProxyWithDifferentSchemesProxyResolver() {}
5524 ~SameProxyWithDifferentSchemesProxyResolver() override {}
5525
5526 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
5527
5528 static HostPortPair ProxyHostPortPair() {
5529 return HostPortPair::FromString(ProxyHostPortPairAsString());
5530 }
5531
5532 // ProxyResolver implementation.
5533 int GetProxyForURL(const GURL& url,
5534 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:175535 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:065536 std::unique_ptr<Request>* request,
5537 const NetLogWithSource& /*net_log*/) override {
5538 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:575539 results->set_traffic_annotation(
5540 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:065541 if (url.path() == "/socks4") {
5542 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
5543 return OK;
5544 }
5545 if (url.path() == "/socks5") {
5546 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
5547 return OK;
5548 }
5549 if (url.path() == "/http") {
5550 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
5551 return OK;
5552 }
5553 if (url.path() == "/https") {
5554 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
5555 return OK;
5556 }
Matt Menkee8648fa2019-01-17 16:47:075557 if (url.path() == "/https_trusted") {
5558 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
5559 ProxyHostPortPair(),
5560 true /* is_trusted_proxy */));
5561 return OK;
5562 }
Matt Menked1eb6d42018-01-17 04:54:065563 NOTREACHED();
5564 return ERR_NOT_IMPLEMENTED;
5565 }
5566
5567 private:
5568 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
5569};
5570
5571class SameProxyWithDifferentSchemesProxyResolverFactory
5572 : public ProxyResolverFactory {
5573 public:
5574 SameProxyWithDifferentSchemesProxyResolverFactory()
5575 : ProxyResolverFactory(false) {}
5576
Lily Houghton99597862018-03-07 16:40:425577 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
5578 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:175579 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:425580 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:065581 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
5582 return OK;
5583 }
5584
5585 private:
5586 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
5587};
5588
5589// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:075590// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:065591// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
5592// request to foo.com using proxy.com as an HTTP proxy.
5593TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:495594 session_deps_.proxy_resolution_service =
5595 std::make_unique<ProxyResolutionService>(
5596 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5597 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
5598 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
5599 nullptr);
Matt Menked1eb6d42018-01-17 04:54:065600
5601 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5602
5603 MockWrite socks_writes[] = {
5604 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
5605 kSOCKS4OkRequestLocalHostPort80Length),
5606 MockWrite(SYNCHRONOUS,
5607 "GET /socks4 HTTP/1.1\r\n"
5608 "Host: test\r\n"
5609 "Connection: keep-alive\r\n\r\n"),
5610 };
5611 MockRead socks_reads[] = {
5612 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
5613 MockRead("HTTP/1.0 200 OK\r\n"
5614 "Connection: keep-alive\r\n"
5615 "Content-Length: 15\r\n\r\n"
5616 "SOCKS4 Response"),
5617 };
Ryan Sleevib8d7ea02018-05-07 20:01:015618 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065619 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5620
5621 const char kSOCKS5Request[] = {
5622 0x05, // Version
5623 0x01, // Command (CONNECT)
5624 0x00, // Reserved
5625 0x03, // Address type (DOMAINNAME)
5626 0x04, // Length of domain (4)
5627 't', 'e', 's', 't', // Domain string
5628 0x00, 0x50, // 16-bit port (80)
5629 };
5630 MockWrite socks5_writes[] = {
5631 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245632 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065633 MockWrite(SYNCHRONOUS,
5634 "GET /socks5 HTTP/1.1\r\n"
5635 "Host: test\r\n"
5636 "Connection: keep-alive\r\n\r\n"),
5637 };
5638 MockRead socks5_reads[] = {
5639 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5640 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5641 MockRead("HTTP/1.0 200 OK\r\n"
5642 "Connection: keep-alive\r\n"
5643 "Content-Length: 15\r\n\r\n"
5644 "SOCKS5 Response"),
5645 };
Ryan Sleevib8d7ea02018-05-07 20:01:015646 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065647 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5648
5649 MockWrite http_writes[] = {
5650 MockWrite(SYNCHRONOUS,
5651 "GET http://test/http HTTP/1.1\r\n"
5652 "Host: test\r\n"
5653 "Proxy-Connection: keep-alive\r\n\r\n"),
5654 };
5655 MockRead http_reads[] = {
5656 MockRead("HTTP/1.1 200 OK\r\n"
5657 "Proxy-Connection: keep-alive\r\n"
5658 "Content-Length: 13\r\n\r\n"
5659 "HTTP Response"),
5660 };
Ryan Sleevib8d7ea02018-05-07 20:01:015661 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065662 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5663
5664 MockWrite https_writes[] = {
5665 MockWrite(SYNCHRONOUS,
5666 "GET http://test/https HTTP/1.1\r\n"
5667 "Host: test\r\n"
5668 "Proxy-Connection: keep-alive\r\n\r\n"),
5669 };
5670 MockRead https_reads[] = {
5671 MockRead("HTTP/1.1 200 OK\r\n"
5672 "Proxy-Connection: keep-alive\r\n"
5673 "Content-Length: 14\r\n\r\n"
5674 "HTTPS Response"),
5675 };
Ryan Sleevib8d7ea02018-05-07 20:01:015676 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065677 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5678 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5679 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5680
Matt Menkee8648fa2019-01-17 16:47:075681 MockWrite https_trusted_writes[] = {
5682 MockWrite(SYNCHRONOUS,
5683 "GET http://test/https_trusted HTTP/1.1\r\n"
5684 "Host: test\r\n"
5685 "Proxy-Connection: keep-alive\r\n\r\n"),
5686 };
5687 MockRead https_trusted_reads[] = {
5688 MockRead("HTTP/1.1 200 OK\r\n"
5689 "Proxy-Connection: keep-alive\r\n"
5690 "Content-Length: 22\r\n\r\n"
5691 "HTTPS Trusted Response"),
5692 };
5693 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5694 https_trusted_writes);
5695 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5696 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5698
Matt Menked1eb6d42018-01-17 04:54:065699 struct TestCase {
5700 GURL url;
5701 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075702 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065703 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075704 int expected_idle_socks4_sockets;
5705 int expected_idle_socks5_sockets;
5706 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5707 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065708 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075709 int expected_idle_https_sockets;
5710 // How many idle sockets there should be in the HTTPS proxy socket pool with
5711 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5712 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065713 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075714 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5715 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5716 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5717 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5718 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5719 1},
Matt Menked1eb6d42018-01-17 04:54:065720 };
5721
5722 for (const auto& test_case : kTestCases) {
5723 HttpRequestInfo request;
5724 request.method = "GET";
5725 request.url = test_case.url;
Ramin Halavatib5e433e62018-02-07 07:41:105726 request.traffic_annotation =
5727 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065728 std::unique_ptr<HttpNetworkTransaction> trans =
5729 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5730 session.get());
5731 TestCompletionCallback callback;
5732 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5733 EXPECT_THAT(callback.GetResult(rv), IsOk());
5734
5735 const HttpResponseInfo* response = trans->GetResponseInfo();
5736 ASSERT_TRUE(response);
5737 ASSERT_TRUE(response->headers);
5738 EXPECT_EQ(200, response->headers->response_code());
5739 std::string response_data;
5740 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5741 EXPECT_EQ(test_case.expected_response, response_data);
5742
5743 // Return the socket to the socket pool, so can make sure it's not used for
5744 // the next requests.
5745 trans.reset();
5746 base::RunLoop().RunUntilIdle();
5747
5748 // Check the number of idle sockets in the pool, to make sure that used
5749 // sockets are indeed being returned to the socket pool. If each request
5750 // doesn't return an idle socket to the pool, the test would incorrectly
5751 // pass.
Matt Menkee8648fa2019-01-17 16:47:075752 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5753 session
Matt Menked23ab952019-03-06 00:24:405754 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075755 HttpNetworkSession::NORMAL_SOCKET_POOL,
5756 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5757 SameProxyWithDifferentSchemesProxyResolver::
5758 ProxyHostPortPair()))
5759 ->IdleSocketCount());
5760 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5761 session
Matt Menked23ab952019-03-06 00:24:405762 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075763 HttpNetworkSession::NORMAL_SOCKET_POOL,
5764 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5765 SameProxyWithDifferentSchemesProxyResolver::
5766 ProxyHostPortPair()))
5767 ->IdleSocketCount());
5768 EXPECT_EQ(test_case.expected_idle_http_sockets,
5769 session
Matt Menked23ab952019-03-06 00:24:405770 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075771 HttpNetworkSession::NORMAL_SOCKET_POOL,
5772 ProxyServer(ProxyServer::SCHEME_HTTP,
5773 SameProxyWithDifferentSchemesProxyResolver::
5774 ProxyHostPortPair()))
5775 ->IdleSocketCount());
5776 EXPECT_EQ(test_case.expected_idle_https_sockets,
5777 session
Matt Menked23ab952019-03-06 00:24:405778 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075779 HttpNetworkSession::NORMAL_SOCKET_POOL,
5780 ProxyServer(ProxyServer::SCHEME_HTTPS,
5781 SameProxyWithDifferentSchemesProxyResolver::
5782 ProxyHostPortPair()))
5783 ->IdleSocketCount());
5784 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5785 session
Matt Menked23ab952019-03-06 00:24:405786 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075787 HttpNetworkSession::NORMAL_SOCKET_POOL,
5788 ProxyServer(ProxyServer::SCHEME_HTTPS,
5789 SameProxyWithDifferentSchemesProxyResolver::
5790 ProxyHostPortPair(),
5791 true /* is_trusted_proxy */))
5792 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065793 }
5794}
5795
[email protected]029c83b62013-01-24 05:28:205796// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015797TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205798 HttpRequestInfo request1;
5799 request1.method = "GET";
bncce36dca22015-04-21 22:11:235800 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105801 request1.traffic_annotation =
5802 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205803
5804 HttpRequestInfo request2;
5805 request2.method = "GET";
bncce36dca22015-04-21 22:11:235806 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105807 request2.traffic_annotation =
5808 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205809
5810 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495811 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5812 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515813 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075814 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095815 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205816
5817 // Since we have proxy, should try to establish tunnel.
5818 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175819 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5820 "Host: www.example.org:443\r\n"
5821 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205822
rsleevidb16bb02015-11-12 23:47:175823 MockWrite("GET /1 HTTP/1.1\r\n"
5824 "Host: www.example.org\r\n"
5825 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205826
rsleevidb16bb02015-11-12 23:47:175827 MockWrite("GET /2 HTTP/1.1\r\n"
5828 "Host: www.example.org\r\n"
5829 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205830 };
5831
5832 // The proxy responds to the connect with a 407, using a persistent
5833 // connection.
5834 MockRead data_reads1[] = {
5835 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5836
5837 MockRead("HTTP/1.1 200 OK\r\n"),
5838 MockRead("Content-Length: 1\r\n\r\n"),
5839 MockRead(SYNCHRONOUS, "1"),
5840
5841 MockRead("HTTP/1.1 200 OK\r\n"),
5842 MockRead("Content-Length: 2\r\n\r\n"),
5843 MockRead(SYNCHRONOUS, "22"),
5844 };
5845
Ryan Sleevib8d7ea02018-05-07 20:01:015846 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075847 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205848 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075849 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205850
5851 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585852 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195853 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205854
5855 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015856 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205857
5858 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015859 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205860
5861 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525862 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475863 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525864 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205865 EXPECT_EQ(1, response1->headers->GetContentLength());
5866
5867 LoadTimingInfo load_timing_info1;
5868 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5869 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5870
5871 trans1.reset();
5872
5873 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585874 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195875 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205876
5877 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015878 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205879
5880 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015881 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205882
5883 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525884 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475885 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525886 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205887 EXPECT_EQ(2, response2->headers->GetContentLength());
5888
5889 LoadTimingInfo load_timing_info2;
5890 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5891 TestLoadTimingReused(load_timing_info2);
5892
5893 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5894
5895 trans2.reset();
5896 session->CloseAllConnections();
5897}
5898
5899// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015900TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205901 HttpRequestInfo request1;
5902 request1.method = "GET";
bncce36dca22015-04-21 22:11:235903 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105904 request1.traffic_annotation =
5905 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205906
5907 HttpRequestInfo request2;
5908 request2.method = "GET";
bncce36dca22015-04-21 22:11:235909 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105910 request2.traffic_annotation =
5911 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205912
5913 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595914 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495915 ProxyResolutionService::CreateFixedFromPacResult(
5916 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515917 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075918 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095919 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205920
5921 // Since we have proxy, should try to establish tunnel.
5922 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175923 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5924 "Host: www.example.org:443\r\n"
5925 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205926
rsleevidb16bb02015-11-12 23:47:175927 MockWrite("GET /1 HTTP/1.1\r\n"
5928 "Host: www.example.org\r\n"
5929 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205930
rsleevidb16bb02015-11-12 23:47:175931 MockWrite("GET /2 HTTP/1.1\r\n"
5932 "Host: www.example.org\r\n"
5933 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205934 };
5935
5936 // The proxy responds to the connect with a 407, using a persistent
5937 // connection.
5938 MockRead data_reads1[] = {
5939 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5940
5941 MockRead("HTTP/1.1 200 OK\r\n"),
5942 MockRead("Content-Length: 1\r\n\r\n"),
5943 MockRead(SYNCHRONOUS, "1"),
5944
5945 MockRead("HTTP/1.1 200 OK\r\n"),
5946 MockRead("Content-Length: 2\r\n\r\n"),
5947 MockRead(SYNCHRONOUS, "22"),
5948 };
5949
Ryan Sleevib8d7ea02018-05-07 20:01:015950 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075951 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205952 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075953 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205954
5955 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585956 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195957 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205958
5959 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015960 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205961
5962 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015963 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205964
5965 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525966 ASSERT_TRUE(response1);
5967 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205968 EXPECT_EQ(1, response1->headers->GetContentLength());
5969
5970 LoadTimingInfo load_timing_info1;
5971 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5972 TestLoadTimingNotReusedWithPac(load_timing_info1,
5973 CONNECT_TIMING_HAS_SSL_TIMES);
5974
5975 trans1.reset();
5976
5977 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585978 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195979 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205980
5981 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015982 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205983
5984 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015985 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205986
5987 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525988 ASSERT_TRUE(response2);
5989 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205990 EXPECT_EQ(2, response2->headers->GetContentLength());
5991
5992 LoadTimingInfo load_timing_info2;
5993 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5994 TestLoadTimingReusedWithPac(load_timing_info2);
5995
5996 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5997
5998 trans2.reset();
5999 session->CloseAllConnections();
6000}
6001
[email protected]2df19bb2010-08-25 20:13:466002// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016003TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276004 HttpRequestInfo request;
6005 request.method = "GET";
bncce36dca22015-04-21 22:11:236006 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106007 request.traffic_annotation =
6008 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276009
[email protected]2df19bb2010-08-25 20:13:466010 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496011 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6012 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516013 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076014 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096015 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:466016
[email protected]2df19bb2010-08-25 20:13:466017 // Since we have proxy, should use full url
6018 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236019 MockWrite(
6020 "GET http://www.example.org/ HTTP/1.1\r\n"
6021 "Host: www.example.org\r\n"
6022 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466023 };
6024
6025 MockRead data_reads1[] = {
6026 MockRead("HTTP/1.1 200 OK\r\n"),
6027 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6028 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066029 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466030 };
6031
Ryan Sleevib8d7ea02018-05-07 20:01:016032 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076033 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066034 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076035 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466036
[email protected]49639fa2011-12-20 23:22:416037 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466038
bnc691fda62016-08-12 00:43:166039 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506040
bnc691fda62016-08-12 00:43:166041 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016042 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466043
6044 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016045 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466046
[email protected]58e32bb2013-01-21 18:23:256047 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166048 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256049 TestLoadTimingNotReused(load_timing_info,
6050 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6051
bnc691fda62016-08-12 00:43:166052 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526053 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466054
tbansal2ecbbc72016-10-06 17:15:476055 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:466056 EXPECT_TRUE(response->headers->IsKeepAlive());
6057 EXPECT_EQ(200, response->headers->response_code());
6058 EXPECT_EQ(100, response->headers->GetContentLength());
6059 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6060
6061 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586062 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466063}
6064
[email protected]7642b5ae2010-09-01 20:55:176065// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016066TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276067 HttpRequestInfo request;
6068 request.method = "GET";
bncce36dca22015-04-21 22:11:236069 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106070 request.traffic_annotation =
6071 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276072
[email protected]7642b5ae2010-09-01 20:55:176073 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496074 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6075 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516076 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076077 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096078 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:176079
bncce36dca22015-04-21 22:11:236080 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136081 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456082 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416083 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:176084
Ryan Hamilton0239aac2018-05-19 00:03:136085 spdy::SpdySerializedFrame resp(
6086 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6087 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:176088 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416089 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:176090 };
6091
Ryan Sleevib8d7ea02018-05-07 20:01:016092 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076093 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:176094
[email protected]8ddf8322012-02-23 18:08:066095 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366096 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076097 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:176098
[email protected]49639fa2011-12-20 23:22:416099 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:176100
bnc691fda62016-08-12 00:43:166101 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506102
bnc691fda62016-08-12 00:43:166103 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016104 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:176105
6106 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016107 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:176108
[email protected]58e32bb2013-01-21 18:23:256109 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166110 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256111 TestLoadTimingNotReused(load_timing_info,
6112 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6113
bnc691fda62016-08-12 00:43:166114 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526115 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:476116 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:526117 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026118 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:176119
6120 std::string response_data;
bnc691fda62016-08-12 00:43:166121 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236122 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:176123}
6124
[email protected]1c173852014-06-19 12:51:506125// Verifies that a session which races and wins against the owning transaction
6126// (completing prior to host resolution), doesn't fail the transaction.
6127// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:016128TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:506129 HttpRequestInfo request;
6130 request.method = "GET";
bncce36dca22015-04-21 22:11:236131 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106132 request.traffic_annotation =
6133 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:506134
6135 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496136 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6137 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516138 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:506139 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096140 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:506141
bncce36dca22015-04-21 22:11:236142 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:136143 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456144 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416145 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:506146
Raul Tambre94493c652019-03-11 17:18:356147 spdy::SpdySerializedFrame resp(
6148 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136149 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:506150 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416151 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:506152 };
6153
Ryan Sleevib8d7ea02018-05-07 20:01:016154 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:506155 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6156
6157 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366158 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:506159 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6160
6161 TestCompletionCallback callback1;
6162
bnc691fda62016-08-12 00:43:166163 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:506164
6165 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:506166 session_deps_.host_resolver->set_ondemand_mode(true);
6167
bnc691fda62016-08-12 00:43:166168 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016169 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:506170
6171 // Race a session to the proxy, which completes first.
6172 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:046173 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:116174 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:346175 SpdySessionKey::IsProxySession::kTrue, SocketTag(),
6176 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]1c173852014-06-19 12:51:506177 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:526178 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:506179
6180 // Unstall the resolution begun by the transaction.
6181 session_deps_.host_resolver->set_ondemand_mode(true);
6182 session_deps_.host_resolver->ResolveAllPending();
6183
6184 EXPECT_FALSE(callback1.have_result());
6185 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016186 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:506187
bnc691fda62016-08-12 00:43:166188 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526189 ASSERT_TRUE(response);
6190 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026191 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:506192
6193 std::string response_data;
bnc691fda62016-08-12 00:43:166194 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:506195 EXPECT_EQ(kUploadData, response_data);
6196}
6197
[email protected]dc7bd1c52010-11-12 00:01:136198// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016199TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:276200 HttpRequestInfo request;
6201 request.method = "GET";
bncce36dca22015-04-21 22:11:236202 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106203 request.traffic_annotation =
6204 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276205
[email protected]79cb5c12011-09-12 13:12:046206 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496207 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6208 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516209 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076210 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096211 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:136212
[email protected]dc7bd1c52010-11-12 00:01:136213 // The first request will be a bare GET, the second request will be a
6214 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:456215 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:136216 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:486217 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:386218 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:136219 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466220 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:136221 };
Ryan Hamilton0239aac2018-05-19 00:03:136222 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:246223 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:486224 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:136225 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416226 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:136227 };
6228
6229 // The first response is a 407 proxy authentication challenge, and the second
6230 // response will be a 200 response since the second request includes a valid
6231 // Authorization header.
6232 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466233 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:136234 };
Ryan Hamilton0239aac2018-05-19 00:03:136235 spdy::SpdySerializedFrame resp_authentication(
6236 spdy_util_.ConstructSpdyReplyError(
6237 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:246238 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136239 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:416240 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:136241 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:356242 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136243 spdy::SpdySerializedFrame body_data(
6244 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:136245 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416246 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:466247 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416248 CreateMockRead(resp_data, 4),
6249 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:136250 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:136251 };
6252
Ryan Sleevib8d7ea02018-05-07 20:01:016253 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076254 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:136255
[email protected]8ddf8322012-02-23 18:08:066256 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366257 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:136259
[email protected]49639fa2011-12-20 23:22:416260 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:136261
bnc691fda62016-08-12 00:43:166262 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:136263
bnc691fda62016-08-12 00:43:166264 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016265 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136266
6267 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016268 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136269
bnc691fda62016-08-12 00:43:166270 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136271
wezca1070932016-05-26 20:30:526272 ASSERT_TRUE(response);
6273 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:136274 EXPECT_EQ(407, response->headers->response_code());
6275 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:586276 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:136277
[email protected]49639fa2011-12-20 23:22:416278 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:136279
bnc691fda62016-08-12 00:43:166280 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016281 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136282
6283 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016284 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136285
bnc691fda62016-08-12 00:43:166286 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136287
wezca1070932016-05-26 20:30:526288 ASSERT_TRUE(response_restart);
6289 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:136290 EXPECT_EQ(200, response_restart->headers->response_code());
6291 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586292 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:136293}
6294
[email protected]d9da5fe2010-10-13 22:37:166295// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:016296TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:276297 HttpRequestInfo request;
6298 request.method = "GET";
bncce36dca22015-04-21 22:11:236299 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106300 request.traffic_annotation =
6301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276302
[email protected]d9da5fe2010-10-13 22:37:166303 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496304 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6305 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516306 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076307 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096308 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166309
bnc691fda62016-08-12 00:43:166310 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166311
bncce36dca22015-04-21 22:11:236312 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136313 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046314 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6315 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236316 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:166317
bncce36dca22015-04-21 22:11:236318 const char get[] =
6319 "GET / HTTP/1.1\r\n"
6320 "Host: www.example.org\r\n"
6321 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136322 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:196323 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:136324 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356325 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:166326 const char resp[] = "HTTP/1.1 200 OK\r\n"
6327 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136328 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:196329 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:136330 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:196331 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:136332 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416333 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:046334
6335 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416336 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6337 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:046338 };
6339
[email protected]d9da5fe2010-10-13 22:37:166340 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416341 CreateMockRead(conn_resp, 1, ASYNC),
6342 CreateMockRead(wrapped_get_resp, 3, ASYNC),
6343 CreateMockRead(wrapped_body, 4, ASYNC),
6344 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136345 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:166346 };
6347
Ryan Sleevib8d7ea02018-05-07 20:01:016348 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076349 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166350
[email protected]8ddf8322012-02-23 18:08:066351 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366352 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076353 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066354 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076355 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166356
[email protected]49639fa2011-12-20 23:22:416357 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166358
bnc691fda62016-08-12 00:43:166359 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016360 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166361
6362 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016363 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166364
[email protected]58e32bb2013-01-21 18:23:256365 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166366 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256367 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6368
bnc691fda62016-08-12 00:43:166369 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526370 ASSERT_TRUE(response);
6371 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:166372 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6373
6374 std::string response_data;
bnc691fda62016-08-12 00:43:166375 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:166376 EXPECT_EQ("1234567890", response_data);
6377}
6378
6379// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:016380TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
6381 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:386382
[email protected]cb9bf6ca2011-01-28 13:15:276383 HttpRequestInfo request;
6384 request.method = "GET";
bncce36dca22015-04-21 22:11:236385 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106386 request.traffic_annotation =
6387 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276388
[email protected]d9da5fe2010-10-13 22:37:166389 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496390 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6391 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516392 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076393 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096394 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166395
bnc691fda62016-08-12 00:43:166396 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166397
bncce36dca22015-04-21 22:11:236398 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136399 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046400 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6401 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236402 // fetch https://www.example.org/ via SPDY
6403 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:136404 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:496405 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:136406 spdy::SpdySerializedFrame wrapped_get(
6407 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6408 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356409 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136410 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356411 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136412 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:026413 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136414 spdy::SpdySerializedFrame body(
6415 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
6416 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:026417 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136418 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:416419 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:136420 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:416421 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:046422
6423 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416424 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6425 CreateMockWrite(window_update_get_resp, 6),
6426 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:046427 };
6428
[email protected]d9da5fe2010-10-13 22:37:166429 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416430 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:096431 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:416432 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6433 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136434 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:166435 };
6436
Ryan Sleevib8d7ea02018-05-07 20:01:016437 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076438 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166439
[email protected]8ddf8322012-02-23 18:08:066440 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366441 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076442 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066443 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366444 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076445 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166446
[email protected]49639fa2011-12-20 23:22:416447 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166448
bnc691fda62016-08-12 00:43:166449 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016450 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166451
rch32320842015-05-16 15:57:096452 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:556453 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:096454 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:596455 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:166456 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016457 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166458
[email protected]58e32bb2013-01-21 18:23:256459 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166460 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256461 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6462
bnc691fda62016-08-12 00:43:166463 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526464 ASSERT_TRUE(response);
6465 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026466 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:166467
6468 std::string response_data;
bnc691fda62016-08-12 00:43:166469 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236470 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:166471}
6472
6473// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016474TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:276475 HttpRequestInfo request;
6476 request.method = "GET";
bncce36dca22015-04-21 22:11:236477 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106478 request.traffic_annotation =
6479 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276480
[email protected]d9da5fe2010-10-13 22:37:166481 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496482 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6483 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516484 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076485 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096486 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166487
bnc691fda62016-08-12 00:43:166488 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166489
bncce36dca22015-04-21 22:11:236490 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136491 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046492 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6493 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136494 spdy::SpdySerializedFrame get(
6495 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:166496
6497 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416498 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:166499 };
6500
Ryan Hamilton0239aac2018-05-19 00:03:136501 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
6502 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:166503 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416504 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:166505 };
6506
Ryan Sleevib8d7ea02018-05-07 20:01:016507 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076508 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166509
[email protected]8ddf8322012-02-23 18:08:066510 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366511 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076512 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066513 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366514 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076515 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166516
[email protected]49639fa2011-12-20 23:22:416517 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166518
bnc691fda62016-08-12 00:43:166519 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016520 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166521
6522 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016523 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:166524
ttuttle960fcbf2016-04-19 13:26:326525 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:166526}
6527
Matt Menkecb2cd0982018-12-19 17:54:046528// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:246529// is observed, but does exist by the time auth credentials are provided. In
6530// this case, auth and SSL are fully negotated on the second request, but then
6531// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:046532TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
6533 ProxyConfig proxy_config;
6534 proxy_config.set_auto_detect(true);
6535 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6536
6537 CapturingProxyResolver capturing_proxy_resolver;
6538 capturing_proxy_resolver.set_proxy_server(
6539 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
6540 session_deps_.proxy_resolution_service =
6541 std::make_unique<ProxyResolutionService>(
6542 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6543 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6544 std::make_unique<CapturingProxyResolverFactory>(
6545 &capturing_proxy_resolver),
6546 nullptr);
6547
6548 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6549
6550 const char kMyUrl[] = "https://www.example.org/";
6551 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6552 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356553 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:046554 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6555
6556 spdy_util_.UpdateWithStreamDestruction(1);
6557 spdy::SpdySerializedFrame get2(
6558 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
6559 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356560 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:046561 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
6562
6563 MockWrite auth_challenge_writes[] = {
6564 MockWrite(ASYNC, 0,
6565 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6566 "Host: www.example.org:443\r\n"
6567 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:246568 MockWrite(ASYNC, 2,
6569 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6570 "Host: www.example.org:443\r\n"
6571 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:046572 };
6573
6574 MockRead auth_challenge_reads[] = {
6575 MockRead(ASYNC, 1,
6576 "HTTP/1.1 407 Authentication Required\r\n"
6577 "Content-Length: 0\r\n"
6578 "Proxy-Connection: close\r\n"
6579 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
6580 };
6581
6582 MockWrite spdy_writes[] = {
6583 MockWrite(ASYNC, 0,
6584 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6585 "Host: www.example.org:443\r\n"
6586 "Proxy-Connection: keep-alive\r\n"
6587 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6588 CreateMockWrite(get, 2),
6589 CreateMockWrite(get2, 5),
6590 };
6591
6592 MockRead spdy_reads[] = {
6593 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6594 CreateMockRead(get_resp, 3, ASYNC),
6595 CreateMockRead(body, 4, ASYNC),
6596 CreateMockRead(get_resp2, 6, ASYNC),
6597 CreateMockRead(body2, 7, ASYNC),
6598
6599 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
6600 };
6601
Matt Menke5062be22019-05-01 17:50:246602 MockWrite auth_response_writes_discarded_socket[] = {
6603 MockWrite(ASYNC, 0,
6604 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6605 "Host: www.example.org:443\r\n"
6606 "Proxy-Connection: keep-alive\r\n"
6607 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6608 };
6609
6610 MockRead auth_response_reads_discarded_socket[] = {
6611 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6612 };
6613
Matt Menkecb2cd0982018-12-19 17:54:046614 SequencedSocketData auth_challenge1(auth_challenge_reads,
6615 auth_challenge_writes);
6616 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
6617
6618 SequencedSocketData auth_challenge2(auth_challenge_reads,
6619 auth_challenge_writes);
6620 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
6621
6622 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6623 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6624
Matt Menke5062be22019-05-01 17:50:246625 SequencedSocketData auth_response_discarded_socket(
6626 auth_response_reads_discarded_socket,
6627 auth_response_writes_discarded_socket);
6628 session_deps_.socket_factory->AddSocketDataProvider(
6629 &auth_response_discarded_socket);
6630
Matt Menkecb2cd0982018-12-19 17:54:046631 SSLSocketDataProvider ssl(ASYNC, OK);
6632 ssl.next_proto = kProtoHTTP2;
6633 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6634
Matt Menke5062be22019-05-01 17:50:246635 SSLSocketDataProvider ssl2(ASYNC, OK);
6636 ssl2.next_proto = kProtoHTTP2;
6637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6638
Matt Menkecb2cd0982018-12-19 17:54:046639 TestCompletionCallback callback;
6640 std::string response_data;
6641
6642 // Run first request until an auth challenge is observed.
6643 HttpRequestInfo request1;
6644 request1.method = "GET";
6645 request1.url = GURL(kMyUrl);
6646 request1.traffic_annotation =
6647 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6648 HttpNetworkTransaction trans1(LOWEST, session.get());
6649 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6650 EXPECT_THAT(callback.GetResult(rv), IsOk());
6651 const HttpResponseInfo* response = trans1.GetResponseInfo();
6652 ASSERT_TRUE(response);
6653 ASSERT_TRUE(response->headers);
6654 EXPECT_EQ(407, response->headers->response_code());
6655 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586656 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046657
6658 // Run second request until an auth challenge is observed.
6659 HttpRequestInfo request2;
6660 request2.method = "GET";
6661 request2.url = GURL(kMyUrl);
6662 request2.traffic_annotation =
6663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6664 HttpNetworkTransaction trans2(LOWEST, session.get());
6665 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6666 EXPECT_THAT(callback.GetResult(rv), IsOk());
6667 response = trans2.GetResponseInfo();
6668 ASSERT_TRUE(response);
6669 ASSERT_TRUE(response->headers);
6670 EXPECT_EQ(407, response->headers->response_code());
6671 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586672 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046673
6674 // Now provide credentials for the first request, and wait for it to complete.
6675 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6676 rv = callback.GetResult(rv);
6677 EXPECT_THAT(rv, IsOk());
6678 response = trans1.GetResponseInfo();
6679 ASSERT_TRUE(response);
6680 ASSERT_TRUE(response->headers);
6681 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6682 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6683 EXPECT_EQ(kUploadData, response_data);
6684
6685 // Now provide credentials for the second request. It should notice the
6686 // existing session, and reuse it.
6687 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6688 EXPECT_THAT(callback.GetResult(rv), IsOk());
6689 response = trans2.GetResponseInfo();
6690 ASSERT_TRUE(response);
6691 ASSERT_TRUE(response->headers);
6692 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6693 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6694 EXPECT_EQ(kUploadData, response_data);
6695}
6696
[email protected]f6c63db52013-02-02 00:35:226697// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6698// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016699TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226700 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6701 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496702 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6703 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516704 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076705 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096706 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506707 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226708
6709 HttpRequestInfo request1;
6710 request1.method = "GET";
bncce36dca22015-04-21 22:11:236711 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226712 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106713 request1.traffic_annotation =
6714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226715
6716 HttpRequestInfo request2;
6717 request2.method = "GET";
bncce36dca22015-04-21 22:11:236718 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226719 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106720 request2.traffic_annotation =
6721 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226722
bncce36dca22015-04-21 22:11:236723 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136724 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046725 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6726 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136727 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356728 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226729
bncce36dca22015-04-21 22:11:236730 // Fetch https://www.example.org/ via HTTP.
6731 const char get1[] =
6732 "GET / HTTP/1.1\r\n"
6733 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226734 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136735 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196736 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226737 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6738 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136739 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196740 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136741 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196742 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136743 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416744 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226745
bncce36dca22015-04-21 22:11:236746 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136747 spdy::SpdyHeaderBlock connect2_block;
6748 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6749 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6750 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046751 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6752 false));
[email protected]601e03f12014-04-06 16:26:396753
Ryan Hamilton0239aac2018-05-19 00:03:136754 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356755 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226756
bncce36dca22015-04-21 22:11:236757 // Fetch https://mail.example.org/ via HTTP.
6758 const char get2[] =
6759 "GET / HTTP/1.1\r\n"
6760 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226761 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136762 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196763 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226764 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6765 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136766 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196767 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136768 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196769 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226770
6771 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416772 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6773 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226774 };
6775
6776 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416777 CreateMockRead(conn_resp1, 1, ASYNC),
6778 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6779 CreateMockRead(wrapped_body1, 4, ASYNC),
6780 CreateMockRead(conn_resp2, 6, ASYNC),
6781 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6782 CreateMockRead(wrapped_body2, 9, ASYNC),
6783 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226784 };
6785
Ryan Sleevib8d7ea02018-05-07 20:01:016786 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506787 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226788
6789 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366790 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226792 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506793 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226794 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506795 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226796
6797 TestCompletionCallback callback;
6798
bnc691fda62016-08-12 00:43:166799 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206800 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016801 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226802
6803 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166804 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226805 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6806
bnc691fda62016-08-12 00:43:166807 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526808 ASSERT_TRUE(response);
6809 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226810 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6811
6812 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446813 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166814 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506815 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226816
bnc691fda62016-08-12 00:43:166817 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206818 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016819 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226820
6821 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166822 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226823 // Even though the SPDY connection is reused, a new tunnelled connection has
6824 // to be created, so the socket's load timing looks like a fresh connection.
6825 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6826
6827 // The requests should have different IDs, since they each are using their own
6828 // separate stream.
6829 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6830
bnc691fda62016-08-12 00:43:166831 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506832 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226833}
6834
6835// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6836// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016837TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226838 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6839 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496840 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6841 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516842 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076843 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096844 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506845 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226846
6847 HttpRequestInfo request1;
6848 request1.method = "GET";
bncce36dca22015-04-21 22:11:236849 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226850 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106851 request1.traffic_annotation =
6852 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226853
6854 HttpRequestInfo request2;
6855 request2.method = "GET";
bncce36dca22015-04-21 22:11:236856 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226857 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106858 request2.traffic_annotation =
6859 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226860
bncce36dca22015-04-21 22:11:236861 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136862 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046863 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6864 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136865 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356866 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226867
bncce36dca22015-04-21 22:11:236868 // Fetch https://www.example.org/ via HTTP.
6869 const char get1[] =
6870 "GET / HTTP/1.1\r\n"
6871 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226872 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136873 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196874 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226875 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6876 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136877 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196878 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136879 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196880 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136881 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416882 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226883
bncce36dca22015-04-21 22:11:236884 // Fetch https://www.example.org/2 via HTTP.
6885 const char get2[] =
6886 "GET /2 HTTP/1.1\r\n"
6887 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226888 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136889 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196890 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226891 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6892 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136893 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196894 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136895 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196896 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226897
6898 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416899 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6900 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226901 };
6902
6903 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416904 CreateMockRead(conn_resp1, 1, ASYNC),
6905 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466906 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416907 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466908 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416909 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226910 };
6911
Ryan Sleevib8d7ea02018-05-07 20:01:016912 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506913 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226914
6915 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366916 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506917 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226918 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506919 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226920
6921 TestCompletionCallback callback;
6922
bnc87dcefc2017-05-25 12:47:586923 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196924 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206925 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016926 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226927
6928 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016929 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226930
6931 LoadTimingInfo load_timing_info;
6932 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6933 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6934
6935 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526936 ASSERT_TRUE(response);
6937 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226938 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6939
6940 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446941 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506942 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226943 trans.reset();
6944
bnc87dcefc2017-05-25 12:47:586945 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196946 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206947 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016948 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226949
[email protected]f6c63db52013-02-02 00:35:226950 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016951 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226952
6953 LoadTimingInfo load_timing_info2;
6954 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6955 TestLoadTimingReused(load_timing_info2);
6956
6957 // The requests should have the same ID.
6958 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6959
[email protected]90499482013-06-01 00:39:506960 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226961}
6962
6963// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6964// Proxy to different servers.
bncd16676a2016-07-20 16:23:016965TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226966 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496967 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6968 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516969 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076970 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096971 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506972 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226973
6974 HttpRequestInfo request1;
6975 request1.method = "GET";
bncce36dca22015-04-21 22:11:236976 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226977 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106978 request1.traffic_annotation =
6979 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226980
6981 HttpRequestInfo request2;
6982 request2.method = "GET";
bncce36dca22015-04-21 22:11:236983 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226984 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106985 request2.traffic_annotation =
6986 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226987
bncce36dca22015-04-21 22:11:236988 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136989 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236990 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136991 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156992 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136993 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356994 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136995 spdy::SpdySerializedFrame body1(
6996 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386997 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226998
bncce36dca22015-04-21 22:11:236999 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:137000 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:237001 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137002 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:157003 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137004 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:357005 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:137006 spdy::SpdySerializedFrame body2(
7007 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:227008
7009 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417010 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:227011 };
7012
7013 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417014 CreateMockRead(get_resp1, 1, ASYNC),
7015 CreateMockRead(body1, 2, ASYNC),
7016 CreateMockRead(get_resp2, 4, ASYNC),
7017 CreateMockRead(body2, 5, ASYNC),
7018 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:227019 };
7020
Ryan Sleevib8d7ea02018-05-07 20:01:017021 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507022 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227023
7024 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367025 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507026 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227027
7028 TestCompletionCallback callback;
7029
bnc87dcefc2017-05-25 12:47:587030 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197031 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207032 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017033 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227034
7035 LoadTimingInfo load_timing_info;
7036 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7037 TestLoadTimingNotReused(load_timing_info,
7038 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7039
7040 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527041 ASSERT_TRUE(response);
7042 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:027043 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:227044
7045 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447046 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:507047 rv = trans->Read(buf.get(), 256, callback.callback());
7048 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227049 // Delete the first request, so the second one can reuse the socket.
7050 trans.reset();
7051
bnc691fda62016-08-12 00:43:167052 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207053 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017054 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227055
7056 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:167057 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:227058 TestLoadTimingReused(load_timing_info2);
7059
7060 // The requests should have the same ID.
7061 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7062
bnc691fda62016-08-12 00:43:167063 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507064 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227065}
7066
Matt Menke2436b2f2018-12-11 18:07:117067// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
7068// direct (non-proxied) request to the proxy server are not pooled, as that
7069// would break socket pool isolation.
7070TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
7071 ProxyConfig proxy_config;
7072 proxy_config.set_auto_detect(true);
7073 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7074
7075 CapturingProxyResolver capturing_proxy_resolver;
7076 session_deps_.proxy_resolution_service =
7077 std::make_unique<ProxyResolutionService>(
7078 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7079 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7080 std::make_unique<CapturingProxyResolverFactory>(
7081 &capturing_proxy_resolver),
7082 nullptr);
7083
7084 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7085
7086 SpdyTestUtil spdy_util1;
7087 // CONNECT to www.example.org:443 via HTTP/2.
7088 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047089 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7090 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117091 // fetch https://www.example.org/ via HTTP/2.
7092 const char kMyUrl[] = "https://www.example.org/";
7093 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7094 spdy::SpdySerializedFrame wrapped_get(
7095 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7096 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:357097 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117098 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:357099 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117100 spdy::SpdySerializedFrame wrapped_get_resp(
7101 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7102 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
7103 spdy::SpdySerializedFrame wrapped_body(
7104 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7105 spdy::SpdySerializedFrame window_update_get_resp(
7106 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7107 spdy::SpdySerializedFrame window_update_body(
7108 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7109
7110 MockWrite spdy_writes1[] = {
7111 CreateMockWrite(connect, 0),
7112 CreateMockWrite(wrapped_get, 2),
7113 CreateMockWrite(window_update_get_resp, 6),
7114 CreateMockWrite(window_update_body, 7),
7115 };
7116
7117 MockRead spdy_reads1[] = {
7118 CreateMockRead(conn_resp, 1, ASYNC),
7119 MockRead(ASYNC, ERR_IO_PENDING, 3),
7120 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7121 CreateMockRead(wrapped_body, 5, ASYNC),
7122 MockRead(ASYNC, 0, 8),
7123 };
7124
7125 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7126 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7127
7128 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
7129 // a new pipe.
7130 SpdyTestUtil spdy_util2;
7131 spdy::SpdySerializedFrame req(
7132 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7133 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
7134
7135 spdy::SpdySerializedFrame resp(
7136 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7137 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
7138 MockRead spdy_reads2[] = {
7139 CreateMockRead(resp, 1),
7140 CreateMockRead(data, 2),
7141 MockRead(ASYNC, 0, 3),
7142 };
7143 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7144 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7145
7146 SSLSocketDataProvider ssl(ASYNC, OK);
7147 ssl.next_proto = kProtoHTTP2;
7148 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7149 SSLSocketDataProvider ssl2(ASYNC, OK);
7150 ssl2.next_proto = kProtoHTTP2;
7151 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7152 SSLSocketDataProvider ssl3(ASYNC, OK);
7153 ssl3.next_proto = kProtoHTTP2;
7154 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7155
7156 TestCompletionCallback callback;
7157 std::string response_data;
7158
7159 // Make a request using proxy:70 as a HTTP/2 proxy.
7160 capturing_proxy_resolver.set_proxy_server(
7161 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7162 HttpRequestInfo request1;
7163 request1.method = "GET";
7164 request1.url = GURL("https://www.example.org/");
7165 request1.traffic_annotation =
7166 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7167
7168 HttpNetworkTransaction trans1(LOWEST, session.get());
7169 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
7170 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7171
7172 // Allow the SpdyProxyClientSocket's write callback to complete.
7173 base::RunLoop().RunUntilIdle();
7174 // Now allow the read of the response to complete.
7175 spdy_data1.Resume();
7176 rv = callback.WaitForResult();
7177 EXPECT_THAT(rv, IsOk());
7178
7179 const HttpResponseInfo* response = trans1.GetResponseInfo();
7180 ASSERT_TRUE(response);
7181 ASSERT_TRUE(response->headers);
7182 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7183
7184 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7185 EXPECT_EQ(kUploadData, response_data);
7186 RunUntilIdle();
7187
7188 // Make a direct HTTP/2 request to proxy:70.
7189 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7190 HttpRequestInfo request2;
7191 request2.method = "GET";
7192 request2.url = GURL("https://proxy:70/");
7193 request2.traffic_annotation =
7194 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7195 HttpNetworkTransaction trans2(LOWEST, session.get());
7196 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
7197 NetLogWithSource())),
7198 IsOk());
7199 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7200}
7201
7202// Same as above, but reverse request order, since the code to check for an
7203// existing session is different for tunnels and direct connections.
7204TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
7205 // Configure against https proxy server "myproxy:80".
7206 ProxyConfig proxy_config;
7207 proxy_config.set_auto_detect(true);
7208 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7209
7210 CapturingProxyResolver capturing_proxy_resolver;
7211 session_deps_.proxy_resolution_service =
7212 std::make_unique<ProxyResolutionService>(
7213 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7214 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7215 std::make_unique<CapturingProxyResolverFactory>(
7216 &capturing_proxy_resolver),
7217 nullptr);
7218
7219 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7220 // Fetch https://proxy:70/ via HTTP/2.
7221 SpdyTestUtil spdy_util1;
7222 spdy::SpdySerializedFrame req(
7223 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7224 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
7225
7226 spdy::SpdySerializedFrame resp(
7227 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
7228 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
7229 MockRead spdy_reads1[] = {
7230 CreateMockRead(resp, 1),
7231 CreateMockRead(data, 2),
7232 MockRead(ASYNC, 0, 3),
7233 };
7234 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7235 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7236
7237 SpdyTestUtil spdy_util2;
7238 // CONNECT to www.example.org:443 via HTTP/2.
7239 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047240 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7241 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117242 // fetch https://www.example.org/ via HTTP/2.
7243 const char kMyUrl[] = "https://www.example.org/";
7244 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7245 spdy::SpdySerializedFrame wrapped_get(
7246 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7247 spdy::SpdySerializedFrame conn_resp(
7248 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7249 spdy::SpdySerializedFrame get_resp(
7250 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7251 spdy::SpdySerializedFrame wrapped_get_resp(
7252 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7253 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
7254 spdy::SpdySerializedFrame wrapped_body(
7255 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7256 spdy::SpdySerializedFrame window_update_get_resp(
7257 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7258 spdy::SpdySerializedFrame window_update_body(
7259 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7260
7261 MockWrite spdy_writes2[] = {
7262 CreateMockWrite(connect, 0),
7263 CreateMockWrite(wrapped_get, 2),
7264 CreateMockWrite(window_update_get_resp, 6),
7265 CreateMockWrite(window_update_body, 7),
7266 };
7267
7268 MockRead spdy_reads2[] = {
7269 CreateMockRead(conn_resp, 1, ASYNC),
7270 MockRead(ASYNC, ERR_IO_PENDING, 3),
7271 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7272 CreateMockRead(wrapped_body, 5, ASYNC),
7273 MockRead(ASYNC, 0, 8),
7274 };
7275
7276 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7277 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7278
7279 SSLSocketDataProvider ssl(ASYNC, OK);
7280 ssl.next_proto = kProtoHTTP2;
7281 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7282 SSLSocketDataProvider ssl2(ASYNC, OK);
7283 ssl2.next_proto = kProtoHTTP2;
7284 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7285 SSLSocketDataProvider ssl3(ASYNC, OK);
7286 ssl3.next_proto = kProtoHTTP2;
7287 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7288
7289 TestCompletionCallback callback;
7290 std::string response_data;
7291
7292 // Make a direct HTTP/2 request to proxy:70.
7293 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7294 HttpRequestInfo request1;
7295 request1.method = "GET";
7296 request1.url = GURL("https://proxy:70/");
7297 request1.traffic_annotation =
7298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7299 HttpNetworkTransaction trans1(LOWEST, session.get());
7300 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
7301 NetLogWithSource())),
7302 IsOk());
7303 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7304 RunUntilIdle();
7305
7306 // Make a request using proxy:70 as a HTTP/2 proxy.
7307 capturing_proxy_resolver.set_proxy_server(
7308 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7309 HttpRequestInfo request2;
7310 request2.method = "GET";
7311 request2.url = GURL("https://www.example.org/");
7312 request2.traffic_annotation =
7313 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7314
7315 HttpNetworkTransaction trans2(LOWEST, session.get());
7316 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
7317 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7318
7319 // Allow the SpdyProxyClientSocket's write callback to complete.
7320 base::RunLoop().RunUntilIdle();
7321 // Now allow the read of the response to complete.
7322 spdy_data2.Resume();
7323 rv = callback.WaitForResult();
7324 EXPECT_THAT(rv, IsOk());
7325
7326 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
7327 ASSERT_TRUE(response2);
7328 ASSERT_TRUE(response2->headers);
7329 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
7330
7331 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7332 EXPECT_EQ(kUploadData, response_data);
7333}
7334
[email protected]2df19bb2010-08-25 20:13:467335// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:017336TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:467337 HttpRequestInfo request;
7338 request.method = "GET";
bncce36dca22015-04-21 22:11:237339 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467340 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297341 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:107342 request.traffic_annotation =
7343 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:467344
[email protected]79cb5c12011-09-12 13:12:047345 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497346 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7347 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:517348 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077349 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097350 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277351
[email protected]2df19bb2010-08-25 20:13:467352 // Since we have proxy, should use full url
7353 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:167354 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7355 "Host: www.example.org\r\n"
7356 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467357
bnc691fda62016-08-12 00:43:167358 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:237359 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:167360 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7361 "Host: www.example.org\r\n"
7362 "Proxy-Connection: keep-alive\r\n"
7363 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467364 };
7365
7366 // The proxy responds to the GET with a 407, using a persistent
7367 // connection.
7368 MockRead data_reads1[] = {
7369 // No credentials.
7370 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7371 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7372 MockRead("Proxy-Connection: keep-alive\r\n"),
7373 MockRead("Content-Length: 0\r\n\r\n"),
7374
7375 MockRead("HTTP/1.1 200 OK\r\n"),
7376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7377 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067378 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467379 };
7380
Ryan Sleevib8d7ea02018-05-07 20:01:017381 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077382 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:067383 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077384 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467385
[email protected]49639fa2011-12-20 23:22:417386 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:467387
bnc691fda62016-08-12 00:43:167388 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507389
bnc691fda62016-08-12 00:43:167390 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:017391 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467392
7393 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017394 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467395
[email protected]58e32bb2013-01-21 18:23:257396 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:167397 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257398 TestLoadTimingNotReused(load_timing_info,
7399 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7400
bnc691fda62016-08-12 00:43:167401 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527402 ASSERT_TRUE(response);
7403 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:467404 EXPECT_EQ(407, response->headers->response_code());
7405 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587406 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:507407 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467408
[email protected]49639fa2011-12-20 23:22:417409 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:467410
bnc691fda62016-08-12 00:43:167411 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017412 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467413
7414 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017415 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467416
[email protected]58e32bb2013-01-21 18:23:257417 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:167418 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257419 // Retrying with HTTP AUTH is considered to be reusing a socket.
7420 TestLoadTimingReused(load_timing_info);
7421
bnc691fda62016-08-12 00:43:167422 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527423 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:467424
7425 EXPECT_TRUE(response->headers->IsKeepAlive());
7426 EXPECT_EQ(200, response->headers->response_code());
7427 EXPECT_EQ(100, response->headers->GetContentLength());
7428 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:507429 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467430
7431 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:587432 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:467433}
7434
[email protected]23e482282013-06-14 16:08:027435void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:087436 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:427437 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:087438 request.method = "GET";
bncce36dca22015-04-21 22:11:237439 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107440 request.traffic_annotation =
7441 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:087442
[email protected]cb9bf6ca2011-01-28 13:15:277443 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497444 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7445 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097446 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277447
[email protected]c744cf22009-02-27 07:28:087448 // Since we have proxy, should try to establish tunnel.
7449 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177450 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7451 "Host: www.example.org:443\r\n"
7452 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:087453 };
7454
7455 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:237456 status, MockRead("Content-Length: 10\r\n\r\n"),
7457 // No response body because the test stops reading here.
7458 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:087459 };
7460
Ryan Sleevib8d7ea02018-05-07 20:01:017461 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:077462 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:087463
[email protected]49639fa2011-12-20 23:22:417464 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:087465
bnc691fda62016-08-12 00:43:167466 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507467
tfarina42834112016-09-22 13:38:207468 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017469 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:087470
7471 rv = callback.WaitForResult();
7472 EXPECT_EQ(expected_status, rv);
7473}
7474
[email protected]23e482282013-06-14 16:08:027475void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:237476 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:087477 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:427478 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:087479}
7480
bncd16676a2016-07-20 16:23:017481TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:087482 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
7483}
7484
bncd16676a2016-07-20 16:23:017485TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:087486 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
7487}
7488
bncd16676a2016-07-20 16:23:017489TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:087490 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
7491}
7492
bncd16676a2016-07-20 16:23:017493TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:087494 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
7495}
7496
bncd16676a2016-07-20 16:23:017497TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:087498 ConnectStatusHelper(
7499 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
7500}
7501
bncd16676a2016-07-20 16:23:017502TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:087503 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
7504}
7505
bncd16676a2016-07-20 16:23:017506TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:087507 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
7508}
7509
bncd16676a2016-07-20 16:23:017510TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:087511 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
7512}
7513
bncd16676a2016-07-20 16:23:017514TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:087515 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
7516}
7517
bncd16676a2016-07-20 16:23:017518TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:087519 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
7520}
7521
bncd16676a2016-07-20 16:23:017522TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:087523 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
7524}
7525
bncd16676a2016-07-20 16:23:017526TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:087527 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
7528}
7529
bncd16676a2016-07-20 16:23:017530TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:087531 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
7532}
7533
bncd16676a2016-07-20 16:23:017534TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:087535 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
7536}
7537
bncd16676a2016-07-20 16:23:017538TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:087539 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
7540}
7541
bncd16676a2016-07-20 16:23:017542TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:087543 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
7544}
7545
bncd16676a2016-07-20 16:23:017546TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:377547 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
7548}
7549
bncd16676a2016-07-20 16:23:017550TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:087551 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
7552}
7553
bncd16676a2016-07-20 16:23:017554TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:087555 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
7556}
7557
bncd16676a2016-07-20 16:23:017558TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:087559 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
7560}
7561
bncd16676a2016-07-20 16:23:017562TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:087563 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
7564}
7565
bncd16676a2016-07-20 16:23:017566TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:087567 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
7568}
7569
bncd16676a2016-07-20 16:23:017570TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:087571 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
7572}
7573
bncd16676a2016-07-20 16:23:017574TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:087575 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
7576}
7577
bncd16676a2016-07-20 16:23:017578TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:087579 ConnectStatusHelperWithExpectedStatus(
7580 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:547581 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:087582}
7583
bncd16676a2016-07-20 16:23:017584TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:087585 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
7586}
7587
bncd16676a2016-07-20 16:23:017588TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:087589 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
7590}
7591
bncd16676a2016-07-20 16:23:017592TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:087593 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
7594}
7595
bncd16676a2016-07-20 16:23:017596TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:087597 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
7598}
7599
bncd16676a2016-07-20 16:23:017600TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:087601 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
7602}
7603
bncd16676a2016-07-20 16:23:017604TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:087605 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
7606}
7607
bncd16676a2016-07-20 16:23:017608TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:087609 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
7610}
7611
bncd16676a2016-07-20 16:23:017612TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:087613 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
7614}
7615
bncd16676a2016-07-20 16:23:017616TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:087617 ConnectStatusHelper(
7618 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
7619}
7620
bncd16676a2016-07-20 16:23:017621TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:087622 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
7623}
7624
bncd16676a2016-07-20 16:23:017625TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:087626 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
7627}
7628
bncd16676a2016-07-20 16:23:017629TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:087630 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
7631}
7632
bncd16676a2016-07-20 16:23:017633TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:087634 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
7635}
7636
bncd16676a2016-07-20 16:23:017637TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:087638 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
7639}
7640
bncd16676a2016-07-20 16:23:017641TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:087642 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
7643}
7644
bncd16676a2016-07-20 16:23:017645TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087646 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7647}
7648
[email protected]038e9a32008-10-08 22:40:167649// Test the flow when both the proxy server AND origin server require
7650// authentication. Again, this uses basic auth for both since that is
7651// the simplest to mock.
bncd16676a2016-07-20 16:23:017652TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277653 HttpRequestInfo request;
7654 request.method = "GET";
bncce36dca22015-04-21 22:11:237655 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107656 request.traffic_annotation =
7657 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277658
[email protected]038e9a32008-10-08 22:40:167659 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497660 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7661 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097662 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077663
bnc691fda62016-08-12 00:43:167664 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167665
[email protected]f9ee6b52008-11-08 06:46:237666 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237667 MockWrite(
7668 "GET http://www.example.org/ HTTP/1.1\r\n"
7669 "Host: www.example.org\r\n"
7670 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237671 };
7672
[email protected]038e9a32008-10-08 22:40:167673 MockRead data_reads1[] = {
7674 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7675 // Give a couple authenticate options (only the middle one is actually
7676 // supported).
[email protected]22927ad2009-09-21 19:56:197677 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167678 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7679 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7680 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7681 // Large content-length -- won't matter, as connection will be reset.
7682 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067683 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167684 };
7685
bnc691fda62016-08-12 00:43:167686 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167687 // request we should be issuing -- the final header line contains the
7688 // proxy's credentials.
7689 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237690 MockWrite(
7691 "GET http://www.example.org/ HTTP/1.1\r\n"
7692 "Host: www.example.org\r\n"
7693 "Proxy-Connection: keep-alive\r\n"
7694 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167695 };
7696
7697 // Now the proxy server lets the request pass through to origin server.
7698 // The origin server responds with a 401.
7699 MockRead data_reads2[] = {
7700 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7701 // Note: We are using the same realm-name as the proxy server. This is
7702 // completely valid, as realms are unique across hosts.
7703 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7704 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7705 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067706 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167707 };
7708
bnc691fda62016-08-12 00:43:167709 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167710 // the credentials for both the proxy and origin server.
7711 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237712 MockWrite(
7713 "GET http://www.example.org/ HTTP/1.1\r\n"
7714 "Host: www.example.org\r\n"
7715 "Proxy-Connection: keep-alive\r\n"
7716 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7717 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167718 };
7719
7720 // Lastly we get the desired content.
7721 MockRead data_reads3[] = {
7722 MockRead("HTTP/1.0 200 OK\r\n"),
7723 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7724 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067725 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167726 };
7727
Ryan Sleevib8d7ea02018-05-07 20:01:017728 StaticSocketDataProvider data1(data_reads1, data_writes1);
7729 StaticSocketDataProvider data2(data_reads2, data_writes2);
7730 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077731 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7732 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7733 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167734
[email protected]49639fa2011-12-20 23:22:417735 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167736
tfarina42834112016-09-22 13:38:207737 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017738 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167739
7740 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017741 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167742
bnc691fda62016-08-12 00:43:167743 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527744 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587745 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167746
[email protected]49639fa2011-12-20 23:22:417747 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167748
bnc691fda62016-08-12 00:43:167749 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017750 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167751
7752 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017753 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167754
bnc691fda62016-08-12 00:43:167755 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527756 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587757 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167758
[email protected]49639fa2011-12-20 23:22:417759 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167760
bnc691fda62016-08-12 00:43:167761 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7762 callback3.callback());
robpercival214763f2016-07-01 23:27:017763 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167764
7765 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017766 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167767
bnc691fda62016-08-12 00:43:167768 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587769 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167770 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167771}
[email protected]4ddaf2502008-10-23 18:26:197772
[email protected]ea9dc9a2009-09-05 00:43:327773// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7774// can't hook into its internals to cause it to generate predictable NTLM
7775// authorization headers.
7776#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377777// The NTLM authentication unit tests are based on known test data from the
7778// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7779// flow rather than the implementation of the NTLM protocol. See net/ntlm
7780// for the implementation and testing of the protocol.
7781//
7782// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297783
7784// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557785TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427786 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247787 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557788 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107789 request.traffic_annotation =
7790 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547791
7792 // Ensure load is not disrupted by flags which suppress behaviour specific
7793 // to other auth schemes.
7794 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247795
Zentaro Kavanagh6ccee512017-09-28 18:34:097796 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7797 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097798 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277799
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377800 // Generate the NTLM messages based on known test data.
7801 std::string negotiate_msg;
7802 std::string challenge_msg;
7803 std::string authenticate_msg;
7804 base::Base64Encode(
7805 base::StringPiece(
7806 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247807 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377808 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557809 base::Base64Encode(
7810 base::StringPiece(
7811 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247812 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557813 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377814 base::Base64Encode(
7815 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097816 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557817 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247818 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557819 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377820 &authenticate_msg);
7821
[email protected]3f918782009-02-28 01:29:247822 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557823 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7824 "Host: server\r\n"
7825 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247826 };
7827
7828 MockRead data_reads1[] = {
7829 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047830 // Negotiate and NTLM are often requested together. However, we only want
7831 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7832 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247833 MockRead("WWW-Authenticate: NTLM\r\n"),
7834 MockRead("Connection: close\r\n"),
7835 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367836 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247837 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247838 };
7839
7840 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167841 // After restarting with a null identity, this is the
7842 // request we should be issuing -- the final header line contains a Type
7843 // 1 message.
7844 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557845 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167846 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377847 "Authorization: NTLM "),
7848 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247849
bnc691fda62016-08-12 00:43:167850 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377851 // (using correct credentials). The second request continues on the
7852 // same connection.
bnc691fda62016-08-12 00:43:167853 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557854 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167855 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377856 "Authorization: NTLM "),
7857 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247858 };
7859
7860 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027861 // The origin server responds with a Type 2 message.
7862 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377863 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7864 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027865 MockRead("Content-Type: text/html\r\n\r\n"),
7866 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247867
Bence Béky1e4ef192017-09-18 19:58:027868 // Lastly we get the desired content.
7869 MockRead("HTTP/1.1 200 OK\r\n"),
7870 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7871 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247872 };
7873
Ryan Sleevib8d7ea02018-05-07 20:01:017874 StaticSocketDataProvider data1(data_reads1, data_writes1);
7875 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077876 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7877 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247878
Bence Béky83eb3512017-09-05 12:56:097879 SSLSocketDataProvider ssl1(ASYNC, OK);
7880 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7881 SSLSocketDataProvider ssl2(ASYNC, OK);
7882 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7883
[email protected]49639fa2011-12-20 23:22:417884 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247885
bnc691fda62016-08-12 00:43:167886 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507887
tfarina42834112016-09-22 13:38:207888 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017889 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247890
7891 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017892 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247893
bnc691fda62016-08-12 00:43:167894 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227895
bnc691fda62016-08-12 00:43:167896 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527897 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587898 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247899
[email protected]49639fa2011-12-20 23:22:417900 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257901
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377902 rv = trans.RestartWithAuth(
7903 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7904 callback2.callback());
robpercival214763f2016-07-01 23:27:017905 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257906
7907 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017908 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257909
bnc691fda62016-08-12 00:43:167910 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257911
bnc691fda62016-08-12 00:43:167912 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527913 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587914 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257915
[email protected]49639fa2011-12-20 23:22:417916 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247917
bnc691fda62016-08-12 00:43:167918 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247920
[email protected]0757e7702009-03-27 04:00:227921 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017922 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247923
bnc691fda62016-08-12 00:43:167924 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527925 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587926 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027927 EXPECT_EQ(14, response->headers->GetContentLength());
7928
7929 std::string response_data;
7930 rv = ReadTransaction(&trans, &response_data);
7931 EXPECT_THAT(rv, IsOk());
7932 EXPECT_EQ("Please Login\r\n", response_data);
7933
7934 EXPECT_TRUE(data1.AllReadDataConsumed());
7935 EXPECT_TRUE(data1.AllWriteDataConsumed());
7936 EXPECT_TRUE(data2.AllReadDataConsumed());
7937 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247938}
7939
[email protected]385a4672009-03-11 22:21:297940// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557941TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427942 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297943 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557944 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107945 request.traffic_annotation =
7946 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297947
Zentaro Kavanagh6ccee512017-09-28 18:34:097948 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7949 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097950 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277951
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377952 // Generate the NTLM messages based on known test data.
7953 std::string negotiate_msg;
7954 std::string challenge_msg;
7955 std::string authenticate_msg;
7956 base::Base64Encode(
7957 base::StringPiece(
7958 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247959 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377960 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557961 base::Base64Encode(
7962 base::StringPiece(
7963 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247964 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557965 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377966 base::Base64Encode(
7967 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097968 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557969 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247970 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557971 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377972 &authenticate_msg);
7973
7974 // The authenticate message when |kWrongPassword| is sent.
7975 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557976 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7977 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7978 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7979 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7980 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7981 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377982
Zentaro Kavanagh1890a3d2018-01-29 19:52:557983 // Sanity check that it's the same length as the correct authenticate message
7984 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377985 ASSERT_EQ(authenticate_msg.length(),
7986 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557987 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377988
[email protected]385a4672009-03-11 22:21:297989 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557990 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7991 "Host: server\r\n"
7992 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297993 };
7994
7995 MockRead data_reads1[] = {
7996 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047997 // Negotiate and NTLM are often requested together. However, we only want
7998 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7999 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:298000 MockRead("WWW-Authenticate: NTLM\r\n"),
8001 MockRead("Connection: close\r\n"),
8002 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:368003 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298004 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298005 };
8006
8007 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:168008 // After restarting with a null identity, this is the
8009 // request we should be issuing -- the final header line contains a Type
8010 // 1 message.
8011 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558012 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168013 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378014 "Authorization: NTLM "),
8015 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298016
bnc691fda62016-08-12 00:43:168017 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378018 // (using incorrect credentials). The second request continues on the
8019 // same connection.
bnc691fda62016-08-12 00:43:168020 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558021 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168022 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378023 "Authorization: NTLM "),
8024 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298025 };
8026
8027 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378028 // The origin server responds with a Type 2 message.
8029 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8030 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8031 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
8032 MockRead("Content-Type: text/html\r\n\r\n"),
8033 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298034
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378035 // Wrong password.
8036 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8037 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
8038 MockRead("Content-Length: 42\r\n"),
8039 MockRead("Content-Type: text/html\r\n\r\n"),
8040 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298041 };
8042
8043 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:168044 // After restarting with a null identity, this is the
8045 // request we should be issuing -- the final header line contains a Type
8046 // 1 message.
8047 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558048 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168049 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378050 "Authorization: NTLM "),
8051 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298052
bnc691fda62016-08-12 00:43:168053 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8054 // (the credentials for the origin server). The second request continues
8055 // on the same connection.
8056 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558057 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168058 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378059 "Authorization: NTLM "),
8060 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298061 };
8062
8063 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:028064 // The origin server responds with a Type 2 message.
8065 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378066 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8067 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028068 MockRead("Content-Type: text/html\r\n\r\n"),
8069 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298070
Bence Béky1e4ef192017-09-18 19:58:028071 // Lastly we get the desired content.
8072 MockRead("HTTP/1.1 200 OK\r\n"),
8073 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
8074 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:298075 };
8076
Ryan Sleevib8d7ea02018-05-07 20:01:018077 StaticSocketDataProvider data1(data_reads1, data_writes1);
8078 StaticSocketDataProvider data2(data_reads2, data_writes2);
8079 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078080 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8081 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8082 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:298083
Bence Béky83eb3512017-09-05 12:56:098084 SSLSocketDataProvider ssl1(ASYNC, OK);
8085 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8086 SSLSocketDataProvider ssl2(ASYNC, OK);
8087 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8088 SSLSocketDataProvider ssl3(ASYNC, OK);
8089 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8090
[email protected]49639fa2011-12-20 23:22:418091 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:298092
bnc691fda62016-08-12 00:43:168093 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508094
tfarina42834112016-09-22 13:38:208095 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018096 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298097
8098 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018099 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298100
bnc691fda62016-08-12 00:43:168101 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:298102
bnc691fda62016-08-12 00:43:168103 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528104 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588105 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:298106
[email protected]49639fa2011-12-20 23:22:418107 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:298108
[email protected]0757e7702009-03-27 04:00:228109 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378110 rv = trans.RestartWithAuth(
8111 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
8112 callback2.callback());
robpercival214763f2016-07-01 23:27:018113 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298114
[email protected]10af5fe72011-01-31 16:17:258115 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018116 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298117
bnc691fda62016-08-12 00:43:168118 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:418119 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168120 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018121 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258122 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018123 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168124 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228125
bnc691fda62016-08-12 00:43:168126 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528127 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588128 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:228129
[email protected]49639fa2011-12-20 23:22:418130 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:228131
8132 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378133 rv = trans.RestartWithAuth(
8134 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8135 callback4.callback());
robpercival214763f2016-07-01 23:27:018136 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258137
8138 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:018139 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258140
bnc691fda62016-08-12 00:43:168141 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258142
[email protected]49639fa2011-12-20 23:22:418143 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:258144
8145 // One more roundtrip
bnc691fda62016-08-12 00:43:168146 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:018147 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:228148
8149 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:018150 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:228151
bnc691fda62016-08-12 00:43:168152 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:588153 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028154 EXPECT_EQ(14, response->headers->GetContentLength());
8155
8156 std::string response_data;
8157 rv = ReadTransaction(&trans, &response_data);
8158 EXPECT_THAT(rv, IsOk());
8159 EXPECT_EQ("Please Login\r\n", response_data);
8160
8161 EXPECT_TRUE(data1.AllReadDataConsumed());
8162 EXPECT_TRUE(data1.AllWriteDataConsumed());
8163 EXPECT_TRUE(data2.AllReadDataConsumed());
8164 EXPECT_TRUE(data2.AllWriteDataConsumed());
8165 EXPECT_TRUE(data3.AllReadDataConsumed());
8166 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:298167}
Bence Béky83eb3512017-09-05 12:56:098168
Bence Béky3238f2e12017-09-22 22:44:498169// Server requests NTLM authentication, which is not supported over HTTP/2.
8170// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:098171TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:098172 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
8173 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:098174
Zentaro Kavanagh1890a3d2018-01-29 19:52:558175 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:098176
8177 HttpRequestInfo request;
8178 request.method = "GET";
8179 request.url = GURL(kUrl);
Ramin Halavatib5e433e62018-02-07 07:41:108180 request.traffic_annotation =
8181 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:098182
8183 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:138184 spdy::SpdyHeaderBlock request_headers0(
8185 spdy_util_.ConstructGetHeaderBlock(kUrl));
8186 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:098187 1, std::move(request_headers0), LOWEST, true));
8188
Ryan Hamilton0239aac2018-05-19 00:03:138189 spdy::SpdyHeaderBlock response_headers0;
8190 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:098191 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:138192 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:098193 1, std::move(response_headers0), true));
8194
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378195 // Stream 1 is closed.
8196 spdy_util_.UpdateWithStreamDestruction(1);
8197
8198 // Generate the NTLM messages based on known test data.
8199 std::string negotiate_msg;
8200 std::string challenge_msg;
8201 std::string authenticate_msg;
8202 base::Base64Encode(
8203 base::StringPiece(
8204 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248205 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378206 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558207 base::Base64Encode(
8208 base::StringPiece(
8209 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248210 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558211 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378212 base::Base64Encode(
8213 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098214 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558215 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248216 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558217 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378218 &authenticate_msg);
8219
Bence Béky3238f2e12017-09-22 22:44:498220 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:168221 MockRead reads0[] = {CreateMockRead(resp, 1),
8222 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:098223
8224 // Retry yet again using HTTP/1.1.
8225 MockWrite writes1[] = {
8226 // After restarting with a null identity, this is the
8227 // request we should be issuing -- the final header line contains a Type
8228 // 1 message.
8229 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558230 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098231 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378232 "Authorization: NTLM "),
8233 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098234
8235 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8236 // (the credentials for the origin server). The second request continues
8237 // on the same connection.
8238 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558239 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098240 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378241 "Authorization: NTLM "),
8242 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098243 };
8244
8245 MockRead reads1[] = {
8246 // The origin server responds with a Type 2 message.
8247 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378248 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8249 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:098250 MockRead("Content-Type: text/html\r\n\r\n"),
8251 MockRead("You are not authorized to view this page\r\n"),
8252
8253 // Lastly we get the desired content.
8254 MockRead("HTTP/1.1 200 OK\r\n"),
8255 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028256 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:098257 };
Ryan Sleevib8d7ea02018-05-07 20:01:018258 SequencedSocketData data0(reads0, writes0);
8259 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:098260 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8261 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8262
8263 SSLSocketDataProvider ssl0(ASYNC, OK);
8264 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:168265 ssl0.next_protos_expected_in_ssl_config =
8266 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098267 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:168268 // When creating the second connection, only HTTP/1.1 should be allowed.
8269 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098270 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8271 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8272
8273 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8274 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8275
8276 TestCompletionCallback callback1;
8277 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
8278 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8279
8280 rv = callback1.WaitForResult();
8281 EXPECT_THAT(rv, IsOk());
8282
8283 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8284
8285 const HttpResponseInfo* response = trans.GetResponseInfo();
8286 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588287 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:098288
8289 TestCompletionCallback callback2;
8290
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378291 rv = trans.RestartWithAuth(
8292 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8293 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:098294 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8295
8296 rv = callback2.WaitForResult();
8297 EXPECT_THAT(rv, IsOk());
8298
8299 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8300
8301 response = trans.GetResponseInfo();
8302 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588303 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:098304
8305 TestCompletionCallback callback3;
8306
8307 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
8308 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8309
8310 rv = callback3.WaitForResult();
8311 EXPECT_THAT(rv, IsOk());
8312
8313 response = trans.GetResponseInfo();
8314 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588315 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028316 EXPECT_EQ(14, response->headers->GetContentLength());
8317
8318 std::string response_data;
8319 rv = ReadTransaction(&trans, &response_data);
8320 EXPECT_THAT(rv, IsOk());
8321 EXPECT_EQ("Please Login\r\n", response_data);
8322
8323 EXPECT_TRUE(data0.AllReadDataConsumed());
8324 EXPECT_TRUE(data0.AllWriteDataConsumed());
8325 EXPECT_TRUE(data1.AllReadDataConsumed());
8326 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:098327}
David Benjamin5cb91132018-04-06 05:54:498328
Matt Menkef2ee07c2019-08-29 02:10:368329#if BUILDFLAG(ENABLE_WEBSOCKETS)
8330
8331// Variant of above test using WebSockets.
8332TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
8333 const GURL kInitialUrl("https://server/");
8334 const GURL kWebSocketUrl("wss://server/");
8335 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
8336 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8337
8338 // Initial request establishes an H2 connection, which will then be reused for
8339 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
8340 // it won't create a new one.
8341 spdy::SpdyHeaderBlock initial_request_headers(
8342 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
8343 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
8344 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
8345 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
8346
8347 // Settings frame, indicating WebSockets is supported.
8348 spdy::SettingsMap settings;
8349 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
8350 spdy::SpdySerializedFrame settings_frame(
8351 spdy_util_.ConstructSpdySettings(settings));
8352
8353 // Response headers for first request. Body is never received, but that
8354 // shouldn't matter for the purposes of this test.
8355 spdy::SpdySerializedFrame initial_response(
8356 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8357
8358 // First WebSocket request, which has no credentials.
8359 spdy::SpdyHeaderBlock websocket_request_headers;
8360 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
8361 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
8362 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
8363 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
8364 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
8365 websocket_request_headers["origin"] = "http://server";
8366 websocket_request_headers["sec-websocket-version"] = "13";
8367 websocket_request_headers["sec-websocket-extensions"] =
8368 "permessage-deflate; client_max_window_bits";
8369 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
8370 3, std::move(websocket_request_headers), MEDIUM, false));
8371
8372 // Auth challenge to WebSocket request.
8373 spdy::SpdyHeaderBlock auth_challenge_headers;
8374 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
8375 auth_challenge_headers["www-authenticate"] = "NTLM";
8376 spdy::SpdySerializedFrame websocket_auth_challenge(
8377 spdy_util_.ConstructSpdyResponseHeaders(
8378 3, std::move(auth_challenge_headers), true));
8379
8380 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
8381 CreateMockWrite(settings_ack, 2),
8382 CreateMockWrite(websocket_request, 4),
8383 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
8384 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
8385 CreateMockRead(initial_response, 3),
8386 CreateMockRead(websocket_auth_challenge, 5),
8387 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
8388
8389 // Generate the NTLM messages based on known test data.
8390 std::string negotiate_msg;
8391 std::string challenge_msg;
8392 std::string authenticate_msg;
8393 base::Base64Encode(
8394 base::StringPiece(
8395 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
8396 base::size(ntlm::test::kExpectedNegotiateMsg)),
8397 &negotiate_msg);
8398 base::Base64Encode(
8399 base::StringPiece(
8400 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
8401 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
8402 &challenge_msg);
8403 base::Base64Encode(
8404 base::StringPiece(
8405 reinterpret_cast<const char*>(
8406 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
8407 base::size(
8408 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8409 &authenticate_msg);
8410
8411 // Retry yet again using HTTP/1.1.
8412 MockWrite writes1[] = {
8413 // After restarting with a null identity, this is the
8414 // request we should be issuing -- the final header line contains a Type
8415 // 1 message.
8416 MockWrite("GET / HTTP/1.1\r\n"
8417 "Host: server\r\n"
8418 "Connection: Upgrade\r\n"
8419 "Authorization: NTLM "),
8420 MockWrite(negotiate_msg.c_str()),
8421 MockWrite("\r\n"),
8422 MockWrite("Origin: http://server\r\n"
8423 "Sec-WebSocket-Version: 13\r\n"
8424 "Upgrade: websocket\r\n"
8425 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8426 "Sec-WebSocket-Extensions: permessage-deflate; "
8427 "client_max_window_bits\r\n\r\n"),
8428
8429 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8430 // (the credentials for the origin server). The second request continues
8431 // on the same connection.
8432 MockWrite("GET / HTTP/1.1\r\n"
8433 "Host: server\r\n"
8434 "Connection: Upgrade\r\n"
8435 "Authorization: NTLM "),
8436 MockWrite(authenticate_msg.c_str()),
8437 MockWrite("\r\n"),
8438 MockWrite("Origin: http://server\r\n"
8439 "Sec-WebSocket-Version: 13\r\n"
8440 "Upgrade: websocket\r\n"
8441 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8442 "Sec-WebSocket-Extensions: permessage-deflate; "
8443 "client_max_window_bits\r\n\r\n"),
8444 };
8445
8446 MockRead reads1[] = {
8447 // The origin server responds with a Type 2 message.
8448 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8449 MockRead("WWW-Authenticate: NTLM "),
8450 MockRead(challenge_msg.c_str()),
8451 MockRead("\r\n"),
8452 MockRead("Content-Length: 42\r\n"),
8453 MockRead("Content-Type: text/html\r\n\r\n"),
8454 MockRead("You are not authorized to view this page\r\n"),
8455
8456 // Lastly we get the desired content.
8457 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
8458 "Upgrade: websocket\r\n"
8459 "Connection: Upgrade\r\n"
8460 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
8461 };
8462 SequencedSocketData data0(reads0, writes0);
8463 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8464 SSLSocketDataProvider ssl0(ASYNC, OK);
8465 ssl0.next_proto = kProtoHTTP2;
8466 ssl0.next_protos_expected_in_ssl_config =
8467 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
8468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8469
8470 StaticSocketDataProvider data1(reads1, writes1);
8471 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8472 SSLSocketDataProvider ssl1(ASYNC, OK);
8473 // When creating the second connection, only HTTP/1.1 should be allowed.
8474 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
8475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8476
8477 session_deps_.enable_websocket_over_http2 = true;
8478 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8479
8480 HttpRequestInfo initial_request_info;
8481 initial_request_info.method = "GET";
8482 initial_request_info.url = kInitialUrl;
8483 initial_request_info.traffic_annotation =
8484 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8485 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
8486 TestCompletionCallback initial_callback;
8487 int rv = initial_trans.Start(&initial_request_info,
8488 initial_callback.callback(), NetLogWithSource());
8489 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
8490
8491 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
8492 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8493
8494 HttpRequestInfo websocket_request_info;
8495 websocket_request_info.method = "GET";
8496 websocket_request_info.url = kWebSocketUrl;
8497 websocket_request_info.traffic_annotation =
8498 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8499 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
8500 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
8501 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
8502 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
8503 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
8504 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
8505 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
8506
8507 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8508
8509 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
8510 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
8511 &websocket_stream_create_helper);
8512
8513 TestCompletionCallback websocket_callback;
8514 rv = websocket_trans.Start(&websocket_request_info,
8515 websocket_callback.callback(), NetLogWithSource());
8516 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8517
8518 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
8519
8520 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
8521 ASSERT_TRUE(response);
8522 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
8523
8524 rv = websocket_trans.RestartWithAuth(
8525 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8526 websocket_callback.callback());
8527 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8528
8529 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
8530
8531 response = websocket_trans.GetResponseInfo();
8532 ASSERT_TRUE(response);
8533 EXPECT_FALSE(response->auth_challenge.has_value());
8534
8535 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
8536 websocket_callback.callback());
8537 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8538
8539 // The server should have been marked as requiring HTTP/1.1. The important
8540 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
8541 // WSS.
8542 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
8543 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8544}
8545
8546#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
8547
David Benjamin5cb91132018-04-06 05:54:498548// Test that, if we have an NTLM proxy and the origin resets the connection, we
8549// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:378550// regression test for https://crbug.com/823387. The version interference probe
8551// has since been removed, but retain the regression test so we can update it if
8552// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:498553TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
8554 // The NTLM test data expects the proxy to be named 'server'. The origin is
8555 // https://origin/.
8556 session_deps_.proxy_resolution_service =
8557 ProxyResolutionService::CreateFixedFromPacResult(
8558 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
8559
David Benjamin151ec6b2019-08-02 19:38:528560 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:498561 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:078562 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:498563
8564 HttpRequestInfo request;
8565 request.method = "GET";
8566 request.url = GURL("https://origin/");
8567 request.traffic_annotation =
8568 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8569
8570 // Ensure load is not disrupted by flags which suppress behaviour specific
8571 // to other auth schemes.
8572 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
8573
8574 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
8575 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8576 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8577
8578 // Generate the NTLM messages based on known test data.
8579 std::string negotiate_msg;
8580 std::string challenge_msg;
8581 std::string authenticate_msg;
8582 base::Base64Encode(
8583 base::StringPiece(
8584 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248585 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:498586 &negotiate_msg);
8587 base::Base64Encode(
8588 base::StringPiece(
8589 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248590 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:498591 &challenge_msg);
8592 base::Base64Encode(
8593 base::StringPiece(
8594 reinterpret_cast<const char*>(
8595 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248596 base::size(
David Benjamin5cb91132018-04-06 05:54:498597 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8598 &authenticate_msg);
8599
8600 MockWrite data_writes[] = {
8601 // The initial CONNECT request.
8602 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8603 "Host: origin:443\r\n"
8604 "Proxy-Connection: keep-alive\r\n\r\n"),
8605
8606 // After restarting with an identity.
8607 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8608 "Host: origin:443\r\n"
8609 "Proxy-Connection: keep-alive\r\n"
8610 "Proxy-Authorization: NTLM "),
8611 MockWrite(negotiate_msg.c_str()),
8612 // End headers.
8613 MockWrite("\r\n\r\n"),
8614
8615 // The second restart.
8616 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8617 "Host: origin:443\r\n"
8618 "Proxy-Connection: keep-alive\r\n"
8619 "Proxy-Authorization: NTLM "),
8620 MockWrite(authenticate_msg.c_str()),
8621 // End headers.
8622 MockWrite("\r\n\r\n"),
8623 };
8624
8625 MockRead data_reads[] = {
8626 // The initial NTLM response.
8627 MockRead("HTTP/1.1 407 Access Denied\r\n"
8628 "Content-Length: 0\r\n"
8629 "Proxy-Authenticate: NTLM\r\n\r\n"),
8630
8631 // The NTLM challenge message.
8632 MockRead("HTTP/1.1 407 Access Denied\r\n"
8633 "Content-Length: 0\r\n"
8634 "Proxy-Authenticate: NTLM "),
8635 MockRead(challenge_msg.c_str()),
8636 // End headers.
8637 MockRead("\r\n\r\n"),
8638
8639 // Finally the tunnel is established.
8640 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
8641 };
8642
Ryan Sleevib8d7ea02018-05-07 20:01:018643 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:498644 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:498645 session_deps_.socket_factory->AddSocketDataProvider(&data);
8646 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:498647
8648 // Start the transaction. The proxy responds with an NTLM authentication
8649 // request.
8650 TestCompletionCallback callback;
8651 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8652 int rv = callback.GetResult(
8653 trans.Start(&request, callback.callback(), NetLogWithSource()));
8654
8655 EXPECT_THAT(rv, IsOk());
8656 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8657 const HttpResponseInfo* response = trans.GetResponseInfo();
8658 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588659 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:498660
David Benjamind61bd532019-04-23 21:11:378661 // Configure credentials and restart. The proxy responds with the challenge
8662 // message.
David Benjamin5cb91132018-04-06 05:54:498663 rv = callback.GetResult(trans.RestartWithAuth(
8664 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8665 callback.callback()));
8666 EXPECT_THAT(rv, IsOk());
8667 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8668 response = trans.GetResponseInfo();
8669 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588670 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:498671
David Benjamind61bd532019-04-23 21:11:378672 // Restart once more. The tunnel will be established and then the SSL
8673 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:498674 rv = callback.GetResult(
8675 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8676 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
8677}
8678
[email protected]ea9dc9a2009-09-05 00:43:328679#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:298680
[email protected]4ddaf2502008-10-23 18:26:198681// Test reading a server response which has only headers, and no body.
8682// After some maximum number of bytes is consumed, the transaction should
8683// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:018684TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:428685 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:198686 request.method = "GET";
bncce36dca22015-04-21 22:11:238687 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108688 request.traffic_annotation =
8689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:198690
danakj1fd259a02016-04-16 03:17:098691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168692 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278693
[email protected]b75b7b2f2009-10-06 00:54:538694 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:438695 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:538696 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:198697
8698 MockRead data_reads[] = {
8699 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:068700 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:198701 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:068702 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:198703 };
Ryan Sleevib8d7ea02018-05-07 20:01:018704 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078705 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:198706
[email protected]49639fa2011-12-20 23:22:418707 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:198708
tfarina42834112016-09-22 13:38:208709 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018710 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:198711
8712 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018713 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:198714}
[email protected]f4e426b2008-11-05 00:24:498715
8716// Make sure that we don't try to reuse a TCPClientSocket when failing to
8717// establish tunnel.
8718// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:018719TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:278720 HttpRequestInfo request;
8721 request.method = "GET";
bncce36dca22015-04-21 22:11:238722 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108723 request.traffic_annotation =
8724 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278725
[email protected]f4e426b2008-11-05 00:24:498726 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:498727 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
8728 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:018729
danakj1fd259a02016-04-16 03:17:098730 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:498731
bnc87dcefc2017-05-25 12:47:588732 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198733 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:498734
[email protected]f4e426b2008-11-05 00:24:498735 // Since we have proxy, should try to establish tunnel.
8736 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:178737 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8738 "Host: www.example.org:443\r\n"
8739 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:498740 };
8741
[email protected]77848d12008-11-14 00:00:228742 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:498743 // connection. Usually a proxy would return 501 (not implemented),
8744 // or 200 (tunnel established).
8745 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:238746 MockRead("HTTP/1.1 404 Not Found\r\n"),
8747 MockRead("Content-Length: 10\r\n\r\n"),
8748 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:498749 };
8750
Ryan Sleevib8d7ea02018-05-07 20:01:018751 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078752 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:498753
[email protected]49639fa2011-12-20 23:22:418754 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:498755
tfarina42834112016-09-22 13:38:208756 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018757 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:498758
8759 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018760 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:498761
[email protected]b4404c02009-04-10 16:38:528762 // Empty the current queue. This is necessary because idle sockets are
8763 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558764 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528765
[email protected]f4e426b2008-11-05 00:24:498766 // We now check to make sure the TCPClientSocket was not added back to
8767 // the pool.
[email protected]90499482013-06-01 00:39:508768 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498769 trans.reset();
fdoray92e35a72016-06-10 15:54:558770 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:498771 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:508772 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498773}
[email protected]372d34a2008-11-05 21:30:518774
[email protected]1b157c02009-04-21 01:55:408775// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:018776TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:428777 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:408778 request.method = "GET";
bncce36dca22015-04-21 22:11:238779 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108780 request.traffic_annotation =
8781 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:408782
danakj1fd259a02016-04-16 03:17:098783 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278784
bnc691fda62016-08-12 00:43:168785 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278786
[email protected]1b157c02009-04-21 01:55:408787 MockRead data_reads[] = {
8788 // A part of the response body is received with the response headers.
8789 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8790 // The rest of the response body is received in two parts.
8791 MockRead("lo"),
8792 MockRead(" world"),
8793 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068794 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:408795 };
8796
Ryan Sleevib8d7ea02018-05-07 20:01:018797 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078798 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:408799
[email protected]49639fa2011-12-20 23:22:418800 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:408801
tfarina42834112016-09-22 13:38:208802 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018803 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:408804
8805 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018806 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408807
bnc691fda62016-08-12 00:43:168808 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528809 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:408810
wezca1070932016-05-26 20:30:528811 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:408812 std::string status_line = response->headers->GetStatusLine();
8813 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8814
[email protected]90499482013-06-01 00:39:508815 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408816
8817 std::string response_data;
bnc691fda62016-08-12 00:43:168818 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018819 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408820 EXPECT_EQ("hello world", response_data);
8821
8822 // Empty the current queue. This is necessary because idle sockets are
8823 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558824 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:408825
8826 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508827 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408828}
8829
[email protected]76a505b2010-08-25 06:23:008830// Make sure that we recycle a SSL socket after reading all of the response
8831// body.
bncd16676a2016-07-20 16:23:018832TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008833 HttpRequestInfo request;
8834 request.method = "GET";
bncce36dca22015-04-21 22:11:238835 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108836 request.traffic_annotation =
8837 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008838
8839 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238840 MockWrite(
8841 "GET / HTTP/1.1\r\n"
8842 "Host: www.example.org\r\n"
8843 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008844 };
8845
8846 MockRead data_reads[] = {
8847 MockRead("HTTP/1.1 200 OK\r\n"),
8848 MockRead("Content-Length: 11\r\n\r\n"),
8849 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068850 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008851 };
8852
[email protected]8ddf8322012-02-23 18:08:068853 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078854 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:008855
Ryan Sleevib8d7ea02018-05-07 20:01:018856 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078857 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008858
[email protected]49639fa2011-12-20 23:22:418859 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008860
danakj1fd259a02016-04-16 03:17:098861 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168862 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008863
tfarina42834112016-09-22 13:38:208864 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008865
robpercival214763f2016-07-01 23:27:018866 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8867 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008868
bnc691fda62016-08-12 00:43:168869 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528870 ASSERT_TRUE(response);
8871 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008872 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8873
[email protected]90499482013-06-01 00:39:508874 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008875
8876 std::string response_data;
bnc691fda62016-08-12 00:43:168877 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018878 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008879 EXPECT_EQ("hello world", response_data);
8880
8881 // Empty the current queue. This is necessary because idle sockets are
8882 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558883 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008884
8885 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238886 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008887}
8888
8889// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8890// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018891TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008892 HttpRequestInfo request;
8893 request.method = "GET";
bncce36dca22015-04-21 22:11:238894 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108895 request.traffic_annotation =
8896 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008897
8898 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238899 MockWrite(
8900 "GET / HTTP/1.1\r\n"
8901 "Host: www.example.org\r\n"
8902 "Connection: keep-alive\r\n\r\n"),
8903 MockWrite(
8904 "GET / HTTP/1.1\r\n"
8905 "Host: www.example.org\r\n"
8906 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008907 };
8908
8909 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428910 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8911 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008912
[email protected]8ddf8322012-02-23 18:08:068913 SSLSocketDataProvider ssl(ASYNC, OK);
8914 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078915 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8916 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008917
Ryan Sleevib8d7ea02018-05-07 20:01:018918 StaticSocketDataProvider data(data_reads, data_writes);
8919 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078920 session_deps_.socket_factory->AddSocketDataProvider(&data);
8921 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008922
[email protected]49639fa2011-12-20 23:22:418923 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008924
danakj1fd259a02016-04-16 03:17:098925 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588926 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198927 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008928
tfarina42834112016-09-22 13:38:208929 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008930
robpercival214763f2016-07-01 23:27:018931 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8932 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008933
8934 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528935 ASSERT_TRUE(response);
8936 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008937 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8938
[email protected]90499482013-06-01 00:39:508939 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008940
8941 std::string response_data;
8942 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018943 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008944 EXPECT_EQ("hello world", response_data);
8945
8946 // Empty the current queue. This is necessary because idle sockets are
8947 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558948 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008949
8950 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238951 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008952
8953 // Now start the second transaction, which should reuse the previous socket.
8954
bnc87dcefc2017-05-25 12:47:588955 trans =
Jeremy Roman0579ed62017-08-29 15:56:198956 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008957
tfarina42834112016-09-22 13:38:208958 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008959
robpercival214763f2016-07-01 23:27:018960 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8961 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008962
8963 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528964 ASSERT_TRUE(response);
8965 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008966 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8967
[email protected]90499482013-06-01 00:39:508968 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008969
8970 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018971 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008972 EXPECT_EQ("hello world", response_data);
8973
8974 // Empty the current queue. This is necessary because idle sockets are
8975 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558976 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008977
8978 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238979 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008980}
8981
maksim.sisov0adf8592016-07-15 06:25:568982// Grab a socket, use it, and put it back into the pool. Then, make
8983// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018984TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568985 HttpRequestInfo request;
8986 request.method = "GET";
8987 request.url = GURL("http://www.example.org/");
8988 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108989 request.traffic_annotation =
8990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568991
8992 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8993
bnc691fda62016-08-12 00:43:168994 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568995
8996 MockRead data_reads[] = {
8997 // A part of the response body is received with the response headers.
8998 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8999 // The rest of the response body is received in two parts.
9000 MockRead("lo"), MockRead(" world"),
9001 MockRead("junk"), // Should not be read!!
9002 MockRead(SYNCHRONOUS, OK),
9003 };
9004
Ryan Sleevib8d7ea02018-05-07 20:01:019005 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:569006 session_deps_.socket_factory->AddSocketDataProvider(&data);
9007
9008 TestCompletionCallback callback;
9009
tfarina42834112016-09-22 13:38:209010 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569011 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9012
9013 EXPECT_THAT(callback.GetResult(rv), IsOk());
9014
bnc691fda62016-08-12 00:43:169015 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569016 ASSERT_TRUE(response);
9017 EXPECT_TRUE(response->headers);
9018 std::string status_line = response->headers->GetStatusLine();
9019 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9020
9021 // Make memory critical notification and ensure the transaction still has been
9022 // operating right.
9023 base::MemoryPressureListener::NotifyMemoryPressure(
9024 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9025 base::RunLoop().RunUntilIdle();
9026
9027 // Socket should not be flushed as long as it is not idle.
9028 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9029
9030 std::string response_data;
bnc691fda62016-08-12 00:43:169031 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569032 EXPECT_THAT(rv, IsOk());
9033 EXPECT_EQ("hello world", response_data);
9034
9035 // Empty the current queue. This is necessary because idle sockets are
9036 // added to the connection pool asynchronously with a PostTask.
9037 base::RunLoop().RunUntilIdle();
9038
9039 // We now check to make sure the socket was added back to the pool.
9040 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9041
9042 // Idle sockets should be flushed now.
9043 base::MemoryPressureListener::NotifyMemoryPressure(
9044 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9045 base::RunLoop().RunUntilIdle();
9046
9047 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9048}
9049
yucliu48f235d2018-01-11 00:59:559050// Disable idle socket closing on memory pressure.
9051// Grab a socket, use it, and put it back into the pool. Then, make
9052// low memory notification and ensure the socket pool is NOT flushed.
9053TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
9054 HttpRequestInfo request;
9055 request.method = "GET";
9056 request.url = GURL("http://www.example.org/");
9057 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109058 request.traffic_annotation =
9059 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:559060
9061 // Disable idle socket closing on memory pressure.
9062 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
9063 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9064
9065 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9066
9067 MockRead data_reads[] = {
9068 // A part of the response body is received with the response headers.
9069 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9070 // The rest of the response body is received in two parts.
9071 MockRead("lo"), MockRead(" world"),
9072 MockRead("junk"), // Should not be read!!
9073 MockRead(SYNCHRONOUS, OK),
9074 };
9075
Ryan Sleevib8d7ea02018-05-07 20:01:019076 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:559077 session_deps_.socket_factory->AddSocketDataProvider(&data);
9078
9079 TestCompletionCallback callback;
9080
9081 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9082 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9083
9084 EXPECT_THAT(callback.GetResult(rv), IsOk());
9085
9086 const HttpResponseInfo* response = trans.GetResponseInfo();
9087 ASSERT_TRUE(response);
9088 EXPECT_TRUE(response->headers);
9089 std::string status_line = response->headers->GetStatusLine();
9090 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9091
9092 // Make memory critical notification and ensure the transaction still has been
9093 // operating right.
9094 base::MemoryPressureListener::NotifyMemoryPressure(
9095 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9096 base::RunLoop().RunUntilIdle();
9097
9098 // Socket should not be flushed as long as it is not idle.
9099 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9100
9101 std::string response_data;
9102 rv = ReadTransaction(&trans, &response_data);
9103 EXPECT_THAT(rv, IsOk());
9104 EXPECT_EQ("hello world", response_data);
9105
9106 // Empty the current queue. This is necessary because idle sockets are
9107 // added to the connection pool asynchronously with a PostTask.
9108 base::RunLoop().RunUntilIdle();
9109
9110 // We now check to make sure the socket was added back to the pool.
9111 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9112
9113 // Idle sockets should NOT be flushed on moderate memory pressure.
9114 base::MemoryPressureListener::NotifyMemoryPressure(
9115 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
9116 base::RunLoop().RunUntilIdle();
9117
9118 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9119
9120 // Idle sockets should NOT be flushed on critical memory pressure.
9121 base::MemoryPressureListener::NotifyMemoryPressure(
9122 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9123 base::RunLoop().RunUntilIdle();
9124
9125 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9126}
9127
maksim.sisov0adf8592016-07-15 06:25:569128// Grab an SSL socket, use it, and put it back into the pool. Then, make
9129// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019130TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569131 HttpRequestInfo request;
9132 request.method = "GET";
9133 request.url = GURL("https://www.example.org/");
9134 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109135 request.traffic_annotation =
9136 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569137
9138 MockWrite data_writes[] = {
9139 MockWrite("GET / HTTP/1.1\r\n"
9140 "Host: www.example.org\r\n"
9141 "Connection: keep-alive\r\n\r\n"),
9142 };
9143
9144 MockRead data_reads[] = {
9145 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9146 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
9147
9148 SSLSocketDataProvider ssl(ASYNC, OK);
9149 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9150
Ryan Sleevib8d7ea02018-05-07 20:01:019151 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:569152 session_deps_.socket_factory->AddSocketDataProvider(&data);
9153
9154 TestCompletionCallback callback;
9155
9156 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169157 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569158
Matt Menke9d5e2c92019-02-05 01:42:239159 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:209160 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569161
9162 EXPECT_THAT(callback.GetResult(rv), IsOk());
9163
bnc691fda62016-08-12 00:43:169164 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569165 ASSERT_TRUE(response);
9166 ASSERT_TRUE(response->headers);
9167 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9168
9169 // Make memory critical notification and ensure the transaction still has been
9170 // operating right.
9171 base::MemoryPressureListener::NotifyMemoryPressure(
9172 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9173 base::RunLoop().RunUntilIdle();
9174
Matt Menke9d5e2c92019-02-05 01:42:239175 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569176
9177 std::string response_data;
bnc691fda62016-08-12 00:43:169178 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569179 EXPECT_THAT(rv, IsOk());
9180 EXPECT_EQ("hello world", response_data);
9181
9182 // Empty the current queue. This is necessary because idle sockets are
9183 // added to the connection pool asynchronously with a PostTask.
9184 base::RunLoop().RunUntilIdle();
9185
9186 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239187 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569188
9189 // Make memory notification once again and ensure idle socket is closed.
9190 base::MemoryPressureListener::NotifyMemoryPressure(
9191 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9192 base::RunLoop().RunUntilIdle();
9193
Matt Menke9d5e2c92019-02-05 01:42:239194 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569195}
9196
[email protected]b4404c02009-04-10 16:38:529197// Make sure that we recycle a socket after a zero-length response.
9198// http://crbug.com/9880
bncd16676a2016-07-20 16:23:019199TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:429200 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:529201 request.method = "GET";
bncce36dca22015-04-21 22:11:239202 request.url = GURL(
9203 "http://www.example.org/csi?v=3&s=web&action=&"
9204 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
9205 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
9206 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e62018-02-07 07:41:109207 request.traffic_annotation =
9208 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:529209
danakj1fd259a02016-04-16 03:17:099210 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279211
[email protected]b4404c02009-04-10 16:38:529212 MockRead data_reads[] = {
9213 MockRead("HTTP/1.1 204 No Content\r\n"
9214 "Content-Length: 0\r\n"
9215 "Content-Type: text/html\r\n\r\n"),
9216 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069217 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:529218 };
9219
Ryan Sleevib8d7ea02018-05-07 20:01:019220 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079221 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:529222
mmenkecc2298e2015-12-07 18:20:189223 // Transaction must be created after the MockReads, so it's destroyed before
9224 // them.
bnc691fda62016-08-12 00:43:169225 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:189226
[email protected]49639fa2011-12-20 23:22:419227 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:529228
tfarina42834112016-09-22 13:38:209229 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019230 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:529231
9232 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019233 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529234
bnc691fda62016-08-12 00:43:169235 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529236 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:529237
wezca1070932016-05-26 20:30:529238 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:529239 std::string status_line = response->headers->GetStatusLine();
9240 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
9241
[email protected]90499482013-06-01 00:39:509242 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529243
9244 std::string response_data;
bnc691fda62016-08-12 00:43:169245 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019246 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529247 EXPECT_EQ("", response_data);
9248
9249 // Empty the current queue. This is necessary because idle sockets are
9250 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559251 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529252
9253 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509254 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529255}
9256
bncd16676a2016-07-20 16:23:019257TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:099258 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:229259 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:199260 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:229261 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279262
[email protected]1c773ea12009-04-28 19:58:429263 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:519264 // Transaction 1: a GET request that succeeds. The socket is recycled
9265 // after use.
9266 request[0].method = "GET";
9267 request[0].url = GURL("http://www.google.com/");
9268 request[0].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109269 request[0].traffic_annotation =
9270 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519271 // Transaction 2: a POST request. Reuses the socket kept alive from
9272 // transaction 1. The first attempts fails when writing the POST data.
9273 // This causes the transaction to retry with a new socket. The second
9274 // attempt succeeds.
9275 request[1].method = "POST";
9276 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:279277 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:519278 request[1].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109279 request[1].traffic_annotation =
9280 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519281
danakj1fd259a02016-04-16 03:17:099282 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:519283
9284 // The first socket is used for transaction 1 and the first attempt of
9285 // transaction 2.
9286
9287 // The response of transaction 1.
9288 MockRead data_reads1[] = {
9289 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
9290 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069291 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519292 };
9293 // The mock write results of transaction 1 and the first attempt of
9294 // transaction 2.
9295 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:069296 MockWrite(SYNCHRONOUS, 64), // GET
9297 MockWrite(SYNCHRONOUS, 93), // POST
9298 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:519299 };
Ryan Sleevib8d7ea02018-05-07 20:01:019300 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:519301
9302 // The second socket is used for the second attempt of transaction 2.
9303
9304 // The response of transaction 2.
9305 MockRead data_reads2[] = {
9306 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
9307 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:069308 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519309 };
9310 // The mock write results of the second attempt of transaction 2.
9311 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:069312 MockWrite(SYNCHRONOUS, 93), // POST
9313 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:519314 };
Ryan Sleevib8d7ea02018-05-07 20:01:019315 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:519316
[email protected]bb88e1d32013-05-03 23:11:079317 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9318 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:519319
thestig9d3bb0c2015-01-24 00:49:519320 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:519321 "hello world", "welcome"
9322 };
9323
9324 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:169325 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:519326
[email protected]49639fa2011-12-20 23:22:419327 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:519328
tfarina42834112016-09-22 13:38:209329 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:519331
9332 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019333 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519334
bnc691fda62016-08-12 00:43:169335 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529336 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:519337
wezca1070932016-05-26 20:30:529338 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:519339 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9340
9341 std::string response_data;
bnc691fda62016-08-12 00:43:169342 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019343 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519344 EXPECT_EQ(kExpectedResponseData[i], response_data);
9345 }
9346}
[email protected]f9ee6b52008-11-08 06:46:239347
9348// Test the request-challenge-retry sequence for basic auth when there is
9349// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:169350// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:019351TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:429352 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239353 request.method = "GET";
bncce36dca22015-04-21 22:11:239354 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:419355 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:109356 request.traffic_annotation =
9357 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:299358
danakj1fd259a02016-04-16 03:17:099359 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169360 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279361
[email protected]a97cca42009-08-14 01:00:299362 // The password contains an escaped character -- for this test to pass it
9363 // will need to be unescaped by HttpNetworkTransaction.
9364 EXPECT_EQ("b%40r", request.url.password());
9365
[email protected]f9ee6b52008-11-08 06:46:239366 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239367 MockWrite(
9368 "GET / HTTP/1.1\r\n"
9369 "Host: www.example.org\r\n"
9370 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239371 };
9372
9373 MockRead data_reads1[] = {
9374 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9375 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9376 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069377 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239378 };
9379
[email protected]2262e3a2012-05-22 16:08:169380 // After the challenge above, the transaction will be restarted using the
9381 // identity from the url (foo, b@r) to answer the challenge.
9382 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239383 MockWrite(
9384 "GET / HTTP/1.1\r\n"
9385 "Host: www.example.org\r\n"
9386 "Connection: keep-alive\r\n"
9387 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169388 };
9389
9390 MockRead data_reads2[] = {
9391 MockRead("HTTP/1.0 200 OK\r\n"),
9392 MockRead("Content-Length: 100\r\n\r\n"),
9393 MockRead(SYNCHRONOUS, OK),
9394 };
9395
Ryan Sleevib8d7ea02018-05-07 20:01:019396 StaticSocketDataProvider data1(data_reads1, data_writes1);
9397 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079398 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9399 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239400
[email protected]49639fa2011-12-20 23:22:419401 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209402 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019403 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239404 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019405 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169406 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169407
9408 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169409 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019410 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169411 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019412 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169413 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229414
bnc691fda62016-08-12 00:43:169415 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529416 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169417
9418 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:589419 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169420
9421 EXPECT_EQ(100, response->headers->GetContentLength());
9422
9423 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559424 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:169425}
9426
9427// Test the request-challenge-retry sequence for basic auth when there is an
9428// incorrect identity in the URL. The identity from the URL should be used only
9429// once.
bncd16676a2016-07-20 16:23:019430TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:169431 HttpRequestInfo request;
9432 request.method = "GET";
9433 // Note: the URL has a username:password in it. The password "baz" is
9434 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:239435 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:169436
9437 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:109438 request.traffic_annotation =
9439 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:169440
danakj1fd259a02016-04-16 03:17:099441 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169442 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:169443
9444 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239445 MockWrite(
9446 "GET / HTTP/1.1\r\n"
9447 "Host: www.example.org\r\n"
9448 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169449 };
9450
9451 MockRead data_reads1[] = {
9452 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9453 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9454 MockRead("Content-Length: 10\r\n\r\n"),
9455 MockRead(SYNCHRONOUS, ERR_FAILED),
9456 };
9457
9458 // After the challenge above, the transaction will be restarted using the
9459 // identity from the url (foo, baz) to answer the challenge.
9460 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239461 MockWrite(
9462 "GET / HTTP/1.1\r\n"
9463 "Host: www.example.org\r\n"
9464 "Connection: keep-alive\r\n"
9465 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169466 };
9467
9468 MockRead data_reads2[] = {
9469 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9470 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9471 MockRead("Content-Length: 10\r\n\r\n"),
9472 MockRead(SYNCHRONOUS, ERR_FAILED),
9473 };
9474
9475 // After the challenge above, the transaction will be restarted using the
9476 // identity supplied by the user (foo, bar) to answer the challenge.
9477 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239478 MockWrite(
9479 "GET / HTTP/1.1\r\n"
9480 "Host: www.example.org\r\n"
9481 "Connection: keep-alive\r\n"
9482 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169483 };
9484
9485 MockRead data_reads3[] = {
9486 MockRead("HTTP/1.0 200 OK\r\n"),
9487 MockRead("Content-Length: 100\r\n\r\n"),
9488 MockRead(SYNCHRONOUS, OK),
9489 };
9490
Ryan Sleevib8d7ea02018-05-07 20:01:019491 StaticSocketDataProvider data1(data_reads1, data_writes1);
9492 StaticSocketDataProvider data2(data_reads2, data_writes2);
9493 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079494 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9495 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9496 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:169497
9498 TestCompletionCallback callback1;
9499
tfarina42834112016-09-22 13:38:209500 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019501 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169502
9503 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019504 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:169505
bnc691fda62016-08-12 00:43:169506 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169507 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169508 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019509 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169510 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019511 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169512 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169513
bnc691fda62016-08-12 00:43:169514 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529515 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589516 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:169517
9518 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169519 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019520 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169521 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019522 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169523 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169524
bnc691fda62016-08-12 00:43:169525 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529526 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169527
9528 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589529 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169530
9531 EXPECT_EQ(100, response->headers->GetContentLength());
9532
[email protected]ea9dc9a2009-09-05 00:43:329533 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559534 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:329535}
9536
[email protected]2217aa22013-10-11 03:03:549537
9538// Test the request-challenge-retry sequence for basic auth when there is a
9539// correct identity in the URL, but its use is being suppressed. The identity
9540// from the URL should never be used.
bncd16676a2016-07-20 16:23:019541TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:549542 HttpRequestInfo request;
9543 request.method = "GET";
bncce36dca22015-04-21 22:11:239544 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:549545 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e62018-02-07 07:41:109546 request.traffic_annotation =
9547 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:549548
danakj1fd259a02016-04-16 03:17:099549 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169550 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:549551
9552 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239553 MockWrite(
9554 "GET / HTTP/1.1\r\n"
9555 "Host: www.example.org\r\n"
9556 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549557 };
9558
9559 MockRead data_reads1[] = {
9560 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9561 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9562 MockRead("Content-Length: 10\r\n\r\n"),
9563 MockRead(SYNCHRONOUS, ERR_FAILED),
9564 };
9565
9566 // After the challenge above, the transaction will be restarted using the
9567 // identity supplied by the user, not the one in the URL, to answer the
9568 // challenge.
9569 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239570 MockWrite(
9571 "GET / HTTP/1.1\r\n"
9572 "Host: www.example.org\r\n"
9573 "Connection: keep-alive\r\n"
9574 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549575 };
9576
9577 MockRead data_reads3[] = {
9578 MockRead("HTTP/1.0 200 OK\r\n"),
9579 MockRead("Content-Length: 100\r\n\r\n"),
9580 MockRead(SYNCHRONOUS, OK),
9581 };
9582
Ryan Sleevib8d7ea02018-05-07 20:01:019583 StaticSocketDataProvider data1(data_reads1, data_writes1);
9584 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:549585 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9586 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9587
9588 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209589 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019590 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549591 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019592 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169593 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549594
bnc691fda62016-08-12 00:43:169595 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529596 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589597 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:549598
9599 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169600 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019601 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549602 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019603 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169604 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549605
bnc691fda62016-08-12 00:43:169606 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529607 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:549608
9609 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589610 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:549611 EXPECT_EQ(100, response->headers->GetContentLength());
9612
9613 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559614 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:549615}
9616
[email protected]f9ee6b52008-11-08 06:46:239617// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:019618TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:099619 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:239620
9621 // Transaction 1: authenticate (foo, bar) on MyRealm1
9622 {
[email protected]1c773ea12009-04-28 19:58:429623 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239624 request.method = "GET";
bncce36dca22015-04-21 22:11:239625 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:109626 request.traffic_annotation =
9627 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239628
bnc691fda62016-08-12 00:43:169629 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279630
[email protected]f9ee6b52008-11-08 06:46:239631 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239632 MockWrite(
9633 "GET /x/y/z HTTP/1.1\r\n"
9634 "Host: www.example.org\r\n"
9635 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239636 };
9637
9638 MockRead data_reads1[] = {
9639 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9640 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9641 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069642 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239643 };
9644
9645 // Resend with authorization (username=foo, password=bar)
9646 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239647 MockWrite(
9648 "GET /x/y/z HTTP/1.1\r\n"
9649 "Host: www.example.org\r\n"
9650 "Connection: keep-alive\r\n"
9651 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239652 };
9653
9654 // Sever accepts the authorization.
9655 MockRead data_reads2[] = {
9656 MockRead("HTTP/1.0 200 OK\r\n"),
9657 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069658 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239659 };
9660
Ryan Sleevib8d7ea02018-05-07 20:01:019661 StaticSocketDataProvider data1(data_reads1, data_writes1);
9662 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079663 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9664 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239665
[email protected]49639fa2011-12-20 23:22:419666 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239667
tfarina42834112016-09-22 13:38:209668 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019669 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239670
9671 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019672 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239673
bnc691fda62016-08-12 00:43:169674 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529675 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589676 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239677
[email protected]49639fa2011-12-20 23:22:419678 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239679
bnc691fda62016-08-12 00:43:169680 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9681 callback2.callback());
robpercival214763f2016-07-01 23:27:019682 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239683
9684 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019685 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239686
bnc691fda62016-08-12 00:43:169687 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529688 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589689 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239690 EXPECT_EQ(100, response->headers->GetContentLength());
9691 }
9692
9693 // ------------------------------------------------------------------------
9694
9695 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
9696 {
[email protected]1c773ea12009-04-28 19:58:429697 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239698 request.method = "GET";
9699 // Note that Transaction 1 was at /x/y/z, so this is in the same
9700 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:239701 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109702 request.traffic_annotation =
9703 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239704
bnc691fda62016-08-12 00:43:169705 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279706
[email protected]f9ee6b52008-11-08 06:46:239707 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239708 MockWrite(
9709 "GET /x/y/a/b HTTP/1.1\r\n"
9710 "Host: www.example.org\r\n"
9711 "Connection: keep-alive\r\n"
9712 // Send preemptive authorization for MyRealm1
9713 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239714 };
9715
9716 // The server didn't like the preemptive authorization, and
9717 // challenges us for a different realm (MyRealm2).
9718 MockRead data_reads1[] = {
9719 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9720 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
9721 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069722 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239723 };
9724
9725 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
9726 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239727 MockWrite(
9728 "GET /x/y/a/b HTTP/1.1\r\n"
9729 "Host: www.example.org\r\n"
9730 "Connection: keep-alive\r\n"
9731 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239732 };
9733
9734 // Sever accepts the authorization.
9735 MockRead data_reads2[] = {
9736 MockRead("HTTP/1.0 200 OK\r\n"),
9737 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069738 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239739 };
9740
Ryan Sleevib8d7ea02018-05-07 20:01:019741 StaticSocketDataProvider data1(data_reads1, data_writes1);
9742 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079743 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9744 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239745
[email protected]49639fa2011-12-20 23:22:419746 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239747
tfarina42834112016-09-22 13:38:209748 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019749 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239750
9751 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019752 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239753
bnc691fda62016-08-12 00:43:169754 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529755 ASSERT_TRUE(response);
9756 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:049757 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:439758 EXPECT_EQ("http://www.example.org",
9759 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049760 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:199761 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:239762
[email protected]49639fa2011-12-20 23:22:419763 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239764
bnc691fda62016-08-12 00:43:169765 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
9766 callback2.callback());
robpercival214763f2016-07-01 23:27:019767 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239768
9769 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019770 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239771
bnc691fda62016-08-12 00:43:169772 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529773 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589774 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239775 EXPECT_EQ(100, response->headers->GetContentLength());
9776 }
9777
9778 // ------------------------------------------------------------------------
9779
9780 // Transaction 3: Resend a request in MyRealm's protection space --
9781 // succeed with preemptive authorization.
9782 {
[email protected]1c773ea12009-04-28 19:58:429783 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239784 request.method = "GET";
bncce36dca22015-04-21 22:11:239785 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e62018-02-07 07:41:109786 request.traffic_annotation =
9787 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239788
bnc691fda62016-08-12 00:43:169789 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279790
[email protected]f9ee6b52008-11-08 06:46:239791 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239792 MockWrite(
9793 "GET /x/y/z2 HTTP/1.1\r\n"
9794 "Host: www.example.org\r\n"
9795 "Connection: keep-alive\r\n"
9796 // The authorization for MyRealm1 gets sent preemptively
9797 // (since the url is in the same protection space)
9798 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239799 };
9800
9801 // Sever accepts the preemptive authorization
9802 MockRead data_reads1[] = {
9803 MockRead("HTTP/1.0 200 OK\r\n"),
9804 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069805 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239806 };
9807
Ryan Sleevib8d7ea02018-05-07 20:01:019808 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079809 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:239810
[email protected]49639fa2011-12-20 23:22:419811 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239812
tfarina42834112016-09-22 13:38:209813 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019814 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239815
9816 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019817 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239818
bnc691fda62016-08-12 00:43:169819 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529820 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:239821
Emily Starkf2c9bbd2019-04-09 17:08:589822 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239823 EXPECT_EQ(100, response->headers->GetContentLength());
9824 }
9825
9826 // ------------------------------------------------------------------------
9827
9828 // Transaction 4: request another URL in MyRealm (however the
9829 // url is not known to belong to the protection space, so no pre-auth).
9830 {
[email protected]1c773ea12009-04-28 19:58:429831 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239832 request.method = "GET";
bncce36dca22015-04-21 22:11:239833 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e62018-02-07 07:41:109834 request.traffic_annotation =
9835 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239836
bnc691fda62016-08-12 00:43:169837 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279838
[email protected]f9ee6b52008-11-08 06:46:239839 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239840 MockWrite(
9841 "GET /x/1 HTTP/1.1\r\n"
9842 "Host: www.example.org\r\n"
9843 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239844 };
9845
9846 MockRead data_reads1[] = {
9847 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9848 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9849 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069850 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239851 };
9852
9853 // Resend with authorization from MyRealm's cache.
9854 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239855 MockWrite(
9856 "GET /x/1 HTTP/1.1\r\n"
9857 "Host: www.example.org\r\n"
9858 "Connection: keep-alive\r\n"
9859 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239860 };
9861
9862 // Sever accepts the authorization.
9863 MockRead data_reads2[] = {
9864 MockRead("HTTP/1.0 200 OK\r\n"),
9865 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069866 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239867 };
9868
Ryan Sleevib8d7ea02018-05-07 20:01:019869 StaticSocketDataProvider data1(data_reads1, data_writes1);
9870 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079871 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9872 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239873
[email protected]49639fa2011-12-20 23:22:419874 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239875
tfarina42834112016-09-22 13:38:209876 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019877 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239878
9879 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019880 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239881
bnc691fda62016-08-12 00:43:169882 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419883 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169884 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019885 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229886 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019887 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169888 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229889
bnc691fda62016-08-12 00:43:169890 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529891 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589892 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239893 EXPECT_EQ(100, response->headers->GetContentLength());
9894 }
9895
9896 // ------------------------------------------------------------------------
9897
9898 // Transaction 5: request a URL in MyRealm, but the server rejects the
9899 // cached identity. Should invalidate and re-prompt.
9900 {
[email protected]1c773ea12009-04-28 19:58:429901 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239902 request.method = "GET";
bncce36dca22015-04-21 22:11:239903 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e62018-02-07 07:41:109904 request.traffic_annotation =
9905 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239906
bnc691fda62016-08-12 00:43:169907 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279908
[email protected]f9ee6b52008-11-08 06:46:239909 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239910 MockWrite(
9911 "GET /p/q/t HTTP/1.1\r\n"
9912 "Host: www.example.org\r\n"
9913 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239914 };
9915
9916 MockRead data_reads1[] = {
9917 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9918 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9919 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069920 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239921 };
9922
9923 // Resend with authorization from cache for MyRealm.
9924 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239925 MockWrite(
9926 "GET /p/q/t HTTP/1.1\r\n"
9927 "Host: www.example.org\r\n"
9928 "Connection: keep-alive\r\n"
9929 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239930 };
9931
9932 // Sever rejects the authorization.
9933 MockRead data_reads2[] = {
9934 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9935 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9936 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069937 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239938 };
9939
9940 // At this point we should prompt for new credentials for MyRealm.
9941 // Restart with username=foo3, password=foo4.
9942 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239943 MockWrite(
9944 "GET /p/q/t HTTP/1.1\r\n"
9945 "Host: www.example.org\r\n"
9946 "Connection: keep-alive\r\n"
9947 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239948 };
9949
9950 // Sever accepts the authorization.
9951 MockRead data_reads3[] = {
9952 MockRead("HTTP/1.0 200 OK\r\n"),
9953 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069954 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239955 };
9956
Ryan Sleevib8d7ea02018-05-07 20:01:019957 StaticSocketDataProvider data1(data_reads1, data_writes1);
9958 StaticSocketDataProvider data2(data_reads2, data_writes2);
9959 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079960 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9961 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9962 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239963
[email protected]49639fa2011-12-20 23:22:419964 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239965
tfarina42834112016-09-22 13:38:209966 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019967 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239968
9969 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019970 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239971
bnc691fda62016-08-12 00:43:169972 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419973 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169974 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019975 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229976 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019977 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169978 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229979
bnc691fda62016-08-12 00:43:169980 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529981 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589982 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239983
[email protected]49639fa2011-12-20 23:22:419984 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239985
bnc691fda62016-08-12 00:43:169986 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9987 callback3.callback());
robpercival214763f2016-07-01 23:27:019988 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239989
[email protected]0757e7702009-03-27 04:00:229990 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019991 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239992
bnc691fda62016-08-12 00:43:169993 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529994 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589995 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239996 EXPECT_EQ(100, response->headers->GetContentLength());
9997 }
9998}
[email protected]89ceba9a2009-03-21 03:46:069999
[email protected]3c32c5f2010-05-18 15:18:1210000// Tests that nonce count increments when multiple auth attempts
10001// are started with the same nonce.
bncd16676a2016-07-20 16:23:0110002TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:4410003 HttpAuthHandlerDigest::Factory* digest_factory =
10004 new HttpAuthHandlerDigest::Factory();
10005 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
10006 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
10007 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:0710008 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:0910009 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:1210010
10011 // Transaction 1: authenticate (foo, bar) on MyRealm1
10012 {
[email protected]3c32c5f2010-05-18 15:18:1210013 HttpRequestInfo request;
10014 request.method = "GET";
bncce36dca22015-04-21 22:11:2310015 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:1010016 request.traffic_annotation =
10017 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210018
bnc691fda62016-08-12 00:43:1610019 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710020
[email protected]3c32c5f2010-05-18 15:18:1210021 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310022 MockWrite(
10023 "GET /x/y/z HTTP/1.1\r\n"
10024 "Host: www.example.org\r\n"
10025 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210026 };
10027
10028 MockRead data_reads1[] = {
10029 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10030 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
10031 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610032 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210033 };
10034
10035 // Resend with authorization (username=foo, password=bar)
10036 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310037 MockWrite(
10038 "GET /x/y/z HTTP/1.1\r\n"
10039 "Host: www.example.org\r\n"
10040 "Connection: keep-alive\r\n"
10041 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10042 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
10043 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
10044 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210045 };
10046
10047 // Sever accepts the authorization.
10048 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:0810049 MockRead("HTTP/1.0 200 OK\r\n"),
10050 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210051 };
10052
Ryan Sleevib8d7ea02018-05-07 20:01:0110053 StaticSocketDataProvider data1(data_reads1, data_writes1);
10054 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710055 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10056 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:1210057
[email protected]49639fa2011-12-20 23:22:4110058 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210059
tfarina42834112016-09-22 13:38:2010060 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110061 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210062
10063 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110064 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210065
bnc691fda62016-08-12 00:43:1610066 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210067 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810068 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:1210069
[email protected]49639fa2011-12-20 23:22:4110070 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:1210071
bnc691fda62016-08-12 00:43:1610072 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10073 callback2.callback());
robpercival214763f2016-07-01 23:27:0110074 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210075
10076 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110077 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210078
bnc691fda62016-08-12 00:43:1610079 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210080 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810081 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210082 }
10083
10084 // ------------------------------------------------------------------------
10085
10086 // Transaction 2: Request another resource in digestive's protection space.
10087 // This will preemptively add an Authorization header which should have an
10088 // "nc" value of 2 (as compared to 1 in the first use.
10089 {
[email protected]3c32c5f2010-05-18 15:18:1210090 HttpRequestInfo request;
10091 request.method = "GET";
10092 // Note that Transaction 1 was at /x/y/z, so this is in the same
10093 // protection space as digest.
bncce36dca22015-04-21 22:11:2310094 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:1010095 request.traffic_annotation =
10096 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210097
bnc691fda62016-08-12 00:43:1610098 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710099
[email protected]3c32c5f2010-05-18 15:18:1210100 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310101 MockWrite(
10102 "GET /x/y/a/b HTTP/1.1\r\n"
10103 "Host: www.example.org\r\n"
10104 "Connection: keep-alive\r\n"
10105 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10106 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
10107 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
10108 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210109 };
10110
10111 // Sever accepts the authorization.
10112 MockRead data_reads1[] = {
10113 MockRead("HTTP/1.0 200 OK\r\n"),
10114 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610115 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210116 };
10117
Ryan Sleevib8d7ea02018-05-07 20:01:0110118 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710119 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:1210120
[email protected]49639fa2011-12-20 23:22:4110121 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210122
tfarina42834112016-09-22 13:38:2010123 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110124 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210125
10126 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110127 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210128
bnc691fda62016-08-12 00:43:1610129 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210130 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810131 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210132 }
10133}
10134
[email protected]89ceba9a2009-03-21 03:46:0610135// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:0110136TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:0610137 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:0910138 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610139 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:0610140
10141 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:4410142 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:1610143 trans.read_buf_len_ = 15;
10144 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:0610145
10146 // Setup state in response_
bnc691fda62016-08-12 00:43:1610147 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:5810148 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:0810149 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:5710150 response->response_time = base::Time::Now();
10151 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:0610152
10153 { // Setup state for response_.vary_data
10154 HttpRequestInfo request;
10155 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
10156 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:2710157 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:4310158 request.extra_headers.SetHeader("Foo", "1");
10159 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:5010160 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:0610161 }
10162
10163 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:1610164 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:0610165
10166 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:1610167 EXPECT_FALSE(trans.read_buf_);
10168 EXPECT_EQ(0, trans.read_buf_len_);
10169 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:5810170 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:5210171 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:0410172 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:0810173 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:5710174 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:0610175}
10176
[email protected]bacff652009-03-31 17:50:3310177// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:0110178TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:3310179 HttpRequestInfo request;
10180 request.method = "GET";
bncce36dca22015-04-21 22:11:2310181 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010182 request.traffic_annotation =
10183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310184
danakj1fd259a02016-04-16 03:17:0910185 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610186 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710187
[email protected]bacff652009-03-31 17:50:3310188 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310189 MockWrite(
10190 "GET / HTTP/1.1\r\n"
10191 "Host: www.example.org\r\n"
10192 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310193 };
10194
10195 MockRead data_reads[] = {
10196 MockRead("HTTP/1.0 200 OK\r\n"),
10197 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10198 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610199 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310200 };
10201
[email protected]5ecc992a42009-11-11 01:41:5910202 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:0110203 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610204 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10205 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310206
[email protected]bb88e1d32013-05-03 23:11:0710207 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10208 session_deps_.socket_factory->AddSocketDataProvider(&data);
10209 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10210 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310211
[email protected]49639fa2011-12-20 23:22:4110212 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310213
tfarina42834112016-09-22 13:38:2010214 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110215 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310216
10217 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110218 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310219
bnc691fda62016-08-12 00:43:1610220 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110221 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310222
10223 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110224 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310225
bnc691fda62016-08-12 00:43:1610226 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310227
wezca1070932016-05-26 20:30:5210228 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310229 EXPECT_EQ(100, response->headers->GetContentLength());
10230}
10231
10232// Test HTTPS connections to a site with a bad certificate, going through a
10233// proxy
bncd16676a2016-07-20 16:23:0110234TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910235 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10236 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310237
10238 HttpRequestInfo request;
10239 request.method = "GET";
bncce36dca22015-04-21 22:11:2310240 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010241 request.traffic_annotation =
10242 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310243
10244 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710245 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10246 "Host: www.example.org:443\r\n"
10247 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310248 };
10249
10250 MockRead proxy_reads[] = {
10251 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610252 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:3310253 };
10254
10255 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710256 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10257 "Host: www.example.org:443\r\n"
10258 "Proxy-Connection: keep-alive\r\n\r\n"),
10259 MockWrite("GET / HTTP/1.1\r\n"
10260 "Host: www.example.org\r\n"
10261 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310262 };
10263
10264 MockRead data_reads[] = {
10265 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10266 MockRead("HTTP/1.0 200 OK\r\n"),
10267 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10268 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610269 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310270 };
10271
Ryan Sleevib8d7ea02018-05-07 20:01:0110272 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
10273 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610274 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10275 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310276
[email protected]bb88e1d32013-05-03 23:11:0710277 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10278 session_deps_.socket_factory->AddSocketDataProvider(&data);
10279 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10280 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310281
[email protected]49639fa2011-12-20 23:22:4110282 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310283
10284 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:0710285 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:3310286
danakj1fd259a02016-04-16 03:17:0910287 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610288 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:3310289
tfarina42834112016-09-22 13:38:2010290 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110291 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310292
10293 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110294 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310295
bnc691fda62016-08-12 00:43:1610296 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110297 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310298
10299 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110300 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310301
bnc691fda62016-08-12 00:43:1610302 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310303
wezca1070932016-05-26 20:30:5210304 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310305 EXPECT_EQ(100, response->headers->GetContentLength());
10306 }
10307}
10308
[email protected]2df19bb2010-08-25 20:13:4610309
10310// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:0110311TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910312 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910313 ProxyResolutionService::CreateFixedFromPacResult(
10314 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110315 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710316 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:4610317
10318 HttpRequestInfo request;
10319 request.method = "GET";
bncce36dca22015-04-21 22:11:2310320 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010321 request.traffic_annotation =
10322 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610323
10324 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710325 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10326 "Host: www.example.org:443\r\n"
10327 "Proxy-Connection: keep-alive\r\n\r\n"),
10328 MockWrite("GET / HTTP/1.1\r\n"
10329 "Host: www.example.org\r\n"
10330 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610331 };
10332
10333 MockRead data_reads[] = {
10334 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10335 MockRead("HTTP/1.1 200 OK\r\n"),
10336 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10337 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610338 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610339 };
10340
Ryan Sleevib8d7ea02018-05-07 20:01:0110341 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610342 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10343 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:4610344
[email protected]bb88e1d32013-05-03 23:11:0710345 session_deps_.socket_factory->AddSocketDataProvider(&data);
10346 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10347 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:4610348
[email protected]49639fa2011-12-20 23:22:4110349 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610350
danakj1fd259a02016-04-16 03:17:0910351 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610352 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610353
tfarina42834112016-09-22 13:38:2010354 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110355 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610356
10357 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110358 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610359 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610360
wezca1070932016-05-26 20:30:5210361 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610362
tbansal2ecbbc72016-10-06 17:15:4710363 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:4610364 EXPECT_TRUE(response->headers->IsKeepAlive());
10365 EXPECT_EQ(200, response->headers->response_code());
10366 EXPECT_EQ(100, response->headers->GetContentLength());
10367 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2010368
10369 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610370 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010371 TestLoadTimingNotReusedWithPac(load_timing_info,
10372 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:4610373}
10374
Eric Roman695a7872019-04-16 21:53:2910375// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:0110376TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910377 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910378 ProxyResolutionService::CreateFixedFromPacResult(
10379 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110380 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710381 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:2910382
Matt Menkeecfecfc72019-02-05 19:15:2810383 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10384 session_deps_.host_resolver->set_ondemand_mode(true);
10385
[email protected]511f6f52010-12-17 03:58:2910386 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:1210387 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:2910388 request.method = "GET";
bncce36dca22015-04-21 22:11:2310389 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010390 request.traffic_annotation =
10391 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910392
10393 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810394 MockWrite(ASYNC, 0,
10395 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710396 "Host: www.example.org:443\r\n"
10397 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910398 };
10399
10400 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810401 // Pause on first read.
10402 MockRead(ASYNC, ERR_IO_PENDING, 1),
10403 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
10404 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
10405 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910406 };
10407
Matt Menkeecfecfc72019-02-05 19:15:2810408 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610409 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910410
[email protected]bb88e1d32013-05-03 23:11:0710411 session_deps_.socket_factory->AddSocketDataProvider(&data);
10412 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910413
[email protected]49639fa2011-12-20 23:22:4110414 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910415
danakj1fd259a02016-04-16 03:17:0910416 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610417 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910418
tfarina42834112016-09-22 13:38:2010419 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110420 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810421 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
10422
10423 // Host resolution takes |kTimeIncrement|.
10424 FastForwardBy(kTimeIncrement);
10425 // Resolving the current request with |ResolveNow| will cause the pending
10426 // request to instantly complete, and the async connect will start as well.
10427 session_deps_.host_resolver->ResolveOnlyRequestNow();
10428
10429 // Connecting takes |kTimeIncrement|.
10430 FastForwardBy(kTimeIncrement);
10431 data.RunUntilPaused();
10432
10433 // The server takes |kTimeIncrement| to respond.
10434 FastForwardBy(kTimeIncrement);
10435 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910436
10437 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910438 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910439}
10440
Eric Roman74103c72019-02-21 00:23:1210441// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
10442TEST_F(HttpNetworkTransactionTest,
10443 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
10444 base::HistogramTester histograms;
10445 session_deps_.proxy_resolution_service =
10446 ProxyResolutionService::CreateFixedFromPacResult(
10447 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10448 TestNetLog net_log;
10449 session_deps_.net_log = &net_log;
10450
10451 HttpRequestInfo request;
10452 request.method = "GET";
10453 request.url = GURL("https://www.example.org/");
10454 request.traffic_annotation =
10455 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10456
10457 MockWrite data_writes[] = {
10458 MockWrite(ASYNC, 0,
10459 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10460 "Host: www.example.org:443\r\n"
10461 "Proxy-Connection: keep-alive\r\n\r\n"),
10462 };
10463
10464 MockRead data_reads[] = {
10465 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10466 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10467 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10468 };
10469
10470 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10471 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10472
10473 session_deps_.socket_factory->AddSocketDataProvider(&data);
10474 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10475
10476 TestCompletionCallback callback;
10477
10478 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10479 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10480
10481 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10482 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10483
10484 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910485 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210486}
10487
10488// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
10489// request for main frames.
10490TEST_F(HttpNetworkTransactionTest,
10491 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
10492 base::HistogramTester histograms;
10493 session_deps_.proxy_resolution_service =
10494 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
10495 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10496 TestNetLog net_log;
10497 session_deps_.net_log = &net_log;
10498
10499 HttpRequestInfo request;
10500 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
10501 request.method = "GET";
10502 request.url = GURL("https://www.example.org/");
10503 request.traffic_annotation =
10504 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10505
10506 MockWrite data_writes[] = {
10507 MockWrite(ASYNC, 0,
10508 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10509 "Host: www.example.org:443\r\n"
10510 "Proxy-Connection: keep-alive\r\n\r\n"),
10511 };
10512
10513 MockRead data_reads[] = {
10514 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10515 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10516 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10517 };
10518
10519 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10520 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10521
10522 session_deps_.socket_factory->AddSocketDataProvider(&data);
10523 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10524
10525 TestCompletionCallback callback;
10526
10527 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10528 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10529
10530 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10531 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10532
10533 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910534 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210535}
10536
Eric Roman695a7872019-04-16 21:53:2910537// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:1210538// frames.
bncd16676a2016-07-20 16:23:0110539TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:1210540 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:4910541 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10542 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:2810543 TestNetLog net_log;
10544 session_deps_.net_log = &net_log;
10545
Matt Menkeecfecfc72019-02-05 19:15:2810546 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10547 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:2910548
10549 HttpRequestInfo request;
10550 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:1210551 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:2310552 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010553 request.traffic_annotation =
10554 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910555
Ryan Hamilton0239aac2018-05-19 00:03:1310556 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410557 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10558 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310559 spdy::SpdySerializedFrame goaway(
10560 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910561 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110562 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:2810563 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:2910564 };
10565
10566 static const char* const kExtraHeaders[] = {
10567 "location",
10568 "http://login.example.com/",
10569 };
Ryan Hamilton0239aac2018-05-19 00:03:1310570 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410571 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:2910572 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810573 // Pause on first read.
10574 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
10575 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910576 };
10577
Matt Menkeecfecfc72019-02-05 19:15:2810578 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610579 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610580 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910581
[email protected]bb88e1d32013-05-03 23:11:0710582 session_deps_.socket_factory->AddSocketDataProvider(&data);
10583 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910584
[email protected]49639fa2011-12-20 23:22:4110585 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910586
danakj1fd259a02016-04-16 03:17:0910587 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610588 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910589
tfarina42834112016-09-22 13:38:2010590 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110591 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810592 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:2910593
Matt Menkeecfecfc72019-02-05 19:15:2810594 // Host resolution takes |kTimeIncrement|.
10595 FastForwardBy(kTimeIncrement);
10596 // Resolving the current request with |ResolveNow| will cause the pending
10597 // request to instantly complete, and the async connect will start as well.
10598 session_deps_.host_resolver->ResolveOnlyRequestNow();
10599
10600 // Connecting takes |kTimeIncrement|.
10601 FastForwardBy(kTimeIncrement);
10602 data.RunUntilPaused();
10603
10604 FastForwardBy(kTimeIncrement);
10605 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910606 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910607 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910608}
10609
[email protected]4eddbc732012-08-09 05:40:1710610// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110611TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910612 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10613 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910614
10615 HttpRequestInfo request;
10616 request.method = "GET";
bncce36dca22015-04-21 22:11:2310617 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010618 request.traffic_annotation =
10619 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910620
10621 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710622 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10623 "Host: www.example.org:443\r\n"
10624 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910625 };
10626
10627 MockRead data_reads[] = {
10628 MockRead("HTTP/1.1 404 Not Found\r\n"),
10629 MockRead("Content-Length: 23\r\n\r\n"),
10630 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:0610631 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:2910632 };
10633
Ryan Sleevib8d7ea02018-05-07 20:01:0110634 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610635 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910636
[email protected]bb88e1d32013-05-03 23:11:0710637 session_deps_.socket_factory->AddSocketDataProvider(&data);
10638 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910639
[email protected]49639fa2011-12-20 23:22:4110640 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910641
danakj1fd259a02016-04-16 03:17:0910642 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610643 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910644
tfarina42834112016-09-22 13:38:2010645 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110646 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910647
10648 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110649 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910650
ttuttle960fcbf2016-04-19 13:26:3210651 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910652}
10653
[email protected]4eddbc732012-08-09 05:40:1710654// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110655TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910656 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10657 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910658
10659 HttpRequestInfo request;
10660 request.method = "GET";
bncce36dca22015-04-21 22:11:2310661 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010662 request.traffic_annotation =
10663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910664
Ryan Hamilton0239aac2018-05-19 00:03:1310665 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410666 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10667 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310668 spdy::SpdySerializedFrame rst(
10669 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910670 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110671 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:2910672 };
10673
10674 static const char* const kExtraHeaders[] = {
10675 "location",
10676 "http://login.example.com/",
10677 };
Ryan Hamilton0239aac2018-05-19 00:03:1310678 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410679 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1310680 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:1910681 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:2910682 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110683 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1310684 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910685 };
10686
Ryan Sleevib8d7ea02018-05-07 20:01:0110687 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610688 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610689 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910690
[email protected]bb88e1d32013-05-03 23:11:0710691 session_deps_.socket_factory->AddSocketDataProvider(&data);
10692 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910693
[email protected]49639fa2011-12-20 23:22:4110694 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910695
danakj1fd259a02016-04-16 03:17:0910696 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610697 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910698
tfarina42834112016-09-22 13:38:2010699 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110700 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910701
10702 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110703 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910704
ttuttle960fcbf2016-04-19 13:26:3210705 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910706}
10707
[email protected]0c5fb722012-02-28 11:50:3510708// Test the request-challenge-retry sequence for basic auth, through
10709// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0110710TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3510711 HttpRequestInfo request;
10712 request.method = "GET";
bncce36dca22015-04-21 22:11:2310713 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3510714 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:2910715 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:1010716 request.traffic_annotation =
10717 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3510718
10719 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5910720 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910721 ProxyResolutionService::CreateFixedFromPacResult(
10722 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110723 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710724 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0910725 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3510726
10727 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1310728 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410729 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10730 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310731 spdy::SpdySerializedFrame rst(
10732 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3810733 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3510734
bnc691fda62016-08-12 00:43:1610735 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3510736 // be issuing -- the final header line contains the credentials.
10737 const char* const kAuthCredentials[] = {
10738 "proxy-authorization", "Basic Zm9vOmJhcg==",
10739 };
Ryan Hamilton0239aac2018-05-19 00:03:1310740 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410741 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
10742 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2310743 HostPortPair("www.example.org", 443)));
10744 // fetch https://www.example.org/ via HTTP
10745 const char get[] =
10746 "GET / HTTP/1.1\r\n"
10747 "Host: www.example.org\r\n"
10748 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1310749 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1910750 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3510751
10752 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110753 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
10754 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3510755 };
10756
10757 // The proxy responds to the connect with a 407, using a persistent
10758 // connection.
thestig9d3bb0c2015-01-24 00:49:5110759 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3510760 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3510761 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
10762 };
Ryan Hamilton0239aac2018-05-19 00:03:1310763 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410764 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3510765
Ryan Hamilton0239aac2018-05-19 00:03:1310766 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3510767 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3510768 const char resp[] = "HTTP/1.1 200 OK\r\n"
10769 "Content-Length: 5\r\n\r\n";
10770
Ryan Hamilton0239aac2018-05-19 00:03:1310771 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1910772 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1310773 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1910774 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3510775 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110776 CreateMockRead(conn_auth_resp, 1, ASYNC),
10777 CreateMockRead(conn_resp, 4, ASYNC),
10778 CreateMockRead(wrapped_get_resp, 6, ASYNC),
10779 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1310780 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3510781 };
10782
Ryan Sleevib8d7ea02018-05-07 20:01:0110783 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710784 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3510785 // Negotiate SPDY to the proxy
10786 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610787 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710788 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3510789 // Vanilla SSL to the server
10790 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710791 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3510792
10793 TestCompletionCallback callback1;
10794
bnc87dcefc2017-05-25 12:47:5810795 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910796 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3510797
10798 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110799 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510800
10801 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110802 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5410803 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3510804 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0010805 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10806 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510807 ExpectLogContainsSomewhere(
10808 entries, pos,
mikecirone8b85c432016-09-08 19:11:0010809 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10810 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510811
10812 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210813 ASSERT_TRUE(response);
10814 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3510815 EXPECT_EQ(407, response->headers->response_code());
10816 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5810817 EXPECT_TRUE(response->auth_challenge.has_value());
10818 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3510819
10820 TestCompletionCallback callback2;
10821
10822 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
10823 callback2.callback());
robpercival214763f2016-07-01 23:27:0110824 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510825
10826 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110827 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3510828
10829 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210830 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3510831
10832 EXPECT_TRUE(response->headers->IsKeepAlive());
10833 EXPECT_EQ(200, response->headers->response_code());
10834 EXPECT_EQ(5, response->headers->GetContentLength());
10835 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10836
10837 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810838 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510839
[email protected]029c83b62013-01-24 05:28:2010840 LoadTimingInfo load_timing_info;
10841 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10842 TestLoadTimingNotReusedWithPac(load_timing_info,
10843 CONNECT_TIMING_HAS_SSL_TIMES);
10844
[email protected]0c5fb722012-02-28 11:50:3510845 trans.reset();
10846 session->CloseAllConnections();
10847}
10848
[email protected]7c6f7ba2012-04-03 04:09:2910849// Test that an explicitly trusted SPDY proxy can push a resource from an
10850// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0110851TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1510852 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910853 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510854 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10855 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2910856 HttpRequestInfo request;
10857 HttpRequestInfo push_request;
Ramin Halavatib5e433e62018-02-07 07:41:1010858 request.traffic_annotation =
10859 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910860
[email protected]7c6f7ba2012-04-03 04:09:2910861 request.method = "GET";
bncce36dca22015-04-21 22:11:2310862 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910863 push_request.method = "GET";
10864 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e62018-02-07 07:41:1010865 push_request.traffic_annotation =
10866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910867
tbansal28e68f82016-02-04 02:56:1510868 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910869 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910870 ProxyResolutionService::CreateFixedFromPacResult(
10871 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110872 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710873 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010874
Eric Roman3d8546a2018-09-10 17:00:5210875 session_deps_.proxy_resolution_service->SetProxyDelegate(
10876 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010877
danakj1fd259a02016-04-16 03:17:0910878 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910879
Ryan Hamilton0239aac2018-05-19 00:03:1310880 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510881 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310882 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510883 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910884
10885 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110886 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510887 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910888 };
10889
Ryan Hamilton0239aac2018-05-19 00:03:1310890 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510891 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610892
Ryan Hamilton0239aac2018-05-19 00:03:1310893 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510894 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910895
Ryan Hamilton0239aac2018-05-19 00:03:1310896 spdy::SpdySerializedFrame stream1_body(
10897 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910898
Ryan Hamilton0239aac2018-05-19 00:03:1310899 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910900 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910901
10902 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610903 CreateMockRead(stream2_syn, 1, ASYNC),
10904 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510905 CreateMockRead(stream1_body, 4, ASYNC),
10906 CreateMockRead(stream2_body, 5, ASYNC),
10907 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910908 };
10909
Ryan Sleevib8d7ea02018-05-07 20:01:0110910 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710911 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910912 // Negotiate SPDY to the proxy
10913 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610914 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710915 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910916
bnc87dcefc2017-05-25 12:47:5810917 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910918 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910919 TestCompletionCallback callback;
10920 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110921 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910922
10923 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110924 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910925 const HttpResponseInfo* response = trans->GetResponseInfo();
10926
bnc87dcefc2017-05-25 12:47:5810927 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910928 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010929 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110930 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910931
10932 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110933 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910934 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10935
wezca1070932016-05-26 20:30:5210936 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910937 EXPECT_TRUE(response->headers->IsKeepAlive());
10938
10939 EXPECT_EQ(200, response->headers->response_code());
10940 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10941
10942 std::string response_data;
10943 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110944 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910945 EXPECT_EQ("hello!", response_data);
10946
[email protected]029c83b62013-01-24 05:28:2010947 LoadTimingInfo load_timing_info;
10948 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10949 TestLoadTimingNotReusedWithPac(load_timing_info,
10950 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10951
[email protected]7c6f7ba2012-04-03 04:09:2910952 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210953 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910954 EXPECT_EQ(200, push_response->headers->response_code());
10955
10956 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110957 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910958 EXPECT_EQ("pushed", response_data);
10959
[email protected]029c83b62013-01-24 05:28:2010960 LoadTimingInfo push_load_timing_info;
10961 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10962 TestLoadTimingReusedWithPac(push_load_timing_info);
10963 // The transactions should share a socket ID, despite being for different
10964 // origins.
10965 EXPECT_EQ(load_timing_info.socket_log_id,
10966 push_load_timing_info.socket_log_id);
10967
[email protected]7c6f7ba2012-04-03 04:09:2910968 trans.reset();
10969 push_trans.reset();
10970 session->CloseAllConnections();
10971}
10972
[email protected]8c843192012-04-05 07:15:0010973// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110974TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510975 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910976 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510977 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10978 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010979 HttpRequestInfo request;
10980
10981 request.method = "GET";
bncce36dca22015-04-21 22:11:2310982 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010983 request.traffic_annotation =
10984 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010985
Ramin Halavatica8d5252018-03-12 05:33:4910986 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10987 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110988 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710989 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010990
10991 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210992 session_deps_.proxy_resolution_service->SetProxyDelegate(
10993 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010994
danakj1fd259a02016-04-16 03:17:0910995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010996
Ryan Hamilton0239aac2018-05-19 00:03:1310997 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510998 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010999
Ryan Hamilton0239aac2018-05-19 00:03:1311000 spdy::SpdySerializedFrame push_rst(
11001 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0011002
11003 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111004 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0011005 };
11006
Ryan Hamilton0239aac2018-05-19 00:03:1311007 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511008 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0011009
Ryan Hamilton0239aac2018-05-19 00:03:1311010 spdy::SpdySerializedFrame stream1_body(
11011 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0011012
Ryan Hamilton0239aac2018-05-19 00:03:1311013 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511014 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0011015
11016 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111017 CreateMockRead(stream1_reply, 1, ASYNC),
11018 CreateMockRead(stream2_syn, 2, ASYNC),
11019 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5911020 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0011021 };
11022
Ryan Sleevib8d7ea02018-05-07 20:01:0111023 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711024 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0011025 // Negotiate SPDY to the proxy
11026 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611027 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711028 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0011029
bnc87dcefc2017-05-25 12:47:5811030 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911031 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0011032 TestCompletionCallback callback;
11033 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111034 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0011035
11036 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111037 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011038 const HttpResponseInfo* response = trans->GetResponseInfo();
11039
wezca1070932016-05-26 20:30:5211040 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0011041 EXPECT_TRUE(response->headers->IsKeepAlive());
11042
11043 EXPECT_EQ(200, response->headers->response_code());
11044 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11045
11046 std::string response_data;
11047 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111048 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011049 EXPECT_EQ("hello!", response_data);
11050
11051 trans.reset();
11052 session->CloseAllConnections();
11053}
11054
tbansal8ef1d3e2016-02-03 04:05:4211055// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
11056// resources.
bncd16676a2016-07-20 16:23:0111057TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511058 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911059 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511060 proxy_delegate->set_trusted_spdy_proxy(
11061 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
11062
tbansal8ef1d3e2016-02-03 04:05:4211063 HttpRequestInfo request;
11064
11065 request.method = "GET";
11066 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011067 request.traffic_annotation =
11068 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211069
11070 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4911071 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11072 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211073 BoundTestNetLog log;
11074 session_deps_.net_log = log.bound().net_log();
11075
11076 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211077 session_deps_.proxy_resolution_service->SetProxyDelegate(
11078 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4211079
danakj1fd259a02016-04-16 03:17:0911080 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4211081
Ryan Hamilton0239aac2018-05-19 00:03:1311082 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511083 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311084 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511085 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4211086
11087 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111088 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511089 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4211090 };
11091
Ryan Hamilton0239aac2018-05-19 00:03:1311092 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1511093 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211094
Ryan Hamilton0239aac2018-05-19 00:03:1311095 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3311096 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4911097
Ryan Hamilton0239aac2018-05-19 00:03:1311098 spdy::SpdySerializedFrame stream1_body(
11099 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211100
Ryan Hamilton0239aac2018-05-19 00:03:1311101 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1511102 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211103
Ryan Hamilton0239aac2018-05-19 00:03:1311104 spdy::SpdySerializedFrame stream2_body(
11105 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211106
11107 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111108 CreateMockRead(stream1_reply, 1, ASYNC),
11109 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511110 CreateMockRead(stream1_body, 4, ASYNC),
11111 CreateMockRead(stream2_body, 5, ASYNC),
11112 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4211113 };
11114
Ryan Sleevib8d7ea02018-05-07 20:01:0111115 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4211116 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11117 // Negotiate SPDY to the proxy
11118 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611119 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4211120 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
11121
bnc87dcefc2017-05-25 12:47:5811122 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911123 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4211124 TestCompletionCallback callback;
11125 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111126 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4211127
11128 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111129 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211130 const HttpResponseInfo* response = trans->GetResponseInfo();
11131
wezca1070932016-05-26 20:30:5211132 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4211133 EXPECT_TRUE(response->headers->IsKeepAlive());
11134
11135 EXPECT_EQ(200, response->headers->response_code());
11136 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11137
11138 std::string response_data;
11139 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111140 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211141 EXPECT_EQ("hello!", response_data);
11142
11143 trans.reset();
11144 session->CloseAllConnections();
11145}
11146
[email protected]2df19bb2010-08-25 20:13:4611147// Test HTTPS connections to a site with a bad certificate, going through an
11148// HTTPS proxy
bncd16676a2016-07-20 16:23:0111149TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4911150 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11151 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611152
11153 HttpRequestInfo request;
11154 request.method = "GET";
bncce36dca22015-04-21 22:11:2311155 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011156 request.traffic_annotation =
11157 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611158
11159 // Attempt to fetch the URL from a server with a bad cert
11160 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711161 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11162 "Host: www.example.org:443\r\n"
11163 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611164 };
11165
11166 MockRead bad_cert_reads[] = {
11167 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611168 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4611169 };
11170
11171 // Attempt to fetch the URL with a good cert
11172 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711173 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11174 "Host: www.example.org:443\r\n"
11175 "Proxy-Connection: keep-alive\r\n\r\n"),
11176 MockWrite("GET / HTTP/1.1\r\n"
11177 "Host: www.example.org\r\n"
11178 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611179 };
11180
11181 MockRead good_cert_reads[] = {
11182 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
11183 MockRead("HTTP/1.0 200 OK\r\n"),
11184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11185 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611186 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4611187 };
11188
Ryan Sleevib8d7ea02018-05-07 20:01:0111189 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
11190 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0611191 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
11192 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4611193
11194 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0711195 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11196 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
11197 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4611198
11199 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0711200 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11201 session_deps_.socket_factory->AddSocketDataProvider(&data);
11202 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4611203
[email protected]49639fa2011-12-20 23:22:4111204 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4611205
danakj1fd259a02016-04-16 03:17:0911206 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611207 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4611208
tfarina42834112016-09-22 13:38:2011209 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111210 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611211
11212 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111213 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4611214
bnc691fda62016-08-12 00:43:1611215 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0111216 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611217
11218 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111219 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4611220
bnc691fda62016-08-12 00:43:1611221 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4611222
wezca1070932016-05-26 20:30:5211223 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4611224 EXPECT_EQ(100, response->headers->GetContentLength());
11225}
11226
bncd16676a2016-07-20 16:23:0111227TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4211228 HttpRequestInfo request;
11229 request.method = "GET";
bncce36dca22015-04-21 22:11:2311230 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311231 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11232 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e62018-02-07 07:41:1011233 request.traffic_annotation =
11234 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211235
danakj1fd259a02016-04-16 03:17:0911236 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611237 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711238
[email protected]1c773ea12009-04-28 19:58:4211239 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311240 MockWrite(
11241 "GET / HTTP/1.1\r\n"
11242 "Host: www.example.org\r\n"
11243 "Connection: keep-alive\r\n"
11244 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211245 };
11246
11247 // Lastly, the server responds with the actual content.
11248 MockRead data_reads[] = {
11249 MockRead("HTTP/1.0 200 OK\r\n"),
11250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11251 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611252 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211253 };
11254
Ryan Sleevib8d7ea02018-05-07 20:01:0111255 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711256 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211257
[email protected]49639fa2011-12-20 23:22:4111258 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211259
tfarina42834112016-09-22 13:38:2011260 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111261 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211262
11263 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111264 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211265}
11266
bncd16676a2016-07-20 16:23:0111267TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0011268 // Test user agent values, used both for the request header of the original
11269 // request, and the value returned by the HttpUserAgentSettings. nullptr means
11270 // no request header / no HttpUserAgentSettings object.
11271 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2911272
Matt Menked732ea42019-03-08 12:05:0011273 for (const char* setting_user_agent : kTestUserAgents) {
11274 if (!setting_user_agent) {
11275 session_deps_.http_user_agent_settings.reset();
11276 } else {
11277 session_deps_.http_user_agent_settings =
11278 std::make_unique<StaticHttpUserAgentSettings>(
11279 std::string() /* accept-language */, setting_user_agent);
11280 }
11281 session_deps_.proxy_resolution_service =
11282 ProxyResolutionService::CreateFixed("myproxy:70",
11283 TRAFFIC_ANNOTATION_FOR_TESTS);
11284 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11285 for (const char* request_user_agent : kTestUserAgents) {
11286 HttpRequestInfo request;
11287 request.method = "GET";
11288 request.url = GURL("https://www.example.org/");
11289 if (request_user_agent) {
11290 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11291 request_user_agent);
11292 }
11293 request.traffic_annotation =
11294 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711295
Matt Menked732ea42019-03-08 12:05:0011296 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2911297
Matt Menked732ea42019-03-08 12:05:0011298 std::string expected_request;
11299 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
11300 expected_request =
11301 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11302 "Host: www.example.org:443\r\n"
11303 "Proxy-Connection: keep-alive\r\n\r\n";
11304 } else {
11305 expected_request = base::StringPrintf(
11306 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11307 "Host: www.example.org:443\r\n"
11308 "Proxy-Connection: keep-alive\r\n"
11309 "User-Agent: %s\r\n\r\n",
11310 setting_user_agent);
11311 }
11312 MockWrite data_writes[] = {
11313 MockWrite(expected_request.c_str()),
11314 };
11315 MockRead data_reads[] = {
11316 // Return an error, so the transaction stops here (this test isn't
11317 // interested in the rest).
11318 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
11319 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11320 MockRead("Proxy-Connection: close\r\n\r\n"),
11321 };
[email protected]da81f132010-08-18 23:39:2911322
Matt Menked732ea42019-03-08 12:05:0011323 StaticSocketDataProvider data(data_reads, data_writes);
11324 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2911325
Matt Menked732ea42019-03-08 12:05:0011326 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2911327
Matt Menked732ea42019-03-08 12:05:0011328 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11329 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11330
11331 rv = callback.WaitForResult();
11332 EXPECT_THAT(rv, IsOk());
11333 }
11334 }
[email protected]da81f132010-08-18 23:39:2911335}
11336
bncd16676a2016-07-20 16:23:0111337TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4211338 HttpRequestInfo request;
11339 request.method = "GET";
bncce36dca22015-04-21 22:11:2311340 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1611341 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
11342 "http://the.previous.site.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011343 request.traffic_annotation =
11344 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211345
danakj1fd259a02016-04-16 03:17:0911346 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611347 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711348
[email protected]1c773ea12009-04-28 19:58:4211349 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311350 MockWrite(
11351 "GET / HTTP/1.1\r\n"
11352 "Host: www.example.org\r\n"
11353 "Connection: keep-alive\r\n"
11354 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211355 };
11356
11357 // Lastly, the server responds with the actual content.
11358 MockRead data_reads[] = {
11359 MockRead("HTTP/1.0 200 OK\r\n"),
11360 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11361 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611362 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211363 };
11364
Ryan Sleevib8d7ea02018-05-07 20:01:0111365 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711366 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211367
[email protected]49639fa2011-12-20 23:22:4111368 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211369
tfarina42834112016-09-22 13:38:2011370 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111371 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211372
11373 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111374 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211375}
11376
bncd16676a2016-07-20 16:23:0111377TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211378 HttpRequestInfo request;
11379 request.method = "POST";
bncce36dca22015-04-21 22:11:2311380 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011381 request.traffic_annotation =
11382 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211383
danakj1fd259a02016-04-16 03:17:0911384 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611385 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711386
[email protected]1c773ea12009-04-28 19:58:4211387 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311388 MockWrite(
11389 "POST / HTTP/1.1\r\n"
11390 "Host: www.example.org\r\n"
11391 "Connection: keep-alive\r\n"
11392 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211393 };
11394
11395 // Lastly, the server responds with the actual content.
11396 MockRead data_reads[] = {
11397 MockRead("HTTP/1.0 200 OK\r\n"),
11398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11399 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611400 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211401 };
11402
Ryan Sleevib8d7ea02018-05-07 20:01:0111403 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711404 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211405
[email protected]49639fa2011-12-20 23:22:4111406 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211407
tfarina42834112016-09-22 13:38:2011408 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111409 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211410
11411 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111412 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211413}
11414
bncd16676a2016-07-20 16:23:0111415TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211416 HttpRequestInfo request;
11417 request.method = "PUT";
bncce36dca22015-04-21 22:11:2311418 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011419 request.traffic_annotation =
11420 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211421
danakj1fd259a02016-04-16 03:17:0911422 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611423 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711424
[email protected]1c773ea12009-04-28 19:58:4211425 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311426 MockWrite(
11427 "PUT / HTTP/1.1\r\n"
11428 "Host: www.example.org\r\n"
11429 "Connection: keep-alive\r\n"
11430 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211431 };
11432
11433 // Lastly, the server responds with the actual content.
11434 MockRead data_reads[] = {
11435 MockRead("HTTP/1.0 200 OK\r\n"),
11436 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11437 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611438 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211439 };
11440
Ryan Sleevib8d7ea02018-05-07 20:01:0111441 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711442 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211443
[email protected]49639fa2011-12-20 23:22:4111444 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211445
tfarina42834112016-09-22 13:38:2011446 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111447 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211448
11449 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111450 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211451}
11452
bncd16676a2016-07-20 16:23:0111453TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211454 HttpRequestInfo request;
11455 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2311456 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011457 request.traffic_annotation =
11458 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211459
danakj1fd259a02016-04-16 03:17:0911460 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611461 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711462
[email protected]1c773ea12009-04-28 19:58:4211463 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1311464 MockWrite("HEAD / HTTP/1.1\r\n"
11465 "Host: www.example.org\r\n"
11466 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211467 };
11468
11469 // Lastly, the server responds with the actual content.
11470 MockRead data_reads[] = {
11471 MockRead("HTTP/1.0 200 OK\r\n"),
11472 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11473 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611474 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211475 };
11476
Ryan Sleevib8d7ea02018-05-07 20:01:0111477 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711478 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211479
[email protected]49639fa2011-12-20 23:22:4111480 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211481
tfarina42834112016-09-22 13:38:2011482 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111483 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211484
11485 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111486 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211487}
11488
bncd16676a2016-07-20 16:23:0111489TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4211490 HttpRequestInfo request;
11491 request.method = "GET";
bncce36dca22015-04-21 22:11:2311492 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211493 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1011494 request.traffic_annotation =
11495 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211496
danakj1fd259a02016-04-16 03:17:0911497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611498 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711499
[email protected]1c773ea12009-04-28 19:58:4211500 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311501 MockWrite(
11502 "GET / HTTP/1.1\r\n"
11503 "Host: www.example.org\r\n"
11504 "Connection: keep-alive\r\n"
11505 "Pragma: no-cache\r\n"
11506 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211507 };
11508
11509 // Lastly, the server responds with the actual content.
11510 MockRead data_reads[] = {
11511 MockRead("HTTP/1.0 200 OK\r\n"),
11512 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11513 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611514 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211515 };
11516
Ryan Sleevib8d7ea02018-05-07 20:01:0111517 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711518 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211519
[email protected]49639fa2011-12-20 23:22:4111520 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211521
tfarina42834112016-09-22 13:38:2011522 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111523 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211524
11525 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111526 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211527}
11528
bncd16676a2016-07-20 16:23:0111529TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4211530 HttpRequestInfo request;
11531 request.method = "GET";
bncce36dca22015-04-21 22:11:2311532 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211533 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1011534 request.traffic_annotation =
11535 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211536
danakj1fd259a02016-04-16 03:17:0911537 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611538 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711539
[email protected]1c773ea12009-04-28 19:58:4211540 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311541 MockWrite(
11542 "GET / HTTP/1.1\r\n"
11543 "Host: www.example.org\r\n"
11544 "Connection: keep-alive\r\n"
11545 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211546 };
11547
11548 // Lastly, the server responds with the actual content.
11549 MockRead data_reads[] = {
11550 MockRead("HTTP/1.0 200 OK\r\n"),
11551 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11552 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611553 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211554 };
11555
Ryan Sleevib8d7ea02018-05-07 20:01:0111556 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711557 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211558
[email protected]49639fa2011-12-20 23:22:4111559 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211560
tfarina42834112016-09-22 13:38:2011561 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111562 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211563
11564 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111565 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211566}
11567
bncd16676a2016-07-20 16:23:0111568TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4211569 HttpRequestInfo request;
11570 request.method = "GET";
bncce36dca22015-04-21 22:11:2311571 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311572 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e62018-02-07 07:41:1011573 request.traffic_annotation =
11574 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211575
danakj1fd259a02016-04-16 03:17:0911576 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611577 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711578
[email protected]1c773ea12009-04-28 19:58:4211579 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311580 MockWrite(
11581 "GET / HTTP/1.1\r\n"
11582 "Host: www.example.org\r\n"
11583 "Connection: keep-alive\r\n"
11584 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211585 };
11586
11587 // Lastly, the server responds with the actual content.
11588 MockRead data_reads[] = {
11589 MockRead("HTTP/1.0 200 OK\r\n"),
11590 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11591 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611592 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211593 };
11594
Ryan Sleevib8d7ea02018-05-07 20:01:0111595 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711596 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211597
[email protected]49639fa2011-12-20 23:22:4111598 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211599
tfarina42834112016-09-22 13:38:2011600 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111601 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211602
11603 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111604 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211605}
11606
bncd16676a2016-07-20 16:23:0111607TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4711608 HttpRequestInfo request;
11609 request.method = "GET";
bncce36dca22015-04-21 22:11:2311610 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311611 request.extra_headers.SetHeader("referer", "www.foo.com");
11612 request.extra_headers.SetHeader("hEllo", "Kitty");
11613 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1011614 request.traffic_annotation =
11615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4711616
danakj1fd259a02016-04-16 03:17:0911617 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611618 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711619
[email protected]270c6412010-03-29 22:02:4711620 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311621 MockWrite(
11622 "GET / HTTP/1.1\r\n"
11623 "Host: www.example.org\r\n"
11624 "Connection: keep-alive\r\n"
11625 "referer: www.foo.com\r\n"
11626 "hEllo: Kitty\r\n"
11627 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4711628 };
11629
11630 // Lastly, the server responds with the actual content.
11631 MockRead data_reads[] = {
11632 MockRead("HTTP/1.0 200 OK\r\n"),
11633 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11634 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611635 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4711636 };
11637
Ryan Sleevib8d7ea02018-05-07 20:01:0111638 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711639 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4711640
[email protected]49639fa2011-12-20 23:22:4111641 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4711642
tfarina42834112016-09-22 13:38:2011643 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111644 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4711645
11646 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111647 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4711648}
11649
bncd16676a2016-07-20 16:23:0111650TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711651 HttpRequestInfo request;
11652 request.method = "GET";
bncce36dca22015-04-21 22:11:2311653 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011654 request.traffic_annotation =
11655 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711656
Lily Houghton8c2f97d2018-01-22 05:06:5911657 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911658 ProxyResolutionService::CreateFixedFromPacResult(
11659 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111660 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711661 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211662
danakj1fd259a02016-04-16 03:17:0911663 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611664 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211665
[email protected]3cd17242009-06-23 02:59:0211666 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11667 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11668
11669 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411670 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11671 MockWrite("GET / HTTP/1.1\r\n"
11672 "Host: www.example.org\r\n"
11673 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211674
11675 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411676 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11677 MockRead("HTTP/1.0 200 OK\r\n"),
11678 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11679 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211680
Ryan Sleevib8d7ea02018-05-07 20:01:0111681 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711682 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211683
[email protected]49639fa2011-12-20 23:22:4111684 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211685
tfarina42834112016-09-22 13:38:2011686 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111687 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211688
11689 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111690 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211691
bnc691fda62016-08-12 00:43:1611692 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211693 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0211694
tbansal2ecbbc72016-10-06 17:15:4711695 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2011696 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611697 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011698 TestLoadTimingNotReusedWithPac(load_timing_info,
11699 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11700
[email protected]3cd17242009-06-23 02:59:0211701 std::string response_text;
bnc691fda62016-08-12 00:43:1611702 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111703 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211704 EXPECT_EQ("Payload", response_text);
11705}
11706
bncd16676a2016-07-20 16:23:0111707TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711708 HttpRequestInfo request;
11709 request.method = "GET";
bncce36dca22015-04-21 22:11:2311710 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011711 request.traffic_annotation =
11712 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711713
Lily Houghton8c2f97d2018-01-22 05:06:5911714 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911715 ProxyResolutionService::CreateFixedFromPacResult(
11716 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111717 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711718 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211719
danakj1fd259a02016-04-16 03:17:0911720 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611721 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211722
[email protected]3cd17242009-06-23 02:59:0211723 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
11724 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11725
11726 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311727 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2411728 base::size(write_buffer)),
11729 MockWrite("GET / HTTP/1.1\r\n"
11730 "Host: www.example.org\r\n"
11731 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211732
11733 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411734 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
11735 base::size(read_buffer)),
11736 MockRead("HTTP/1.0 200 OK\r\n"),
11737 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11738 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511739
Ryan Sleevib8d7ea02018-05-07 20:01:0111740 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711741 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511742
[email protected]8ddf8322012-02-23 18:08:0611743 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3511745
[email protected]49639fa2011-12-20 23:22:4111746 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511747
tfarina42834112016-09-22 13:38:2011748 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111749 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511750
11751 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111752 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511753
[email protected]029c83b62013-01-24 05:28:2011754 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611755 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011756 TestLoadTimingNotReusedWithPac(load_timing_info,
11757 CONNECT_TIMING_HAS_SSL_TIMES);
11758
bnc691fda62016-08-12 00:43:1611759 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211760 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711761 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511762
11763 std::string response_text;
bnc691fda62016-08-12 00:43:1611764 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111765 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511766 EXPECT_EQ("Payload", response_text);
11767}
11768
bncd16676a2016-07-20 16:23:0111769TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2011770 HttpRequestInfo request;
11771 request.method = "GET";
bncce36dca22015-04-21 22:11:2311772 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011773 request.traffic_annotation =
11774 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2011775
Ramin Halavatica8d5252018-03-12 05:33:4911776 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11777 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111778 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711779 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2011780
danakj1fd259a02016-04-16 03:17:0911781 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611782 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2011783
11784 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11785 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11786
11787 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411788 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11789 MockWrite("GET / HTTP/1.1\r\n"
11790 "Host: www.example.org\r\n"
11791 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2011792
11793 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411794 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11795 MockRead("HTTP/1.0 200 OK\r\n"),
11796 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11797 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2011798
Ryan Sleevib8d7ea02018-05-07 20:01:0111799 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711800 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2011801
11802 TestCompletionCallback callback;
11803
tfarina42834112016-09-22 13:38:2011804 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111805 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2011806
11807 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111808 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011809
bnc691fda62016-08-12 00:43:1611810 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211811 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2011812
11813 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611814 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011815 TestLoadTimingNotReused(load_timing_info,
11816 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11817
11818 std::string response_text;
bnc691fda62016-08-12 00:43:1611819 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111820 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011821 EXPECT_EQ("Payload", response_text);
11822}
11823
bncd16676a2016-07-20 16:23:0111824TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711825 HttpRequestInfo request;
11826 request.method = "GET";
bncce36dca22015-04-21 22:11:2311827 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011828 request.traffic_annotation =
11829 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711830
Lily Houghton8c2f97d2018-01-22 05:06:5911831 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911832 ProxyResolutionService::CreateFixedFromPacResult(
11833 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111834 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711835 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511836
danakj1fd259a02016-04-16 03:17:0911837 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611838 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511839
[email protected]e0c27be2009-07-15 13:09:3511840 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11841 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711842 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311843 0x05, // Version
11844 0x01, // Command (CONNECT)
11845 0x00, // Reserved.
11846 0x03, // Address type (DOMAINNAME).
11847 0x0F, // Length of domain (15)
11848 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11849 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3711850 };
[email protected]e0c27be2009-07-15 13:09:3511851 const char kSOCKS5OkResponse[] =
11852 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
11853
11854 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411855 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
11856 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
11857 MockWrite("GET / HTTP/1.1\r\n"
11858 "Host: www.example.org\r\n"
11859 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511860
11861 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411862 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11863 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11864 MockRead("HTTP/1.0 200 OK\r\n"),
11865 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11866 MockRead("Payload"),
11867 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511868
Ryan Sleevib8d7ea02018-05-07 20:01:0111869 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711870 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511871
[email protected]49639fa2011-12-20 23:22:4111872 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511873
tfarina42834112016-09-22 13:38:2011874 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111875 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511876
11877 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111878 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511879
bnc691fda62016-08-12 00:43:1611880 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211881 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711882 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511883
[email protected]029c83b62013-01-24 05:28:2011884 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611885 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011886 TestLoadTimingNotReusedWithPac(load_timing_info,
11887 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11888
[email protected]e0c27be2009-07-15 13:09:3511889 std::string response_text;
bnc691fda62016-08-12 00:43:1611890 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111891 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511892 EXPECT_EQ("Payload", response_text);
11893}
11894
bncd16676a2016-07-20 16:23:0111895TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711896 HttpRequestInfo request;
11897 request.method = "GET";
bncce36dca22015-04-21 22:11:2311898 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011899 request.traffic_annotation =
11900 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711901
Lily Houghton8c2f97d2018-01-22 05:06:5911902 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911903 ProxyResolutionService::CreateFixedFromPacResult(
11904 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111905 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711906 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511907
danakj1fd259a02016-04-16 03:17:0911908 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611909 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511910
[email protected]e0c27be2009-07-15 13:09:3511911 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11912 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711913 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311914 0x05, // Version
11915 0x01, // Command (CONNECT)
11916 0x00, // Reserved.
11917 0x03, // Address type (DOMAINNAME).
11918 0x0F, // Length of domain (15)
11919 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11920 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711921 };
11922
[email protected]e0c27be2009-07-15 13:09:3511923 const char kSOCKS5OkResponse[] =
11924 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11925
11926 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411927 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311928 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411929 base::size(kSOCKS5OkRequest)),
11930 MockWrite("GET / HTTP/1.1\r\n"
11931 "Host: www.example.org\r\n"
11932 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511933
11934 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411935 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11936 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11937 MockRead("HTTP/1.0 200 OK\r\n"),
11938 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11939 MockRead("Payload"),
11940 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211941
Ryan Sleevib8d7ea02018-05-07 20:01:0111942 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711943 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211944
[email protected]8ddf8322012-02-23 18:08:0611945 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711946 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211947
[email protected]49639fa2011-12-20 23:22:4111948 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211949
tfarina42834112016-09-22 13:38:2011950 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111951 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211952
11953 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111954 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211955
bnc691fda62016-08-12 00:43:1611956 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211957 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711958 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211959
[email protected]029c83b62013-01-24 05:28:2011960 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611961 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011962 TestLoadTimingNotReusedWithPac(load_timing_info,
11963 CONNECT_TIMING_HAS_SSL_TIMES);
11964
[email protected]3cd17242009-06-23 02:59:0211965 std::string response_text;
bnc691fda62016-08-12 00:43:1611966 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111967 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211968 EXPECT_EQ("Payload", response_text);
11969}
11970
[email protected]448d4ca52012-03-04 04:12:2311971namespace {
11972
Matt Menkef6edce752019-03-19 17:21:5611973// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611974
Matt Menkef6edce752019-03-19 17:21:5611975struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611976 std::string proxy_server;
11977 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611978 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811979 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611980};
11981
Matt Menkef6edce752019-03-19 17:21:5611982std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711983 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911984 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611985
bnc525e175a2016-06-20 12:36:4011986 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311987 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111988 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211989 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111990 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211991 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0711992 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611993
11994 return session;
11995}
11996
Matt Menkef6edce752019-03-19 17:21:5611997int GroupIdTransactionHelper(const std::string& url,
11998 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611999 HttpRequestInfo request;
12000 request.method = "GET";
12001 request.url = GURL(url);
Ramin Halavatib5e433e62018-02-07 07:41:1012002 request.traffic_annotation =
12003 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0612004
bnc691fda62016-08-12 00:43:1612005 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2712006
[email protected]49639fa2011-12-20 23:22:4112007 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0612008
12009 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2012010 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0612011}
12012
[email protected]448d4ca52012-03-04 04:12:2312013} // namespace
12014
Matt Menkef6edce752019-03-19 17:21:5612015TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
12016 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312017 {
Matt Menkef6edce752019-03-19 17:21:5612018 "", // unused
12019 "http://www.example.org/direct",
12020 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12021 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412022 PrivacyMode::PRIVACY_MODE_DISABLED,
12023 NetworkIsolationKey(),
12024 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612025 false,
bncce36dca22015-04-21 22:11:2312026 },
12027 {
Matt Menkef6edce752019-03-19 17:21:5612028 "", // unused
12029 "http://[2001:1418:13:1::25]/direct",
12030 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
12031 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412032 PrivacyMode::PRIVACY_MODE_DISABLED,
12033 NetworkIsolationKey(),
12034 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612035 false,
bncce36dca22015-04-21 22:11:2312036 },
[email protected]04e5be32009-06-26 20:00:3112037
bncce36dca22015-04-21 22:11:2312038 // SSL Tests
12039 {
Matt Menkef6edce752019-03-19 17:21:5612040 "", // unused
12041 "https://www.example.org/direct_ssl",
12042 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12043 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412044 PrivacyMode::PRIVACY_MODE_DISABLED,
12045 NetworkIsolationKey(),
12046 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612047 true,
bncce36dca22015-04-21 22:11:2312048 },
12049 {
Matt Menkef6edce752019-03-19 17:21:5612050 "", // unused
12051 "https://[2001:1418:13:1::25]/direct",
12052 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
12053 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412054 PrivacyMode::PRIVACY_MODE_DISABLED,
12055 NetworkIsolationKey(),
12056 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612057 true,
bncce36dca22015-04-21 22:11:2312058 },
12059 {
Matt Menkef6edce752019-03-19 17:21:5612060 "", // unused
12061 "https://host.with.alternate/direct",
12062 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12063 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412064 PrivacyMode::PRIVACY_MODE_DISABLED,
12065 NetworkIsolationKey(),
12066 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612067 true,
bncce36dca22015-04-21 22:11:2312068 },
[email protected]2d731a32010-04-29 01:04:0612069 };
[email protected]2ff8b312010-04-26 22:20:5412070
Avi Drissman4365a4782018-12-28 19:26:2412071 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912072 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4912073 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
12074 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912075 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612076 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612077
mmenkee65e7af2015-10-13 17:16:4212078 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5612079 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612080 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912081 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012082 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
12083 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4812084 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612085
12086 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612087 GroupIdTransactionHelper(tests[i].url, session.get()));
12088 EXPECT_EQ(tests[i].expected_group_id,
12089 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2312090 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0612091 }
[email protected]2d731a32010-04-29 01:04:0612092}
12093
Matt Menkef6edce752019-03-19 17:21:5612094TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
12095 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312096 {
Matt Menke4802de62019-03-08 22:47:5012097 "http_proxy",
12098 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5612099 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12100 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412101 PrivacyMode::PRIVACY_MODE_DISABLED,
12102 NetworkIsolationKey(),
12103 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012104 false,
bncce36dca22015-04-21 22:11:2312105 },
[email protected]2d731a32010-04-29 01:04:0612106
bncce36dca22015-04-21 22:11:2312107 // SSL Tests
12108 {
Matt Menke4802de62019-03-08 22:47:5012109 "http_proxy",
12110 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5612111 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12112 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412113 PrivacyMode::PRIVACY_MODE_DISABLED,
12114 NetworkIsolationKey(),
12115 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012116 true,
bncce36dca22015-04-21 22:11:2312117 },
[email protected]af3490e2010-10-16 21:02:2912118
bncce36dca22015-04-21 22:11:2312119 {
Matt Menke4802de62019-03-08 22:47:5012120 "http_proxy",
12121 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612122 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12123 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412124 PrivacyMode::PRIVACY_MODE_DISABLED,
12125 NetworkIsolationKey(),
12126 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012127 true,
bncce36dca22015-04-21 22:11:2312128 },
[email protected]2d731a32010-04-29 01:04:0612129 };
12130
Avi Drissman4365a4782018-12-28 19:26:2412131 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912132 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4912133 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
12134 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912135 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612136 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612137
mmenkee65e7af2015-10-13 17:16:4212138 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0612139
Matt Menkee8648fa2019-01-17 16:47:0712140 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
12141 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5612142 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3612143 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912144 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012145 mock_pool_manager->SetSocketPool(proxy_server,
12146 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4812147 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612148
12149 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612150 GroupIdTransactionHelper(tests[i].url, session.get()));
12151 EXPECT_EQ(tests[i].expected_group_id,
12152 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0612153 }
[email protected]2d731a32010-04-29 01:04:0612154}
12155
Matt Menkef6edce752019-03-19 17:21:5612156TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
12157 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312158 {
Matt Menke4802de62019-03-08 22:47:5012159 "socks4://socks_proxy:1080",
12160 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5612161 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12162 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412163 PrivacyMode::PRIVACY_MODE_DISABLED,
12164 NetworkIsolationKey(),
12165 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012166 false,
bncce36dca22015-04-21 22:11:2312167 },
12168 {
Matt Menke4802de62019-03-08 22:47:5012169 "socks5://socks_proxy:1080",
12170 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5612171 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12172 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412173 PrivacyMode::PRIVACY_MODE_DISABLED,
12174 NetworkIsolationKey(),
12175 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012176 false,
bncce36dca22015-04-21 22:11:2312177 },
[email protected]2d731a32010-04-29 01:04:0612178
bncce36dca22015-04-21 22:11:2312179 // SSL Tests
12180 {
Matt Menke4802de62019-03-08 22:47:5012181 "socks4://socks_proxy:1080",
12182 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5612183 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12184 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412185 PrivacyMode::PRIVACY_MODE_DISABLED,
12186 NetworkIsolationKey(),
12187 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012188 true,
bncce36dca22015-04-21 22:11:2312189 },
12190 {
Matt Menke4802de62019-03-08 22:47:5012191 "socks5://socks_proxy:1080",
12192 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5612193 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12194 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412195 PrivacyMode::PRIVACY_MODE_DISABLED,
12196 NetworkIsolationKey(),
12197 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012198 true,
bncce36dca22015-04-21 22:11:2312199 },
[email protected]af3490e2010-10-16 21:02:2912200
bncce36dca22015-04-21 22:11:2312201 {
Matt Menke4802de62019-03-08 22:47:5012202 "socks4://socks_proxy:1080",
12203 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612204 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12205 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412206 PrivacyMode::PRIVACY_MODE_DISABLED,
12207 NetworkIsolationKey(),
12208 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012209 true,
bncce36dca22015-04-21 22:11:2312210 },
[email protected]04e5be32009-06-26 20:00:3112211 };
12212
Avi Drissman4365a4782018-12-28 19:26:2412213 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912214 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4912215 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
12216 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912217 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612218 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0212219
mmenkee65e7af2015-10-13 17:16:4212220 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3112221
Matt Menkee8648fa2019-01-17 16:47:0712222 ProxyServer proxy_server(
12223 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
12224 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5612225 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612226 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912227 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012228 mock_pool_manager->SetSocketPool(proxy_server,
12229 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4812230 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3112231
bnc691fda62016-08-12 00:43:1612232 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3112233
[email protected]2d731a32010-04-29 01:04:0612234 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612235 GroupIdTransactionHelper(tests[i].url, session.get()));
12236 EXPECT_EQ(tests[i].expected_group_id,
12237 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3112238 }
12239}
12240
bncd16676a2016-07-20 16:23:0112241TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2712242 HttpRequestInfo request;
12243 request.method = "GET";
bncce36dca22015-04-21 22:11:2312244 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012245 request.traffic_annotation =
12246 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712247
Ramin Halavatica8d5252018-03-12 05:33:4912248 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
12249 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3212250
[email protected]69719062010-01-05 20:09:2112251 // This simulates failure resolving all hostnames; that means we will fail
12252 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0712253 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3212254
danakj1fd259a02016-04-16 03:17:0912255 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612256 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2512257
[email protected]49639fa2011-12-20 23:22:4112258 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2512259
tfarina42834112016-09-22 13:38:2012260 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112261 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2512262
[email protected]9172a982009-06-06 00:30:2512263 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112264 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2512265}
12266
[email protected]0877e3d2009-10-17 22:29:5712267// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0112268TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5712269 HttpRequestInfo request;
12270 request.method = "GET";
12271 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1012272 request.traffic_annotation =
12273 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712274
12275 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0612276 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712277 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112278 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0712279 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912280 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712281
[email protected]49639fa2011-12-20 23:22:4112282 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712283
bnc691fda62016-08-12 00:43:1612284 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712285
tfarina42834112016-09-22 13:38:2012286 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112287 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712288
12289 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112290 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5912291
12292 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612293 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912294 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712295}
12296
zmo9528c9f42015-08-04 22:12:0812297// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0112298TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5712299 HttpRequestInfo request;
12300 request.method = "GET";
12301 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1012302 request.traffic_annotation =
12303 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712304
12305 MockRead data_reads[] = {
12306 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0612307 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712308 };
12309
Ryan Sleevib8d7ea02018-05-07 20:01:0112310 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712311 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912312 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712313
[email protected]49639fa2011-12-20 23:22:4112314 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712315
bnc691fda62016-08-12 00:43:1612316 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712317
tfarina42834112016-09-22 13:38:2012318 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112319 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712320
12321 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112322 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812323
bnc691fda62016-08-12 00:43:1612324 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212325 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0812326
wezca1070932016-05-26 20:30:5212327 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0812328 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12329
12330 std::string response_data;
bnc691fda62016-08-12 00:43:1612331 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112332 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812333 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5912334
12335 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612336 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912337 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712338}
12339
12340// Make sure that a dropped connection while draining the body for auth
12341// restart does the right thing.
bncd16676a2016-07-20 16:23:0112342TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5712343 HttpRequestInfo request;
12344 request.method = "GET";
bncce36dca22015-04-21 22:11:2312345 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012346 request.traffic_annotation =
12347 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712348
12349 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312350 MockWrite(
12351 "GET / HTTP/1.1\r\n"
12352 "Host: www.example.org\r\n"
12353 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712354 };
12355
12356 MockRead data_reads1[] = {
12357 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
12358 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
12359 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12360 MockRead("Content-Length: 14\r\n\r\n"),
12361 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0612362 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712363 };
12364
Ryan Sleevib8d7ea02018-05-07 20:01:0112365 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0712366 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5712367
bnc691fda62016-08-12 00:43:1612368 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5712369 // be issuing -- the final header line contains the credentials.
12370 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312371 MockWrite(
12372 "GET / HTTP/1.1\r\n"
12373 "Host: www.example.org\r\n"
12374 "Connection: keep-alive\r\n"
12375 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712376 };
12377
12378 // Lastly, the server responds with the actual content.
12379 MockRead data_reads2[] = {
12380 MockRead("HTTP/1.1 200 OK\r\n"),
12381 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12382 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612383 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712384 };
12385
Ryan Sleevib8d7ea02018-05-07 20:01:0112386 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0712387 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0912388 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712389
[email protected]49639fa2011-12-20 23:22:4112390 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5712391
bnc691fda62016-08-12 00:43:1612392 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012393
tfarina42834112016-09-22 13:38:2012394 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112395 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712396
12397 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112398 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712399
bnc691fda62016-08-12 00:43:1612400 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212401 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812402 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5712403
[email protected]49639fa2011-12-20 23:22:4112404 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5712405
bnc691fda62016-08-12 00:43:1612406 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0112407 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712408
12409 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112410 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712411
bnc691fda62016-08-12 00:43:1612412 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212413 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812414 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5712415 EXPECT_EQ(100, response->headers->GetContentLength());
12416}
12417
12418// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0112419TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4912420 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
12421 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712422
12423 HttpRequestInfo request;
12424 request.method = "GET";
bncce36dca22015-04-21 22:11:2312425 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012426 request.traffic_annotation =
12427 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712428
12429 MockRead proxy_reads[] = {
12430 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0612431 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5712432 };
12433
Ryan Sleevib8d7ea02018-05-07 20:01:0112434 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0612435 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5712436
[email protected]bb88e1d32013-05-03 23:11:0712437 session_deps_.socket_factory->AddSocketDataProvider(&data);
12438 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5712439
[email protected]49639fa2011-12-20 23:22:4112440 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712441
[email protected]bb88e1d32013-05-03 23:11:0712442 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5712443
danakj1fd259a02016-04-16 03:17:0912444 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612445 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712446
tfarina42834112016-09-22 13:38:2012447 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112448 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712449
12450 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112451 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5712452}
12453
bncd16676a2016-07-20 16:23:0112454TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4612455 HttpRequestInfo request;
12456 request.method = "GET";
bncce36dca22015-04-21 22:11:2312457 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012458 request.traffic_annotation =
12459 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4612460
danakj1fd259a02016-04-16 03:17:0912461 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612462 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712463
[email protected]e22e1362009-11-23 21:31:1212464 MockRead data_reads[] = {
12465 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612466 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1212467 };
[email protected]9492e4a2010-02-24 00:58:4612468
Ryan Sleevib8d7ea02018-05-07 20:01:0112469 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712470 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4612471
[email protected]49639fa2011-12-20 23:22:4112472 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4612473
tfarina42834112016-09-22 13:38:2012474 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112475 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4612476
robpercival214763f2016-07-01 23:27:0112477 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4612478
bnc691fda62016-08-12 00:43:1612479 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212480 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4612481
wezca1070932016-05-26 20:30:5212482 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4612483 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12484
12485 std::string response_data;
bnc691fda62016-08-12 00:43:1612486 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112487 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1212488}
12489
bncd16676a2016-07-20 16:23:0112490TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1512491 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5212492 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1412493 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2112494 UploadFileElementReader::ScopedOverridingContentLengthForTests
12495 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3312496
danakj1fd259a02016-04-16 03:17:0912497 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912498 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412499 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0712500 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212501 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712502
12503 HttpRequestInfo request;
12504 request.method = "POST";
bncce36dca22015-04-21 22:11:2312505 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712506 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012507 request.traffic_annotation =
12508 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712509
danakj1fd259a02016-04-16 03:17:0912510 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612511 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3312512
12513 MockRead data_reads[] = {
12514 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
12515 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612516 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3312517 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112518 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712519 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3312520
[email protected]49639fa2011-12-20 23:22:4112521 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3312522
tfarina42834112016-09-22 13:38:2012523 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112524 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3312525
12526 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112527 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3312528
bnc691fda62016-08-12 00:43:1612529 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212530 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3312531
maksim.sisove869bf52016-06-23 17:11:5212532 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3312533
[email protected]dd3aa792013-07-16 19:10:2312534 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3312535}
12536
bncd16676a2016-07-20 16:23:0112537TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1512538 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5212539 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3612540 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4812541 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
12542 base::WriteFile(temp_file, temp_file_content.c_str(),
12543 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1112544 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3612545
danakj1fd259a02016-04-16 03:17:0912546 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912547 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412548 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0712549 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212550 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712551
12552 HttpRequestInfo request;
12553 request.method = "POST";
bncce36dca22015-04-21 22:11:2312554 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712555 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012556 request.traffic_annotation =
12557 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712558
[email protected]999dd8c2013-11-12 06:45:5412559 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0912560 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612561 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3612562
Ryan Sleevib8d7ea02018-05-07 20:01:0112563 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0712564 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3612565
[email protected]49639fa2011-12-20 23:22:4112566 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3612567
tfarina42834112016-09-22 13:38:2012568 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112569 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3612570
12571 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112572 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3612573
[email protected]dd3aa792013-07-16 19:10:2312574 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3612575}
12576
bncd16676a2016-07-20 16:23:0112577TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0312578 class FakeUploadElementReader : public UploadElementReader {
12579 public:
Chris Watkins7a41d3552017-12-01 02:13:2712580 FakeUploadElementReader() = default;
12581 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0312582
Matt Menkecc1d3a902018-02-05 18:27:3312583 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0312584
12585 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3312586 int Init(CompletionOnceCallback callback) override {
12587 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0312588 return ERR_IO_PENDING;
12589 }
avibf0746c2015-12-09 19:53:1412590 uint64_t GetContentLength() const override { return 0; }
12591 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2012592 int Read(IOBuffer* buf,
12593 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3312594 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0312595 return ERR_FAILED;
12596 }
12597
12598 private:
Matt Menkecc1d3a902018-02-05 18:27:3312599 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0312600 };
12601
12602 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0912603 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
12604 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2212605 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0312606
12607 HttpRequestInfo request;
12608 request.method = "POST";
bncce36dca22015-04-21 22:11:2312609 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0312610 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012611 request.traffic_annotation =
12612 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0312613
danakj1fd259a02016-04-16 03:17:0912614 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812615 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912616 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0312617
12618 StaticSocketDataProvider data;
12619 session_deps_.socket_factory->AddSocketDataProvider(&data);
12620
12621 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2012622 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112623 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5512624 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0312625
12626 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3312627 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
12628 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0312629
12630 // Return Init()'s result after the transaction gets destroyed.
12631 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3312632 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0312633}
12634
[email protected]aeefc9e82010-02-19 16:18:2712635// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0112636TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2712637 HttpRequestInfo request;
12638 request.method = "GET";
bncce36dca22015-04-21 22:11:2312639 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012640 request.traffic_annotation =
12641 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2712642
12643 // First transaction will request a resource and receive a Basic challenge
12644 // with realm="first_realm".
12645 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312646 MockWrite(
12647 "GET / HTTP/1.1\r\n"
12648 "Host: www.example.org\r\n"
12649 "Connection: keep-alive\r\n"
12650 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712651 };
12652 MockRead data_reads1[] = {
12653 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12654 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12655 "\r\n"),
12656 };
12657
bnc691fda62016-08-12 00:43:1612658 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2712659 // for first_realm. The server will reject and provide a challenge with
12660 // second_realm.
12661 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312662 MockWrite(
12663 "GET / HTTP/1.1\r\n"
12664 "Host: www.example.org\r\n"
12665 "Connection: keep-alive\r\n"
12666 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
12667 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712668 };
12669 MockRead data_reads2[] = {
12670 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12671 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
12672 "\r\n"),
12673 };
12674
12675 // This again fails, and goes back to first_realm. Make sure that the
12676 // entry is removed from cache.
12677 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2312678 MockWrite(
12679 "GET / HTTP/1.1\r\n"
12680 "Host: www.example.org\r\n"
12681 "Connection: keep-alive\r\n"
12682 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
12683 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712684 };
12685 MockRead data_reads3[] = {
12686 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12687 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12688 "\r\n"),
12689 };
12690
12691 // Try one last time (with the correct password) and get the resource.
12692 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2312693 MockWrite(
12694 "GET / HTTP/1.1\r\n"
12695 "Host: www.example.org\r\n"
12696 "Connection: keep-alive\r\n"
12697 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
12698 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712699 };
12700 MockRead data_reads4[] = {
12701 MockRead("HTTP/1.1 200 OK\r\n"
12702 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5012703 "Content-Length: 5\r\n"
12704 "\r\n"
12705 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2712706 };
12707
Ryan Sleevib8d7ea02018-05-07 20:01:0112708 StaticSocketDataProvider data1(data_reads1, data_writes1);
12709 StaticSocketDataProvider data2(data_reads2, data_writes2);
12710 StaticSocketDataProvider data3(data_reads3, data_writes3);
12711 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0712712 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12713 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12714 session_deps_.socket_factory->AddSocketDataProvider(&data3);
12715 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2712716
[email protected]49639fa2011-12-20 23:22:4112717 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2712718
danakj1fd259a02016-04-16 03:17:0912719 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612720 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012721
[email protected]aeefc9e82010-02-19 16:18:2712722 // Issue the first request with Authorize headers. There should be a
12723 // password prompt for first_realm waiting to be filled in after the
12724 // transaction completes.
tfarina42834112016-09-22 13:38:2012725 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112726 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712727 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112728 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612729 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212730 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812731 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212732 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412733 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312734 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412735 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912736 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712737
12738 // Issue the second request with an incorrect password. There should be a
12739 // password prompt for second_realm waiting to be filled in after the
12740 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4112741 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1612742 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
12743 callback2.callback());
robpercival214763f2016-07-01 23:27:0112744 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712745 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112746 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612747 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212748 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812749 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212750 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412751 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312752 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412753 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912754 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712755
12756 // Issue the third request with another incorrect password. There should be
12757 // a password prompt for first_realm waiting to be filled in. If the password
12758 // prompt is not present, it indicates that the HttpAuthCacheEntry for
12759 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4112760 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1612761 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
12762 callback3.callback());
robpercival214763f2016-07-01 23:27:0112763 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712764 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0112765 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612766 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212767 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812768 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212769 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412770 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312771 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412772 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912773 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712774
12775 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4112776 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1612777 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
12778 callback4.callback());
robpercival214763f2016-07-01 23:27:0112779 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712780 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0112781 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612782 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212783 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812784 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2712785}
12786
Bence Béky230ac612017-08-30 19:17:0812787// Regression test for https://crbug.com/754395.
12788TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
12789 MockRead data_reads[] = {
12790 MockRead("HTTP/1.1 200 OK\r\n"),
12791 MockRead(kAlternativeServiceHttpHeader),
12792 MockRead("\r\n"),
12793 MockRead("hello world"),
12794 MockRead(SYNCHRONOUS, OK),
12795 };
12796
12797 HttpRequestInfo request;
12798 request.method = "GET";
12799 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012800 request.traffic_annotation =
12801 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0812802
Ryan Sleevib8d7ea02018-05-07 20:01:0112803 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0812804 session_deps_.socket_factory->AddSocketDataProvider(&data);
12805
12806 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912807 ssl.ssl_info.cert =
12808 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12809 ASSERT_TRUE(ssl.ssl_info.cert);
12810 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0812811 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12812
12813 TestCompletionCallback callback;
12814
12815 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12816 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12817
12818 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12819 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12820
12821 url::SchemeHostPort test_server(request.url);
12822 HttpServerProperties* http_server_properties =
12823 session->http_server_properties();
12824 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912825 http_server_properties
12826 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12827 .empty());
Bence Béky230ac612017-08-30 19:17:0812828
12829 EXPECT_THAT(callback.WaitForResult(), IsOk());
12830
12831 const HttpResponseInfo* response = trans.GetResponseInfo();
12832 ASSERT_TRUE(response);
12833 ASSERT_TRUE(response->headers);
12834 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12835 EXPECT_FALSE(response->was_fetched_via_spdy);
12836 EXPECT_FALSE(response->was_alpn_negotiated);
12837
12838 std::string response_data;
12839 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12840 EXPECT_EQ("hello world", response_data);
12841
12842 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912843 http_server_properties
12844 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12845 .empty());
Bence Béky230ac612017-08-30 19:17:0812846}
12847
bncd16676a2016-07-20 16:23:0112848TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5212849 MockRead data_reads[] = {
12850 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312851 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212852 MockRead("\r\n"),
12853 MockRead("hello world"),
12854 MockRead(SYNCHRONOUS, OK),
12855 };
12856
12857 HttpRequestInfo request;
12858 request.method = "GET";
bncb26024382016-06-29 02:39:4512859 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012860 request.traffic_annotation =
12861 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212862
Ryan Sleevib8d7ea02018-05-07 20:01:0112863 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212864 session_deps_.socket_factory->AddSocketDataProvider(&data);
12865
bncb26024382016-06-29 02:39:4512866 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912867 ssl.ssl_info.cert =
12868 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12869 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512870 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12871
bncc958faa2015-07-31 18:14:5212872 TestCompletionCallback callback;
12873
danakj1fd259a02016-04-16 03:17:0912874 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612875 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212876
tfarina42834112016-09-22 13:38:2012877 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112878 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212879
bncb26024382016-06-29 02:39:4512880 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012881 HttpServerProperties* http_server_properties =
12882 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412883 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912884 http_server_properties
12885 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12886 .empty());
bncc958faa2015-07-31 18:14:5212887
robpercival214763f2016-07-01 23:27:0112888 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212889
bnc691fda62016-08-12 00:43:1612890 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212891 ASSERT_TRUE(response);
12892 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212893 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12894 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212895 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212896
12897 std::string response_data;
bnc691fda62016-08-12 00:43:1612898 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212899 EXPECT_EQ("hello world", response_data);
12900
zhongyic4de03032017-05-19 04:07:3412901 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912902 http_server_properties->GetAlternativeServiceInfos(test_server,
12903 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412904 ASSERT_EQ(1u, alternative_service_info_vector.size());
12905 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12906 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412907 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212908}
12909
Matt Menke3233d8f22019-08-20 21:01:4912910TEST_F(HttpNetworkTransactionTest,
12911 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
12912 base::test::ScopedFeatureList feature_list;
12913 feature_list.InitWithFeatures(
12914 // enabled_features
12915 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
12916 // Need to partition connections by NetworkIsolationKey for
12917 // SpdySessionKeys to include NetworkIsolationKeys.
12918 features::kPartitionConnectionsByNetworkIsolationKey},
12919 // disabled_features
12920 {});
12921 // Since HttpServerProperties caches the feature value, have to create a new
12922 // one.
12923 session_deps_.http_server_properties =
12924 std::make_unique<HttpServerProperties>();
12925
12926 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
12927 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
12928 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
12929 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
12930
12931 MockRead data_reads[] = {
12932 MockRead("HTTP/1.1 200 OK\r\n"),
12933 MockRead(kAlternativeServiceHttpHeader),
12934 MockRead("\r\n"),
12935 MockRead("hello world"),
12936 MockRead(SYNCHRONOUS, OK),
12937 };
12938
12939 HttpRequestInfo request;
12940 request.method = "GET";
12941 request.url = GURL("https://www.example.org/");
12942 request.traffic_annotation =
12943 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12944 request.network_isolation_key = kNetworkIsolationKey1;
12945
12946 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12947 session_deps_.socket_factory->AddSocketDataProvider(&data);
12948
12949 SSLSocketDataProvider ssl(ASYNC, OK);
12950 ssl.ssl_info.cert =
12951 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12952 ASSERT_TRUE(ssl.ssl_info.cert);
12953 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12954
12955 TestCompletionCallback callback;
12956
12957 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12958 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12959
12960 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12961 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12962
12963 url::SchemeHostPort test_server(request.url);
12964 HttpServerProperties* http_server_properties =
12965 session->http_server_properties();
12966 EXPECT_TRUE(
12967 http_server_properties
12968 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
12969 .empty());
12970
12971 EXPECT_THAT(callback.WaitForResult(), IsOk());
12972
12973 const HttpResponseInfo* response = trans.GetResponseInfo();
12974 ASSERT_TRUE(response);
12975 ASSERT_TRUE(response->headers);
12976 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12977 EXPECT_FALSE(response->was_fetched_via_spdy);
12978 EXPECT_FALSE(response->was_alpn_negotiated);
12979
12980 std::string response_data;
12981 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12982 EXPECT_EQ("hello world", response_data);
12983
12984 AlternativeServiceInfoVector alternative_service_info_vector =
12985 http_server_properties->GetAlternativeServiceInfos(test_server,
12986 kNetworkIsolationKey1);
12987 ASSERT_EQ(1u, alternative_service_info_vector.size());
12988 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12989 EXPECT_EQ(alternative_service,
12990 alternative_service_info_vector[0].alternative_service());
12991
12992 // Make sure the alternative service information is only associated with
12993 // kNetworkIsolationKey1.
12994 EXPECT_TRUE(
12995 http_server_properties
12996 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12997 .empty());
12998 EXPECT_TRUE(
12999 http_server_properties
13000 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
13001 .empty());
13002}
13003
bnce3dd56f2016-06-01 10:37:1113004// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0113005TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113006 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1113007 MockRead data_reads[] = {
13008 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313009 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1113010 MockRead("\r\n"),
13011 MockRead("hello world"),
13012 MockRead(SYNCHRONOUS, OK),
13013 };
13014
13015 HttpRequestInfo request;
13016 request.method = "GET";
13017 request.url = GURL("http://www.example.org/");
13018 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013019 request.traffic_annotation =
13020 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113021
Ryan Sleevib8d7ea02018-05-07 20:01:0113022 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113023 session_deps_.socket_factory->AddSocketDataProvider(&data);
13024
13025 TestCompletionCallback callback;
13026
13027 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613028 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113029
13030 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013031 HttpServerProperties* http_server_properties =
13032 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413033 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913034 http_server_properties
13035 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13036 .empty());
bnce3dd56f2016-06-01 10:37:1113037
tfarina42834112016-09-22 13:38:2013038 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113039 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13040 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1113041
bnc691fda62016-08-12 00:43:1613042 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1113043 ASSERT_TRUE(response);
13044 ASSERT_TRUE(response->headers);
13045 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13046 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213047 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1113048
13049 std::string response_data;
bnc691fda62016-08-12 00:43:1613050 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1113051 EXPECT_EQ("hello world", response_data);
13052
zhongyic4de03032017-05-19 04:07:3413053 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913054 http_server_properties
13055 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13056 .empty());
bnce3dd56f2016-06-01 10:37:1113057}
13058
bnca86731e2017-04-17 12:31:2813059// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2513060// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0113061TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2513062 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2813063 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4513064
bnc8bef8da22016-05-30 01:28:2513065 HttpRequestInfo request;
13066 request.method = "GET";
bncb26024382016-06-29 02:39:4513067 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2513068 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013069 request.traffic_annotation =
13070 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2513071
13072 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13073 StaticSocketDataProvider first_data;
13074 first_data.set_connect_data(mock_connect);
13075 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513076 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613077 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513078 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2513079
13080 MockRead data_reads[] = {
13081 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13082 MockRead(ASYNC, OK),
13083 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113084 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2513085 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13086
13087 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13088
bnc525e175a2016-06-20 12:36:4013089 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2513090 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113091 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
13092 444);
bnc8bef8da22016-05-30 01:28:2513093 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113094 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713095 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13096 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2513097
bnc691fda62016-08-12 00:43:1613098 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2513099 TestCompletionCallback callback;
13100
tfarina42834112016-09-22 13:38:2013101 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2513102 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113103 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2513104}
13105
bnce3dd56f2016-06-01 10:37:1113106// Regression test for https://crbug.com/615497:
13107// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0113108TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113109 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1113110 HttpRequestInfo request;
13111 request.method = "GET";
13112 request.url = GURL("http://www.example.org/");
13113 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013114 request.traffic_annotation =
13115 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113116
13117 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13118 StaticSocketDataProvider first_data;
13119 first_data.set_connect_data(mock_connect);
13120 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
13121
13122 MockRead data_reads[] = {
13123 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13124 MockRead(ASYNC, OK),
13125 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113126 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113127 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13128
13129 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13130
bnc525e175a2016-06-20 12:36:4013131 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1113132 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113133 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1113134 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113135 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713136 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13137 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1113138
bnc691fda62016-08-12 00:43:1613139 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113140 TestCompletionCallback callback;
13141
tfarina42834112016-09-22 13:38:2013142 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1113143 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113144 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1113145}
13146
bncd16676a2016-07-20 16:23:0113147TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0813148 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0913149 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013150 HttpServerProperties* http_server_properties =
13151 session->http_server_properties();
bncb26024382016-06-29 02:39:4513152 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2113153 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0813154 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113155 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713156 test_server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4213157 session->params().quic_params.supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4913158 EXPECT_EQ(1u,
13159 http_server_properties
13160 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13161 .size());
bnc4f575852015-10-14 18:35:0813162
13163 // Send a clear header.
13164 MockRead data_reads[] = {
13165 MockRead("HTTP/1.1 200 OK\r\n"),
13166 MockRead("Alt-Svc: clear\r\n"),
13167 MockRead("\r\n"),
13168 MockRead("hello world"),
13169 MockRead(SYNCHRONOUS, OK),
13170 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113171 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0813172 session_deps_.socket_factory->AddSocketDataProvider(&data);
13173
bncb26024382016-06-29 02:39:4513174 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913175 ssl.ssl_info.cert =
13176 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13177 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513178 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13179
bnc4f575852015-10-14 18:35:0813180 HttpRequestInfo request;
13181 request.method = "GET";
bncb26024382016-06-29 02:39:4513182 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013183 request.traffic_annotation =
13184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0813185
13186 TestCompletionCallback callback;
13187
bnc691fda62016-08-12 00:43:1613188 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0813189
tfarina42834112016-09-22 13:38:2013190 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113191 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0813192
bnc691fda62016-08-12 00:43:1613193 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213194 ASSERT_TRUE(response);
13195 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0813196 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13197 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213198 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0813199
13200 std::string response_data;
bnc691fda62016-08-12 00:43:1613201 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0813202 EXPECT_EQ("hello world", response_data);
13203
zhongyic4de03032017-05-19 04:07:3413204 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913205 http_server_properties
13206 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13207 .empty());
bnc4f575852015-10-14 18:35:0813208}
13209
bncd16676a2016-07-20 16:23:0113210TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5213211 MockRead data_reads[] = {
13212 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313213 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
13214 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5213215 MockRead("hello world"),
13216 MockRead(SYNCHRONOUS, OK),
13217 };
13218
13219 HttpRequestInfo request;
13220 request.method = "GET";
bncb26024382016-06-29 02:39:4513221 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013222 request.traffic_annotation =
13223 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213224
Ryan Sleevib8d7ea02018-05-07 20:01:0113225 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213226 session_deps_.socket_factory->AddSocketDataProvider(&data);
13227
bncb26024382016-06-29 02:39:4513228 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913229 ssl.ssl_info.cert =
13230 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13231 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13233
bncc958faa2015-07-31 18:14:5213234 TestCompletionCallback callback;
13235
danakj1fd259a02016-04-16 03:17:0913236 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613237 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213238
tfarina42834112016-09-22 13:38:2013239 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113240 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213241
bncb26024382016-06-29 02:39:4513242 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4013243 HttpServerProperties* http_server_properties =
13244 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413245 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913246 http_server_properties
13247 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13248 .empty());
bncc958faa2015-07-31 18:14:5213249
robpercival214763f2016-07-01 23:27:0113250 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213251
bnc691fda62016-08-12 00:43:1613252 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213253 ASSERT_TRUE(response);
13254 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213255 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13256 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213257 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213258
13259 std::string response_data;
bnc691fda62016-08-12 00:43:1613260 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213261 EXPECT_EQ("hello world", response_data);
13262
zhongyic4de03032017-05-19 04:07:3413263 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913264 http_server_properties->GetAlternativeServiceInfos(test_server,
13265 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413266 ASSERT_EQ(2u, alternative_service_info_vector.size());
13267
13268 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
13269 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413270 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3413271 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
13272 1234);
13273 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5413274 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5213275}
13276
bncd16676a2016-07-20 16:23:0113277TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613278 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213279 HostPortPair alternative("alternative.example.org", 443);
13280 std::string origin_url = "https://origin.example.org:443";
13281 std::string alternative_url = "https://alternative.example.org:443";
13282
13283 // Negotiate HTTP/1.1 with alternative.example.org.
13284 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613285 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213286 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13287
13288 // HTTP/1.1 data for request.
13289 MockWrite http_writes[] = {
13290 MockWrite("GET / HTTP/1.1\r\n"
13291 "Host: alternative.example.org\r\n"
13292 "Connection: keep-alive\r\n\r\n"),
13293 };
13294
13295 MockRead http_reads[] = {
13296 MockRead("HTTP/1.1 200 OK\r\n"
13297 "Content-Type: text/html; charset=iso-8859-1\r\n"
13298 "Content-Length: 40\r\n\r\n"
13299 "first HTTP/1.1 response from alternative"),
13300 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113301 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213302 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13303
13304 StaticSocketDataProvider data_refused;
13305 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13306 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13307
zhongyi3d4a55e72016-04-22 20:36:4613308 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0913309 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013310 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213311 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113312 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0213313 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113314 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713315 server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4213316 HttpNetworkSession::Params().quic_params.supported_versions);
zhongyi48704c182015-12-07 07:52:0213317 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513318 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
13319 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0213320
zhongyi48704c182015-12-07 07:52:0213321 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613322 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213323 request.method = "GET";
13324 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1013325 request.traffic_annotation =
13326 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13327
zhongyi48704c182015-12-07 07:52:0213328 TestCompletionCallback callback;
13329 NetErrorDetails details;
13330 EXPECT_FALSE(details.quic_broken);
13331
tfarina42834112016-09-22 13:38:2013332 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613333 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213334 EXPECT_TRUE(details.quic_broken);
13335}
13336
bncd16676a2016-07-20 16:23:0113337TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613338 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213339 HostPortPair alternative1("alternative1.example.org", 443);
13340 HostPortPair alternative2("alternative2.example.org", 443);
13341 std::string origin_url = "https://origin.example.org:443";
13342 std::string alternative_url1 = "https://alternative1.example.org:443";
13343 std::string alternative_url2 = "https://alternative2.example.org:443";
13344
13345 // Negotiate HTTP/1.1 with alternative1.example.org.
13346 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613347 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213348 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13349
13350 // HTTP/1.1 data for request.
13351 MockWrite http_writes[] = {
13352 MockWrite("GET / HTTP/1.1\r\n"
13353 "Host: alternative1.example.org\r\n"
13354 "Connection: keep-alive\r\n\r\n"),
13355 };
13356
13357 MockRead http_reads[] = {
13358 MockRead("HTTP/1.1 200 OK\r\n"
13359 "Content-Type: text/html; charset=iso-8859-1\r\n"
13360 "Content-Length: 40\r\n\r\n"
13361 "first HTTP/1.1 response from alternative1"),
13362 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113363 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213364 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13365
13366 StaticSocketDataProvider data_refused;
13367 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13368 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13369
danakj1fd259a02016-04-16 03:17:0913370 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013371 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213372 session->http_server_properties();
13373
zhongyi3d4a55e72016-04-22 20:36:4613374 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0213375 AlternativeServiceInfoVector alternative_service_info_vector;
13376 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
13377
bnc3472afd2016-11-17 15:27:2113378 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2113379 alternative_service_info_vector.push_back(
13380 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13381 alternative_service1, expiration,
Nick Harper72ade192019-07-17 03:30:4213382 session->params().quic_params.supported_versions));
bnc3472afd2016-11-17 15:27:2113383 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2113384 alternative_service_info_vector.push_back(
13385 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13386 alternative_service2, expiration,
Nick Harper72ade192019-07-17 03:30:4213387 session->params().quic_params.supported_versions));
zhongyi48704c182015-12-07 07:52:0213388
13389 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4913390 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0213391
13392 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513393 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
13394 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4913395 EXPECT_EQ(2u, http_server_properties
13396 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
13397 .size());
zhongyi48704c182015-12-07 07:52:0213398
zhongyi48704c182015-12-07 07:52:0213399 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613400 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213401 request.method = "GET";
13402 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1013403 request.traffic_annotation =
13404 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13405
zhongyi48704c182015-12-07 07:52:0213406 TestCompletionCallback callback;
13407 NetErrorDetails details;
13408 EXPECT_FALSE(details.quic_broken);
13409
tfarina42834112016-09-22 13:38:2013410 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613411 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213412 EXPECT_FALSE(details.quic_broken);
13413}
13414
bncd16676a2016-07-20 16:23:0113415TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4213416 HttpRequestInfo request;
13417 request.method = "GET";
bncb26024382016-06-29 02:39:4513418 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013419 request.traffic_annotation =
13420 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4213421
[email protected]d973e99a2012-02-17 21:02:3613422 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4213423 StaticSocketDataProvider first_data;
13424 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713425 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513426 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613427 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513428 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4213429
13430 MockRead data_reads[] = {
13431 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13432 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613433 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4213434 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113435 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713436 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4213437
danakj1fd259a02016-04-16 03:17:0913438 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4213439
bnc525e175a2016-06-20 12:36:4013440 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313441 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4613442 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1113443 // Port must be < 1024, or the header will be ignored (since initial port was
13444 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2113445 // Port is ignored by MockConnect anyway.
13446 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13447 666);
bnc7dc7e1b42015-07-28 14:43:1213448 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113449 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713450 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4213451
bnc691fda62016-08-12 00:43:1613452 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113453 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4213454
tfarina42834112016-09-22 13:38:2013455 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113456 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13457 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4213458
bnc691fda62016-08-12 00:43:1613459 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213460 ASSERT_TRUE(response);
13461 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4213462 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13463
13464 std::string response_data;
bnc691fda62016-08-12 00:43:1613465 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4213466 EXPECT_EQ("hello world", response_data);
13467
zhongyic4de03032017-05-19 04:07:3413468 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913469 http_server_properties->GetAlternativeServiceInfos(server,
13470 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413471 ASSERT_EQ(1u, alternative_service_info_vector.size());
13472 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413473 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0513474 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
13475 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4213476}
13477
bnc55ff9da2015-08-19 18:42:3513478// Ensure that we are not allowed to redirect traffic via an alternate protocol
13479// to an unrestricted (port >= 1024) when the original traffic was on a
13480// restricted port (port < 1024). Ensure that we can redirect in all other
13481// cases.
bncd16676a2016-07-20 16:23:0113482TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1113483 HttpRequestInfo restricted_port_request;
13484 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513485 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113486 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013487 restricted_port_request.traffic_annotation =
13488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113489
[email protected]d973e99a2012-02-17 21:02:3613490 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113491 StaticSocketDataProvider first_data;
13492 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713493 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113494
13495 MockRead data_reads[] = {
13496 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13497 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613498 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113499 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113500 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713501 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513502 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613503 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113505
danakj1fd259a02016-04-16 03:17:0913506 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113507
bnc525e175a2016-06-20 12:36:4013508 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313509 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113510 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113511 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13512 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213513 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113514 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713515 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13516 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113517
bnc691fda62016-08-12 00:43:1613518 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113519 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113520
tfarina42834112016-09-22 13:38:2013521 int rv = trans.Start(&restricted_port_request, callback.callback(),
13522 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113523 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113524 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0113525 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1913526}
[email protected]3912662a32011-10-04 00:51:1113527
bnc55ff9da2015-08-19 18:42:3513528// Ensure that we are allowed to redirect traffic via an alternate protocol to
13529// an unrestricted (port >= 1024) when the original traffic was on a restricted
13530// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0113531TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0713532 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1913533
13534 HttpRequestInfo restricted_port_request;
13535 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513536 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1913537 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013538 restricted_port_request.traffic_annotation =
13539 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1913540
13541 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13542 StaticSocketDataProvider first_data;
13543 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713544 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1913545
13546 MockRead data_reads[] = {
13547 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13548 MockRead("hello world"),
13549 MockRead(ASYNC, OK),
13550 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113551 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713552 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513553 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613554 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513555 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1913556
danakj1fd259a02016-04-16 03:17:0913557 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1913558
bnc525e175a2016-06-20 12:36:4013559 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1913560 session->http_server_properties();
13561 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113562 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13563 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213564 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113565 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713566 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13567 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1913568
bnc691fda62016-08-12 00:43:1613569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1913570 TestCompletionCallback callback;
13571
tfarina42834112016-09-22 13:38:2013572 EXPECT_EQ(ERR_IO_PENDING,
13573 trans.Start(&restricted_port_request, callback.callback(),
13574 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1913575 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0113576 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113577}
13578
bnc55ff9da2015-08-19 18:42:3513579// Ensure that we are not allowed to redirect traffic via an alternate protocol
13580// to an unrestricted (port >= 1024) when the original traffic was on a
13581// restricted port (port < 1024). Ensure that we can redirect in all other
13582// cases.
bncd16676a2016-07-20 16:23:0113583TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1113584 HttpRequestInfo restricted_port_request;
13585 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513586 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113587 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013588 restricted_port_request.traffic_annotation =
13589 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113590
[email protected]d973e99a2012-02-17 21:02:3613591 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113592 StaticSocketDataProvider first_data;
13593 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713594 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113595
13596 MockRead data_reads[] = {
13597 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13598 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613599 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113600 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113601 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713602 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113603
bncb26024382016-06-29 02:39:4513604 SSLSocketDataProvider ssl(ASYNC, OK);
13605 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13606
danakj1fd259a02016-04-16 03:17:0913607 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113608
bnc525e175a2016-06-20 12:36:4013609 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313610 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113611 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113612 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13613 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213614 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113615 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713616 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13617 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113618
bnc691fda62016-08-12 00:43:1613619 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113620 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113621
tfarina42834112016-09-22 13:38:2013622 int rv = trans.Start(&restricted_port_request, callback.callback(),
13623 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113624 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113625 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113626 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113627}
13628
bnc55ff9da2015-08-19 18:42:3513629// Ensure that we are not allowed to redirect traffic via an alternate protocol
13630// to an unrestricted (port >= 1024) when the original traffic was on a
13631// restricted port (port < 1024). Ensure that we can redirect in all other
13632// cases.
bncd16676a2016-07-20 16:23:0113633TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1113634 HttpRequestInfo unrestricted_port_request;
13635 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513636 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113637 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013638 unrestricted_port_request.traffic_annotation =
13639 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113640
[email protected]d973e99a2012-02-17 21:02:3613641 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113642 StaticSocketDataProvider first_data;
13643 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713644 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113645
13646 MockRead data_reads[] = {
13647 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13648 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613649 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113650 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113651 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713652 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513653 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613654 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513655 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113656
danakj1fd259a02016-04-16 03:17:0913657 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113658
bnc525e175a2016-06-20 12:36:4013659 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313660 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113661 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113662 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13663 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213664 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113665 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713666 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13667 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113668
bnc691fda62016-08-12 00:43:1613669 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113670 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113671
bnc691fda62016-08-12 00:43:1613672 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013673 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113674 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113675 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113676 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113677}
13678
bnc55ff9da2015-08-19 18:42:3513679// Ensure that we are not allowed to redirect traffic via an alternate protocol
13680// to an unrestricted (port >= 1024) when the original traffic was on a
13681// restricted port (port < 1024). Ensure that we can redirect in all other
13682// cases.
bncd16676a2016-07-20 16:23:0113683TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1113684 HttpRequestInfo unrestricted_port_request;
13685 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513686 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113687 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013688 unrestricted_port_request.traffic_annotation =
13689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113690
[email protected]d973e99a2012-02-17 21:02:3613691 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113692 StaticSocketDataProvider first_data;
13693 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713694 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113695
13696 MockRead data_reads[] = {
13697 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13698 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613699 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113700 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113701 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713702 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113703
bncb26024382016-06-29 02:39:4513704 SSLSocketDataProvider ssl(ASYNC, OK);
13705 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13706
danakj1fd259a02016-04-16 03:17:0913707 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113708
bnc525e175a2016-06-20 12:36:4013709 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313710 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2213711 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2113712 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13713 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213714 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113715 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713716 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13717 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113718
bnc691fda62016-08-12 00:43:1613719 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113720 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113721
bnc691fda62016-08-12 00:43:1613722 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013723 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113724 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113725 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0113726 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113727}
13728
bnc55ff9da2015-08-19 18:42:3513729// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2113730// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
13731// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0113732TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0213733 HttpRequestInfo request;
13734 request.method = "GET";
bncce36dca22015-04-21 22:11:2313735 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013736 request.traffic_annotation =
13737 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0213738
13739 // The alternate protocol request will error out before we attempt to connect,
13740 // so only the standard HTTP request will try to connect.
13741 MockRead data_reads[] = {
13742 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13743 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613744 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0213745 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113746 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713747 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0213748
danakj1fd259a02016-04-16 03:17:0913749 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0213750
bnc525e175a2016-06-20 12:36:4013751 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0213752 session->http_server_properties();
13753 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2113754 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13755 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1213756 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113757 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713758 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13759 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0213760
bnc691fda62016-08-12 00:43:1613761 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0213762 TestCompletionCallback callback;
13763
tfarina42834112016-09-22 13:38:2013764 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113765 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0213766 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0113767 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213768
bnc691fda62016-08-12 00:43:1613769 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213770 ASSERT_TRUE(response);
13771 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0213772 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13773
13774 std::string response_data;
bnc691fda62016-08-12 00:43:1613775 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213776 EXPECT_EQ("hello world", response_data);
13777}
13778
bncd16676a2016-07-20 16:23:0113779TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5413780 HttpRequestInfo request;
13781 request.method = "GET";
bncb26024382016-06-29 02:39:4513782 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013783 request.traffic_annotation =
13784 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413785
13786 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213787 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313788 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213789 MockRead("\r\n"),
13790 MockRead("hello world"),
13791 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13792 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5413793
Ryan Sleevib8d7ea02018-05-07 20:01:0113794 StaticSocketDataProvider first_transaction(data_reads,
13795 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713796 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513797 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613798 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513799 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413800
bnc032658ba2016-09-26 18:17:1513801 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413802
Ryan Hamilton0239aac2018-05-19 00:03:1313803 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513804 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113805 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413806
Raul Tambre94493c652019-03-11 17:18:3513807 spdy::SpdySerializedFrame resp(
13808 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313809 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413810 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113811 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413812 };
13813
Ryan Sleevib8d7ea02018-05-07 20:01:0113814 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713815 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413816
[email protected]d973e99a2012-02-17 21:02:3613817 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113818 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513819 hanging_non_alternate_protocol_socket.set_connect_data(
13820 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713821 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513822 &hanging_non_alternate_protocol_socket);
13823
[email protected]49639fa2011-12-20 23:22:4113824 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413825
danakj1fd259a02016-04-16 03:17:0913826 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813827 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913828 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413829
tfarina42834112016-09-22 13:38:2013830 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113831 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13832 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413833
13834 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213835 ASSERT_TRUE(response);
13836 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413837 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13838
13839 std::string response_data;
robpercival214763f2016-07-01 23:27:0113840 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413841 EXPECT_EQ("hello world", response_data);
13842
bnc87dcefc2017-05-25 12:47:5813843 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913844 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413845
tfarina42834112016-09-22 13:38:2013846 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113847 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13848 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413849
13850 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213851 ASSERT_TRUE(response);
13852 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213853 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313854 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213855 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413856
robpercival214763f2016-07-01 23:27:0113857 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413858 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5413859}
13860
bncd16676a2016-07-20 16:23:0113861TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5513862 HttpRequestInfo request;
13863 request.method = "GET";
bncb26024382016-06-29 02:39:4513864 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013865 request.traffic_annotation =
13866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513867
bncb26024382016-06-29 02:39:4513868 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5513869 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213870 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313871 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213872 MockRead("\r\n"),
13873 MockRead("hello world"),
13874 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13875 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513876 };
13877
Ryan Sleevib8d7ea02018-05-07 20:01:0113878 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4513879 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5513880
bncb26024382016-06-29 02:39:4513881 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913882 ssl_http11.ssl_info.cert =
13883 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13884 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4513885 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
13886
13887 // Second transaction starts an alternative and a non-alternative Job.
13888 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3613889 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113890 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1813891 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1813892 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
13893
Ryan Sleevib8d7ea02018-05-07 20:01:0113894 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1813895 hanging_socket2.set_connect_data(never_finishing_connect);
13896 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5513897
bncb26024382016-06-29 02:39:4513898 // Third transaction starts an alternative and a non-alternative job.
13899 // The non-alternative job hangs, but the alternative one succeeds.
13900 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1313901 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4513902 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1313903 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4513904 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5513905 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113906 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5513907 };
Raul Tambre94493c652019-03-11 17:18:3513908 spdy::SpdySerializedFrame resp1(
13909 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313910 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3513911 spdy::SpdySerializedFrame resp2(
13912 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1313913 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5513914 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113915 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
13916 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1313917 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5513918 };
13919
Ryan Sleevib8d7ea02018-05-07 20:01:0113920 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713921 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5513922
bnc032658ba2016-09-26 18:17:1513923 AddSSLSocketData();
bncb26024382016-06-29 02:39:4513924
Ryan Sleevib8d7ea02018-05-07 20:01:0113925 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1813926 hanging_socket3.set_connect_data(never_finishing_connect);
13927 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5513928
danakj1fd259a02016-04-16 03:17:0913929 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4113930 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5013931 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513932
tfarina42834112016-09-22 13:38:2013933 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113934 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13935 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513936
13937 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5213938 ASSERT_TRUE(response);
13939 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513940 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13941
13942 std::string response_data;
robpercival214763f2016-07-01 23:27:0113943 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513944 EXPECT_EQ("hello world", response_data);
13945
[email protected]49639fa2011-12-20 23:22:4113946 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5013947 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013948 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113949 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513950
[email protected]49639fa2011-12-20 23:22:4113951 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5013952 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013953 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113954 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513955
robpercival214763f2016-07-01 23:27:0113956 EXPECT_THAT(callback2.WaitForResult(), IsOk());
13957 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513958
13959 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5213960 ASSERT_TRUE(response);
13961 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213962 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513963 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213964 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113965 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513966 EXPECT_EQ("hello!", response_data);
13967
13968 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5213969 ASSERT_TRUE(response);
13970 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213971 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513972 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213973 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113974 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513975 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5513976}
13977
bncd16676a2016-07-20 16:23:0113978TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5313979 session_deps_.host_resolver->set_synchronous_mode(true);
13980
[email protected]2d6728692011-03-12 01:39:5513981 HttpRequestInfo request;
13982 request.method = "GET";
bncb26024382016-06-29 02:39:4513983 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013984 request.traffic_annotation =
13985 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513986
13987 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213988 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313989 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213990 MockRead("\r\n"),
13991 MockRead("hello world"),
13992 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13993 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513994 };
13995
Ryan Sleevib8d7ea02018-05-07 20:01:0113996 StaticSocketDataProvider first_transaction(data_reads,
13997 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713998 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513999
[email protected]8ddf8322012-02-23 18:08:0614000 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914001 ssl.ssl_info.cert =
14002 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14003 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0714004 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514005
[email protected]d973e99a2012-02-17 21:02:3614006 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114007 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514008 hanging_alternate_protocol_socket.set_connect_data(
14009 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714010 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514011 &hanging_alternate_protocol_socket);
14012
bncb26024382016-06-29 02:39:4514013 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0114014 StaticSocketDataProvider second_transaction(data_reads,
14015 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1814016 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4514017 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514018
[email protected]49639fa2011-12-20 23:22:4114019 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5514020
danakj1fd259a02016-04-16 03:17:0914021 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814022 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914023 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514024
tfarina42834112016-09-22 13:38:2014025 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114026 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14027 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514028
14029 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214030 ASSERT_TRUE(response);
14031 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514032 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14033
14034 std::string response_data;
robpercival214763f2016-07-01 23:27:0114035 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514036 EXPECT_EQ("hello world", response_data);
14037
bnc87dcefc2017-05-25 12:47:5814038 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914039 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514040
tfarina42834112016-09-22 13:38:2014041 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114042 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14043 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514044
14045 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214046 ASSERT_TRUE(response);
14047 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514048 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14049 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214050 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5514051
robpercival214763f2016-07-01 23:27:0114052 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514053 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5514054}
14055
bnc2e884782016-08-11 19:45:1914056// Test that proxy is resolved using the origin url,
14057// regardless of the alternative server.
14058TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
14059 // Configure proxy to bypass www.example.org, which is the origin URL.
14060 ProxyConfig proxy_config;
14061 proxy_config.proxy_rules().ParseFromString("myproxy:70");
14062 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4914063 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
14064 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1914065
14066 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1914067 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1914068 &capturing_proxy_resolver);
14069
14070 TestNetLog net_log;
14071
Bence Béky53a5aef2018-03-29 21:54:1214072 session_deps_.proxy_resolution_service =
14073 std::make_unique<ProxyResolutionService>(
14074 std::move(proxy_config_service), std::move(proxy_resolver_factory),
14075 &net_log);
bnc2e884782016-08-11 19:45:1914076
14077 session_deps_.net_log = &net_log;
14078
14079 // Configure alternative service with a hostname that is not bypassed by the
14080 // proxy.
14081 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14082 HttpServerProperties* http_server_properties =
14083 session->http_server_properties();
14084 url::SchemeHostPort server("https", "www.example.org", 443);
14085 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2114086 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1914087 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114088 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714089 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1914090
14091 // Non-alternative job should hang.
14092 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114093 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1914094 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
14095 session_deps_.socket_factory->AddSocketDataProvider(
14096 &hanging_alternate_protocol_socket);
14097
bnc032658ba2016-09-26 18:17:1514098 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1914099
14100 HttpRequestInfo request;
14101 request.method = "GET";
14102 request.url = GURL("https://www.example.org/");
14103 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1014104 request.traffic_annotation =
14105 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1914106
Ryan Hamilton0239aac2018-05-19 00:03:1314107 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1914108 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
14109
14110 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
14111
Ryan Hamilton0239aac2018-05-19 00:03:1314112 spdy::SpdySerializedFrame resp(
14113 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
14114 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1914115 MockRead spdy_reads[] = {
14116 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
14117 };
14118
Ryan Sleevib8d7ea02018-05-07 20:01:0114119 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1914120 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
14121
14122 TestCompletionCallback callback;
14123
14124 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14125
tfarina42834112016-09-22 13:38:2014126 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1914127 EXPECT_THAT(callback.GetResult(rv), IsOk());
14128
14129 const HttpResponseInfo* response = trans.GetResponseInfo();
14130 ASSERT_TRUE(response);
14131 ASSERT_TRUE(response->headers);
14132 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
14133 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214134 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1914135
14136 std::string response_data;
14137 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
14138 EXPECT_EQ("hello!", response_data);
14139
14140 // Origin host bypasses proxy, no resolution should have happened.
14141 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
14142}
14143
bncd16676a2016-07-20 16:23:0114144TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1114145 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4214146 proxy_config.set_auto_detect(true);
14147 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1114148
sammc5dd160c2015-04-02 02:43:1314149 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4914150 session_deps_.proxy_resolution_service =
14151 std::make_unique<ProxyResolutionService>(
14152 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
14153 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
14154 std::make_unique<CapturingProxyResolverFactory>(
14155 &capturing_proxy_resolver),
14156 nullptr);
vishal.b62985ca92015-04-17 08:45:5114157 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0714158 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1114159
14160 HttpRequestInfo request;
14161 request.method = "GET";
bncb26024382016-06-29 02:39:4514162 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014163 request.traffic_annotation =
14164 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1114165
14166 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214167 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314168 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214169 MockRead("\r\n"),
14170 MockRead("hello world"),
14171 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14172 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1114173 };
14174
Ryan Sleevib8d7ea02018-05-07 20:01:0114175 StaticSocketDataProvider first_transaction(data_reads,
14176 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714177 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514178 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614179 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514180 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1114181
bnc032658ba2016-09-26 18:17:1514182 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1114183
Ryan Hamilton0239aac2018-05-19 00:03:1314184 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514185 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1114186 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1314187 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2514188 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14189 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1314190 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4114191 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1114192 };
14193
[email protected]d911f1b2010-05-05 22:39:4214194 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
14195
Raul Tambre94493c652019-03-11 17:18:3514196 spdy::SpdySerializedFrame resp(
14197 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314198 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1114199 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114200 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
14201 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1114202 };
14203
Ryan Sleevib8d7ea02018-05-07 20:01:0114204 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714205 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1114206
[email protected]d973e99a2012-02-17 21:02:3614207 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114208 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514209 hanging_non_alternate_protocol_socket.set_connect_data(
14210 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714211 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514212 &hanging_non_alternate_protocol_socket);
14213
[email protected]49639fa2011-12-20 23:22:4114214 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1114215
danakj1fd259a02016-04-16 03:17:0914216 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814217 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914218 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114219
tfarina42834112016-09-22 13:38:2014220 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4114221 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14222 EXPECT_THAT(callback.WaitForResult(), IsOk());
14223
14224 const HttpResponseInfo* response = trans->GetResponseInfo();
14225 ASSERT_TRUE(response);
14226 ASSERT_TRUE(response->headers);
14227 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
14228 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214229 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4114230
14231 std::string response_data;
14232 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
14233 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1114234
bnc87dcefc2017-05-25 12:47:5814235 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914236 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114237
tfarina42834112016-09-22 13:38:2014238 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114239 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14240 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1114241
mmenkea2dcd3bf2016-08-16 21:49:4114242 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214243 ASSERT_TRUE(response);
14244 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214245 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314246 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214247 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1114248
robpercival214763f2016-07-01 23:27:0114249 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1114250 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4514251 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
14252 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1314253 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2314254 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1314255 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1114256
[email protected]029c83b62013-01-24 05:28:2014257 LoadTimingInfo load_timing_info;
14258 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
14259 TestLoadTimingNotReusedWithPac(load_timing_info,
14260 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1114261}
[email protected]631f1322010-04-30 17:59:1114262
bncd16676a2016-07-20 16:23:0114263TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4814264 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5414265 HttpRequestInfo request;
14266 request.method = "GET";
bncb26024382016-06-29 02:39:4514267 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014268 request.traffic_annotation =
14269 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414270
14271 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214272 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314273 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214274 MockRead("\r\n"),
14275 MockRead("hello world"),
14276 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5414277 };
14278
Ryan Sleevib8d7ea02018-05-07 20:01:0114279 StaticSocketDataProvider first_transaction(data_reads,
14280 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714281 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514282 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614283 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514284 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414285
bnc032658ba2016-09-26 18:17:1514286 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414287
Ryan Hamilton0239aac2018-05-19 00:03:1314288 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514289 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114290 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414291
Raul Tambre94493c652019-03-11 17:18:3514292 spdy::SpdySerializedFrame resp(
14293 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314294 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414295 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114296 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414297 };
14298
Ryan Sleevib8d7ea02018-05-07 20:01:0114299 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714300 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414301
[email protected]83039bb2011-12-09 18:43:5514302 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414303
danakj1fd259a02016-04-16 03:17:0914304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5414305
bnc87dcefc2017-05-25 12:47:5814306 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914307 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414308
tfarina42834112016-09-22 13:38:2014309 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114310 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14311 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414312
14313 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214314 ASSERT_TRUE(response);
14315 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414316 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14317
14318 std::string response_data;
robpercival214763f2016-07-01 23:27:0114319 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414320 EXPECT_EQ("hello world", response_data);
14321
14322 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2514323 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4014324 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1114325 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3414326 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
14327 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2714328 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5214329 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3814330
bnc87dcefc2017-05-25 12:47:5814331 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914332 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414333
tfarina42834112016-09-22 13:38:2014334 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114335 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14336 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414337
14338 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214339 ASSERT_TRUE(response);
14340 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214341 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314342 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214343 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414344
robpercival214763f2016-07-01 23:27:0114345 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414346 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4214347}
14348
[email protected]044de0642010-06-17 10:42:1514349// GenerateAuthToken is a mighty big test.
14350// It tests all permutation of GenerateAuthToken behavior:
14351// - Synchronous and Asynchronous completion.
14352// - OK or error on completion.
14353// - Direct connection, non-authenticating proxy, and authenticating proxy.
14354// - HTTP or HTTPS backend (to include proxy tunneling).
14355// - Non-authenticating and authenticating backend.
14356//
[email protected]fe3b7dc2012-02-03 19:52:0914357// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1514358// problems generating an auth token for an authenticating proxy, we don't
14359// need to test all permutations of the backend server).
14360//
14361// The test proceeds by going over each of the configuration cases, and
14362// potentially running up to three rounds in each of the tests. The TestConfig
14363// specifies both the configuration for the test as well as the expectations
14364// for the results.
bncd16676a2016-07-20 16:23:0114365TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5014366 static const char kServer[] = "http://www.example.com";
14367 static const char kSecureServer[] = "https://www.example.com";
14368 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1514369
14370 enum AuthTiming {
14371 AUTH_NONE,
14372 AUTH_SYNC,
14373 AUTH_ASYNC,
14374 };
14375
14376 const MockWrite kGet(
14377 "GET / HTTP/1.1\r\n"
14378 "Host: www.example.com\r\n"
14379 "Connection: keep-alive\r\n\r\n");
14380 const MockWrite kGetProxy(
14381 "GET http://www.example.com/ HTTP/1.1\r\n"
14382 "Host: www.example.com\r\n"
14383 "Proxy-Connection: keep-alive\r\n\r\n");
14384 const MockWrite kGetAuth(
14385 "GET / HTTP/1.1\r\n"
14386 "Host: www.example.com\r\n"
14387 "Connection: keep-alive\r\n"
14388 "Authorization: auth_token\r\n\r\n");
14389 const MockWrite kGetProxyAuth(
14390 "GET http://www.example.com/ HTTP/1.1\r\n"
14391 "Host: www.example.com\r\n"
14392 "Proxy-Connection: keep-alive\r\n"
14393 "Proxy-Authorization: auth_token\r\n\r\n");
14394 const MockWrite kGetAuthThroughProxy(
14395 "GET http://www.example.com/ HTTP/1.1\r\n"
14396 "Host: www.example.com\r\n"
14397 "Proxy-Connection: keep-alive\r\n"
14398 "Authorization: auth_token\r\n\r\n");
14399 const MockWrite kGetAuthWithProxyAuth(
14400 "GET http://www.example.com/ HTTP/1.1\r\n"
14401 "Host: www.example.com\r\n"
14402 "Proxy-Connection: keep-alive\r\n"
14403 "Proxy-Authorization: auth_token\r\n"
14404 "Authorization: auth_token\r\n\r\n");
14405 const MockWrite kConnect(
14406 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714407 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514408 "Proxy-Connection: keep-alive\r\n\r\n");
14409 const MockWrite kConnectProxyAuth(
14410 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714411 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514412 "Proxy-Connection: keep-alive\r\n"
14413 "Proxy-Authorization: auth_token\r\n\r\n");
14414
14415 const MockRead kSuccess(
14416 "HTTP/1.1 200 OK\r\n"
14417 "Content-Type: text/html; charset=iso-8859-1\r\n"
14418 "Content-Length: 3\r\n\r\n"
14419 "Yes");
14420 const MockRead kFailure(
14421 "Should not be called.");
14422 const MockRead kServerChallenge(
14423 "HTTP/1.1 401 Unauthorized\r\n"
14424 "WWW-Authenticate: Mock realm=server\r\n"
14425 "Content-Type: text/html; charset=iso-8859-1\r\n"
14426 "Content-Length: 14\r\n\r\n"
14427 "Unauthorized\r\n");
14428 const MockRead kProxyChallenge(
14429 "HTTP/1.1 407 Unauthorized\r\n"
14430 "Proxy-Authenticate: Mock realm=proxy\r\n"
14431 "Proxy-Connection: close\r\n"
14432 "Content-Type: text/html; charset=iso-8859-1\r\n"
14433 "Content-Length: 14\r\n\r\n"
14434 "Unauthorized\r\n");
14435 const MockRead kProxyConnected(
14436 "HTTP/1.1 200 Connection Established\r\n\r\n");
14437
14438 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
14439 // no constructors, but the C++ compiler on Windows warns about
14440 // unspecified data in compound literals. So, moved to using constructors,
14441 // and TestRound's created with the default constructor should not be used.
14442 struct TestRound {
14443 TestRound()
Raul Tambre94493c652019-03-11 17:18:3514444 : expected_rv(ERR_UNEXPECTED),
14445 extra_write(nullptr),
14446 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4314447 TestRound(const MockWrite& write_arg,
14448 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1514449 int expected_rv_arg)
14450 : write(write_arg),
14451 read(read_arg),
14452 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3514453 extra_write(nullptr),
14454 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1514455 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
14456 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0114457 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1514458 : write(write_arg),
14459 read(read_arg),
14460 expected_rv(expected_rv_arg),
14461 extra_write(extra_write_arg),
14462 extra_read(extra_read_arg) {
14463 }
14464 MockWrite write;
14465 MockRead read;
14466 int expected_rv;
14467 const MockWrite* extra_write;
14468 const MockRead* extra_read;
14469 };
14470
14471 static const int kNoSSL = 500;
14472
14473 struct TestConfig {
asanka463ca4262016-11-16 02:34:3114474 int line_number;
thestig9d3bb0c2015-01-24 00:49:5114475 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1514476 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3114477 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5114478 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1514479 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3114480 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1514481 int num_auth_rounds;
14482 int first_ssl_round;
asankae2257db2016-10-11 22:03:1614483 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1514484 } test_configs[] = {
asankac93076192016-10-03 15:46:0214485 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114486 {__LINE__,
14487 nullptr,
asankac93076192016-10-03 15:46:0214488 AUTH_NONE,
14489 OK,
14490 kServer,
14491 AUTH_NONE,
14492 OK,
14493 1,
14494 kNoSSL,
14495 {TestRound(kGet, kSuccess, OK)}},
14496 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114497 {__LINE__,
14498 nullptr,
asankac93076192016-10-03 15:46:0214499 AUTH_NONE,
14500 OK,
14501 kServer,
14502 AUTH_SYNC,
14503 OK,
14504 2,
14505 kNoSSL,
14506 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514507 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114508 {__LINE__,
14509 nullptr,
asankac93076192016-10-03 15:46:0214510 AUTH_NONE,
14511 OK,
14512 kServer,
14513 AUTH_SYNC,
14514 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614515 3,
14516 kNoSSL,
14517 {TestRound(kGet, kServerChallenge, OK),
14518 TestRound(kGet, kServerChallenge, OK),
14519 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114520 {__LINE__,
14521 nullptr,
asankae2257db2016-10-11 22:03:1614522 AUTH_NONE,
14523 OK,
14524 kServer,
14525 AUTH_SYNC,
14526 ERR_UNSUPPORTED_AUTH_SCHEME,
14527 2,
14528 kNoSSL,
14529 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114530 {__LINE__,
14531 nullptr,
asankae2257db2016-10-11 22:03:1614532 AUTH_NONE,
14533 OK,
14534 kServer,
14535 AUTH_SYNC,
14536 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
14537 2,
14538 kNoSSL,
14539 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114540 {__LINE__,
14541 kProxy,
asankae2257db2016-10-11 22:03:1614542 AUTH_SYNC,
14543 ERR_FAILED,
14544 kServer,
14545 AUTH_NONE,
14546 OK,
14547 2,
14548 kNoSSL,
14549 {TestRound(kGetProxy, kProxyChallenge, OK),
14550 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114551 {__LINE__,
14552 kProxy,
asankae2257db2016-10-11 22:03:1614553 AUTH_ASYNC,
14554 ERR_FAILED,
14555 kServer,
14556 AUTH_NONE,
14557 OK,
14558 2,
14559 kNoSSL,
14560 {TestRound(kGetProxy, kProxyChallenge, OK),
14561 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114562 {__LINE__,
14563 nullptr,
asankae2257db2016-10-11 22:03:1614564 AUTH_NONE,
14565 OK,
14566 kServer,
14567 AUTH_SYNC,
14568 ERR_FAILED,
asankac93076192016-10-03 15:46:0214569 2,
14570 kNoSSL,
14571 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614572 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114573 {__LINE__,
14574 nullptr,
asankae2257db2016-10-11 22:03:1614575 AUTH_NONE,
14576 OK,
14577 kServer,
14578 AUTH_ASYNC,
14579 ERR_FAILED,
14580 2,
14581 kNoSSL,
14582 {TestRound(kGet, kServerChallenge, OK),
14583 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114584 {__LINE__,
14585 nullptr,
asankac93076192016-10-03 15:46:0214586 AUTH_NONE,
14587 OK,
14588 kServer,
14589 AUTH_ASYNC,
14590 OK,
14591 2,
14592 kNoSSL,
14593 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514594 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114595 {__LINE__,
14596 nullptr,
asankac93076192016-10-03 15:46:0214597 AUTH_NONE,
14598 OK,
14599 kServer,
14600 AUTH_ASYNC,
14601 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614602 3,
asankac93076192016-10-03 15:46:0214603 kNoSSL,
14604 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614605 // The second round uses a HttpAuthHandlerMock that always succeeds.
14606 TestRound(kGet, kServerChallenge, OK),
14607 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214608 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114609 {__LINE__,
14610 kProxy,
asankac93076192016-10-03 15:46:0214611 AUTH_NONE,
14612 OK,
14613 kServer,
14614 AUTH_NONE,
14615 OK,
14616 1,
14617 kNoSSL,
14618 {TestRound(kGetProxy, kSuccess, OK)}},
14619 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114620 {__LINE__,
14621 kProxy,
asankac93076192016-10-03 15:46:0214622 AUTH_NONE,
14623 OK,
14624 kServer,
14625 AUTH_SYNC,
14626 OK,
14627 2,
14628 kNoSSL,
14629 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514630 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114631 {__LINE__,
14632 kProxy,
asankac93076192016-10-03 15:46:0214633 AUTH_NONE,
14634 OK,
14635 kServer,
14636 AUTH_SYNC,
14637 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614638 3,
asankac93076192016-10-03 15:46:0214639 kNoSSL,
14640 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614641 TestRound(kGetProxy, kServerChallenge, OK),
14642 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114643 {__LINE__,
14644 kProxy,
asankac93076192016-10-03 15:46:0214645 AUTH_NONE,
14646 OK,
14647 kServer,
14648 AUTH_ASYNC,
14649 OK,
14650 2,
14651 kNoSSL,
14652 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514653 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114654 {__LINE__,
14655 kProxy,
asankac93076192016-10-03 15:46:0214656 AUTH_NONE,
14657 OK,
14658 kServer,
14659 AUTH_ASYNC,
14660 ERR_INVALID_AUTH_CREDENTIALS,
14661 2,
14662 kNoSSL,
14663 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614664 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214665 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114666 {__LINE__,
14667 kProxy,
asankac93076192016-10-03 15:46:0214668 AUTH_SYNC,
14669 OK,
14670 kServer,
14671 AUTH_NONE,
14672 OK,
14673 2,
14674 kNoSSL,
14675 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514676 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114677 {__LINE__,
14678 kProxy,
asankac93076192016-10-03 15:46:0214679 AUTH_SYNC,
14680 ERR_INVALID_AUTH_CREDENTIALS,
14681 kServer,
14682 AUTH_NONE,
14683 OK,
14684 2,
14685 kNoSSL,
14686 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614687 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114688 {__LINE__,
14689 kProxy,
asankac93076192016-10-03 15:46:0214690 AUTH_ASYNC,
14691 OK,
14692 kServer,
14693 AUTH_NONE,
14694 OK,
14695 2,
14696 kNoSSL,
14697 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514698 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114699 {__LINE__,
14700 kProxy,
asankac93076192016-10-03 15:46:0214701 AUTH_ASYNC,
14702 ERR_INVALID_AUTH_CREDENTIALS,
14703 kServer,
14704 AUTH_NONE,
14705 OK,
14706 2,
14707 kNoSSL,
14708 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614709 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114710 {__LINE__,
14711 kProxy,
14712 AUTH_ASYNC,
14713 ERR_INVALID_AUTH_CREDENTIALS,
14714 kServer,
14715 AUTH_NONE,
14716 OK,
14717 3,
14718 kNoSSL,
14719 {TestRound(kGetProxy, kProxyChallenge, OK),
14720 TestRound(kGetProxy, kProxyChallenge, OK),
14721 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214722 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114723 {__LINE__,
14724 kProxy,
asankac93076192016-10-03 15:46:0214725 AUTH_SYNC,
14726 OK,
14727 kServer,
14728 AUTH_SYNC,
14729 OK,
14730 3,
14731 kNoSSL,
14732 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514733 TestRound(kGetProxyAuth, kServerChallenge, OK),
14734 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114735 {__LINE__,
14736 kProxy,
asankac93076192016-10-03 15:46:0214737 AUTH_SYNC,
14738 OK,
14739 kServer,
14740 AUTH_SYNC,
14741 ERR_INVALID_AUTH_CREDENTIALS,
14742 3,
14743 kNoSSL,
14744 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514745 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614746 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114747 {__LINE__,
14748 kProxy,
asankac93076192016-10-03 15:46:0214749 AUTH_ASYNC,
14750 OK,
14751 kServer,
14752 AUTH_SYNC,
14753 OK,
14754 3,
14755 kNoSSL,
14756 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514757 TestRound(kGetProxyAuth, kServerChallenge, OK),
14758 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114759 {__LINE__,
14760 kProxy,
asankac93076192016-10-03 15:46:0214761 AUTH_ASYNC,
14762 OK,
14763 kServer,
14764 AUTH_SYNC,
14765 ERR_INVALID_AUTH_CREDENTIALS,
14766 3,
14767 kNoSSL,
14768 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514769 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614770 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114771 {__LINE__,
14772 kProxy,
asankac93076192016-10-03 15:46:0214773 AUTH_SYNC,
14774 OK,
14775 kServer,
14776 AUTH_ASYNC,
14777 OK,
14778 3,
14779 kNoSSL,
14780 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514781 TestRound(kGetProxyAuth, kServerChallenge, OK),
14782 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114783 {__LINE__,
14784 kProxy,
14785 AUTH_SYNC,
14786 ERR_INVALID_AUTH_CREDENTIALS,
14787 kServer,
14788 AUTH_ASYNC,
14789 OK,
14790 4,
14791 kNoSSL,
14792 {TestRound(kGetProxy, kProxyChallenge, OK),
14793 TestRound(kGetProxy, kProxyChallenge, OK),
14794 TestRound(kGetProxyAuth, kServerChallenge, OK),
14795 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
14796 {__LINE__,
14797 kProxy,
asankac93076192016-10-03 15:46:0214798 AUTH_SYNC,
14799 OK,
14800 kServer,
14801 AUTH_ASYNC,
14802 ERR_INVALID_AUTH_CREDENTIALS,
14803 3,
14804 kNoSSL,
14805 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514806 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614807 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114808 {__LINE__,
14809 kProxy,
asankac93076192016-10-03 15:46:0214810 AUTH_ASYNC,
14811 OK,
14812 kServer,
14813 AUTH_ASYNC,
14814 OK,
14815 3,
14816 kNoSSL,
14817 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514818 TestRound(kGetProxyAuth, kServerChallenge, OK),
14819 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114820 {__LINE__,
14821 kProxy,
asankac93076192016-10-03 15:46:0214822 AUTH_ASYNC,
14823 OK,
14824 kServer,
14825 AUTH_ASYNC,
14826 ERR_INVALID_AUTH_CREDENTIALS,
14827 3,
14828 kNoSSL,
14829 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514830 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614831 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114832 {__LINE__,
14833 kProxy,
14834 AUTH_ASYNC,
14835 ERR_INVALID_AUTH_CREDENTIALS,
14836 kServer,
14837 AUTH_ASYNC,
14838 ERR_INVALID_AUTH_CREDENTIALS,
14839 4,
14840 kNoSSL,
14841 {TestRound(kGetProxy, kProxyChallenge, OK),
14842 TestRound(kGetProxy, kProxyChallenge, OK),
14843 TestRound(kGetProxyAuth, kServerChallenge, OK),
14844 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214845 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114846 {__LINE__,
14847 nullptr,
asankac93076192016-10-03 15:46:0214848 AUTH_NONE,
14849 OK,
14850 kSecureServer,
14851 AUTH_NONE,
14852 OK,
14853 1,
14854 0,
14855 {TestRound(kGet, kSuccess, OK)}},
14856 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114857 {__LINE__,
14858 nullptr,
asankac93076192016-10-03 15:46:0214859 AUTH_NONE,
14860 OK,
14861 kSecureServer,
14862 AUTH_SYNC,
14863 OK,
14864 2,
14865 0,
14866 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514867 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114868 {__LINE__,
14869 nullptr,
asankac93076192016-10-03 15:46:0214870 AUTH_NONE,
14871 OK,
14872 kSecureServer,
14873 AUTH_SYNC,
14874 ERR_INVALID_AUTH_CREDENTIALS,
14875 2,
14876 0,
asankae2257db2016-10-11 22:03:1614877 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114878 {__LINE__,
14879 nullptr,
asankac93076192016-10-03 15:46:0214880 AUTH_NONE,
14881 OK,
14882 kSecureServer,
14883 AUTH_ASYNC,
14884 OK,
14885 2,
14886 0,
14887 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514888 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114889 {__LINE__,
14890 nullptr,
asankac93076192016-10-03 15:46:0214891 AUTH_NONE,
14892 OK,
14893 kSecureServer,
14894 AUTH_ASYNC,
14895 ERR_INVALID_AUTH_CREDENTIALS,
14896 2,
14897 0,
asankae2257db2016-10-11 22:03:1614898 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214899 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114900 {__LINE__,
14901 kProxy,
asankac93076192016-10-03 15:46:0214902 AUTH_NONE,
14903 OK,
14904 kSecureServer,
14905 AUTH_NONE,
14906 OK,
14907 1,
14908 0,
14909 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
14910 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114911 {__LINE__,
14912 kProxy,
asankac93076192016-10-03 15:46:0214913 AUTH_NONE,
14914 OK,
14915 kSecureServer,
14916 AUTH_SYNC,
14917 OK,
14918 2,
14919 0,
14920 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514921 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114922 {__LINE__,
14923 kProxy,
asankac93076192016-10-03 15:46:0214924 AUTH_NONE,
14925 OK,
14926 kSecureServer,
14927 AUTH_SYNC,
14928 ERR_INVALID_AUTH_CREDENTIALS,
14929 2,
14930 0,
14931 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614932 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114933 {__LINE__,
14934 kProxy,
asankac93076192016-10-03 15:46:0214935 AUTH_NONE,
14936 OK,
14937 kSecureServer,
14938 AUTH_ASYNC,
14939 OK,
14940 2,
14941 0,
14942 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514943 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114944 {__LINE__,
14945 kProxy,
asankac93076192016-10-03 15:46:0214946 AUTH_NONE,
14947 OK,
14948 kSecureServer,
14949 AUTH_ASYNC,
14950 ERR_INVALID_AUTH_CREDENTIALS,
14951 2,
14952 0,
14953 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614954 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214955 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114956 {__LINE__,
14957 kProxy,
asankac93076192016-10-03 15:46:0214958 AUTH_SYNC,
14959 OK,
14960 kSecureServer,
14961 AUTH_NONE,
14962 OK,
14963 2,
14964 1,
14965 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514966 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114967 {__LINE__,
14968 kProxy,
asankac93076192016-10-03 15:46:0214969 AUTH_SYNC,
14970 ERR_INVALID_AUTH_CREDENTIALS,
14971 kSecureServer,
14972 AUTH_NONE,
14973 OK,
14974 2,
14975 kNoSSL,
14976 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614977 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114978 {__LINE__,
14979 kProxy,
asankae2257db2016-10-11 22:03:1614980 AUTH_SYNC,
14981 ERR_UNSUPPORTED_AUTH_SCHEME,
14982 kSecureServer,
14983 AUTH_NONE,
14984 OK,
14985 2,
14986 kNoSSL,
14987 {TestRound(kConnect, kProxyChallenge, OK),
14988 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114989 {__LINE__,
14990 kProxy,
asankae2257db2016-10-11 22:03:1614991 AUTH_SYNC,
14992 ERR_UNEXPECTED,
14993 kSecureServer,
14994 AUTH_NONE,
14995 OK,
14996 2,
14997 kNoSSL,
14998 {TestRound(kConnect, kProxyChallenge, OK),
14999 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3115000 {__LINE__,
15001 kProxy,
asankac93076192016-10-03 15:46:0215002 AUTH_ASYNC,
15003 OK,
15004 kSecureServer,
15005 AUTH_NONE,
15006 OK,
15007 2,
15008 1,
15009 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515010 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115011 {__LINE__,
15012 kProxy,
asankac93076192016-10-03 15:46:0215013 AUTH_ASYNC,
15014 ERR_INVALID_AUTH_CREDENTIALS,
15015 kSecureServer,
15016 AUTH_NONE,
15017 OK,
15018 2,
15019 kNoSSL,
15020 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615021 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0215022 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115023 {__LINE__,
15024 kProxy,
asankac93076192016-10-03 15:46:0215025 AUTH_SYNC,
15026 OK,
15027 kSecureServer,
15028 AUTH_SYNC,
15029 OK,
15030 3,
15031 1,
15032 {TestRound(kConnect, kProxyChallenge, OK),
15033 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15034 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515035 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115036 {__LINE__,
15037 kProxy,
asankac93076192016-10-03 15:46:0215038 AUTH_SYNC,
15039 OK,
15040 kSecureServer,
15041 AUTH_SYNC,
15042 ERR_INVALID_AUTH_CREDENTIALS,
15043 3,
15044 1,
15045 {TestRound(kConnect, kProxyChallenge, OK),
15046 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15047 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615048 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115049 {__LINE__,
15050 kProxy,
asankac93076192016-10-03 15:46:0215051 AUTH_ASYNC,
15052 OK,
15053 kSecureServer,
15054 AUTH_SYNC,
15055 OK,
15056 3,
15057 1,
15058 {TestRound(kConnect, kProxyChallenge, OK),
15059 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15060 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515061 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115062 {__LINE__,
15063 kProxy,
asankac93076192016-10-03 15:46:0215064 AUTH_ASYNC,
15065 OK,
15066 kSecureServer,
15067 AUTH_SYNC,
15068 ERR_INVALID_AUTH_CREDENTIALS,
15069 3,
15070 1,
15071 {TestRound(kConnect, kProxyChallenge, OK),
15072 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15073 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615074 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115075 {__LINE__,
15076 kProxy,
asankac93076192016-10-03 15:46:0215077 AUTH_SYNC,
15078 OK,
15079 kSecureServer,
15080 AUTH_ASYNC,
15081 OK,
15082 3,
15083 1,
15084 {TestRound(kConnect, kProxyChallenge, OK),
15085 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15086 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515087 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115088 {__LINE__,
15089 kProxy,
asankac93076192016-10-03 15:46:0215090 AUTH_SYNC,
15091 OK,
15092 kSecureServer,
15093 AUTH_ASYNC,
15094 ERR_INVALID_AUTH_CREDENTIALS,
15095 3,
15096 1,
15097 {TestRound(kConnect, kProxyChallenge, OK),
15098 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15099 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615100 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115101 {__LINE__,
15102 kProxy,
asankac93076192016-10-03 15:46:0215103 AUTH_ASYNC,
15104 OK,
15105 kSecureServer,
15106 AUTH_ASYNC,
15107 OK,
15108 3,
15109 1,
15110 {TestRound(kConnect, kProxyChallenge, OK),
15111 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15112 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515113 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115114 {__LINE__,
15115 kProxy,
asankac93076192016-10-03 15:46:0215116 AUTH_ASYNC,
15117 OK,
15118 kSecureServer,
15119 AUTH_ASYNC,
15120 ERR_INVALID_AUTH_CREDENTIALS,
15121 3,
15122 1,
15123 {TestRound(kConnect, kProxyChallenge, OK),
15124 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15125 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615126 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115127 {__LINE__,
15128 kProxy,
15129 AUTH_ASYNC,
15130 ERR_INVALID_AUTH_CREDENTIALS,
15131 kSecureServer,
15132 AUTH_ASYNC,
15133 ERR_INVALID_AUTH_CREDENTIALS,
15134 4,
15135 2,
15136 {TestRound(kConnect, kProxyChallenge, OK),
15137 TestRound(kConnect, kProxyChallenge, OK),
15138 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15139 &kServerChallenge),
15140 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1515141 };
15142
asanka463ca4262016-11-16 02:34:3115143 for (const auto& test_config : test_configs) {
15144 SCOPED_TRACE(::testing::Message() << "Test config at "
15145 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0815146 HttpAuthHandlerMock::Factory* auth_factory(
15147 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715148 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4915149 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2615150
15151 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1515152 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3115153 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0815154 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15155 std::string auth_challenge = "Mock realm=proxy";
15156 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2415157 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15158 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0815159 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2015160 empty_ssl_info, origin,
15161 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815162 auth_handler->SetGenerateExpectation(
15163 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115164 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0815165 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
15166 }
[email protected]044de0642010-06-17 10:42:1515167 }
15168 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0015169 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1515170 std::string auth_challenge = "Mock realm=server";
15171 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2415172 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15173 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1515174 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2015175 empty_ssl_info, origin,
15176 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515177 auth_handler->SetGenerateExpectation(
15178 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115179 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0815180 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1615181
15182 // The second handler always succeeds. It should only be used where there
15183 // are multiple auth sessions for server auth in the same network
15184 // transaction using the same auth scheme.
15185 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1915186 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1615187 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
15188 empty_ssl_info, origin,
15189 NetLogWithSource());
15190 second_handler->SetGenerateExpectation(true, OK);
15191 auth_factory->AddMockHandler(second_handler.release(),
15192 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1515193 }
15194 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5915195 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915196 ProxyResolutionService::CreateFixed(test_config.proxy_url,
15197 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515198 } else {
Bence Béky53a5aef2018-03-29 21:54:1215199 session_deps_.proxy_resolution_service =
15200 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1515201 }
15202
15203 HttpRequestInfo request;
15204 request.method = "GET";
15205 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e62018-02-07 07:41:1015206 request.traffic_annotation =
15207 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515208
danakj1fd259a02016-04-16 03:17:0915209 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1515210
rchcb68dc62015-05-21 04:45:3615211 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
15212
15213 std::vector<std::vector<MockRead>> mock_reads(1);
15214 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1515215 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215216 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1515217 const TestRound& read_write_round = test_config.rounds[round];
15218
15219 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3615220 mock_reads.back().push_back(read_write_round.read);
15221 mock_writes.back().push_back(read_write_round.write);
15222
15223 // kProxyChallenge uses Proxy-Connection: close which means that the
15224 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5415225 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3615226 mock_reads.push_back(std::vector<MockRead>());
15227 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1515228 }
15229
rchcb68dc62015-05-21 04:45:3615230 if (read_write_round.extra_read) {
15231 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1515232 }
rchcb68dc62015-05-21 04:45:3615233 if (read_write_round.extra_write) {
15234 mock_writes.back().push_back(*read_write_round.extra_write);
15235 }
[email protected]044de0642010-06-17 10:42:1515236
15237 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1515238 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0715239 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1515240 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3615241 }
[email protected]044de0642010-06-17 10:42:1515242
danakj1fd259a02016-04-16 03:17:0915243 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3615244 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1915245 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0115246 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3615247 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3215248 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3615249 }
15250
mmenkecc2298e2015-12-07 18:20:1815251 // Transaction must be created after DataProviders, so it's destroyed before
15252 // they are as well.
15253 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15254
rchcb68dc62015-05-21 04:45:3615255 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215256 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3615257 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1515258 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4115259 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1515260 int rv;
15261 if (round == 0) {
tfarina42834112016-09-22 13:38:2015262 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515263 } else {
[email protected]49639fa2011-12-20 23:22:4115264 rv = trans.RestartWithAuth(
15265 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1515266 }
15267 if (rv == ERR_IO_PENDING)
15268 rv = callback.WaitForResult();
15269
15270 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1615271 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5015272 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5515273 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1515274 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
15275 continue;
15276 }
15277 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5815278 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1515279 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5815280 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1615281 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1515282 }
15283 }
[email protected]e5ae96a2010-04-14 20:12:4515284 }
15285}
15286
bncd16676a2016-07-20 16:23:0115287TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1415288 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1415289 HttpAuthHandlerMock::Factory* auth_factory(
15290 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715291 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1215292 session_deps_.proxy_resolution_service =
15293 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0715294 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1415295
15296 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15297 auth_handler->set_connection_based(true);
15298 std::string auth_challenge = "Mock realm=server";
15299 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2415300 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15301 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4915302 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1415303 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2015304 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815305 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1415306
[email protected]c871bce92010-07-15 21:51:1415307 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3515308 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1415309 HttpRequestInfo request;
15310 request.method = "GET";
15311 request.url = origin;
Ramin Halavatib5e433e62018-02-07 07:41:1015312 request.traffic_annotation =
15313 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715314
danakj1fd259a02016-04-16 03:17:0915315 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1015316
15317 // Use a TCP Socket Pool with only one connection per group. This is used
15318 // to validate that the TCP socket is not released to the pool between
15319 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4215320 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3615321 CommonConnectJobParams common_connect_job_params(
15322 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2815323 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5915324 50, // Max sockets for pool
15325 1, // Max sockets per group
15326 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3615327 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5215328 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1915329 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4015330 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
15331 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4815332 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1015333
bnc691fda62016-08-12 00:43:1615334 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115335 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1415336
15337 const MockWrite kGet(
15338 "GET / HTTP/1.1\r\n"
15339 "Host: www.example.com\r\n"
15340 "Connection: keep-alive\r\n\r\n");
15341 const MockWrite kGetAuth(
15342 "GET / HTTP/1.1\r\n"
15343 "Host: www.example.com\r\n"
15344 "Connection: keep-alive\r\n"
15345 "Authorization: auth_token\r\n\r\n");
15346
15347 const MockRead kServerChallenge(
15348 "HTTP/1.1 401 Unauthorized\r\n"
15349 "WWW-Authenticate: Mock realm=server\r\n"
15350 "Content-Type: text/html; charset=iso-8859-1\r\n"
15351 "Content-Length: 14\r\n\r\n"
15352 "Unauthorized\r\n");
15353 const MockRead kSuccess(
15354 "HTTP/1.1 200 OK\r\n"
15355 "Content-Type: text/html; charset=iso-8859-1\r\n"
15356 "Content-Length: 3\r\n\r\n"
15357 "Yes");
15358
15359 MockWrite writes[] = {
15360 // First round
15361 kGet,
15362 // Second round
15363 kGetAuth,
15364 // Third round
15365 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3015366 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1015367 kGetAuth,
15368 // Competing request
15369 kGet,
[email protected]c871bce92010-07-15 21:51:1415370 };
15371 MockRead reads[] = {
15372 // First round
15373 kServerChallenge,
15374 // Second round
15375 kServerChallenge,
15376 // Third round
[email protected]eca50e122010-09-11 14:03:3015377 kServerChallenge,
15378 // Fourth round
[email protected]c871bce92010-07-15 21:51:1415379 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1015380 // Competing response
15381 kSuccess,
[email protected]c871bce92010-07-15 21:51:1415382 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115383 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0715384 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1415385
Matt Menkef6edce752019-03-19 17:21:5615386 const ClientSocketPool::GroupId kSocketGroup(
15387 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3415388 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
15389 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1015390
15391 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1415392 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2015393 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1415394 if (rv == ERR_IO_PENDING)
15395 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115396 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615397 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215398 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815399 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315400 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115401 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15402 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415403
[email protected]7ef4cbbb2011-02-06 11:19:1015404 // In between rounds, another request comes in for the same domain.
15405 // It should not be able to grab the TCP socket that trans has already
15406 // claimed.
bnc691fda62016-08-12 00:43:1615407 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115408 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2015409 rv = trans_compete.Start(&request, callback_compete.callback(),
15410 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115411 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1015412 // callback_compete.WaitForResult at this point would stall forever,
15413 // since the HttpNetworkTransaction does not release the request back to
15414 // the pool until after authentication completes.
15415
15416 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1415417 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615418 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415419 if (rv == ERR_IO_PENDING)
15420 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115421 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615422 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215423 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815424 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315425 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115426 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15427 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415428
[email protected]7ef4cbbb2011-02-06 11:19:1015429 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1415430 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615431 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415432 if (rv == ERR_IO_PENDING)
15433 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115434 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615435 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215436 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815437 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315438 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115439 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15440 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3015441
[email protected]7ef4cbbb2011-02-06 11:19:1015442 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3015443 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615444 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3015445 if (rv == ERR_IO_PENDING)
15446 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115447 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615448 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215449 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815450 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315451 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015452
asanka463ca4262016-11-16 02:34:3115453 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
15454 // auth handler should transition to a DONE state in concert with the remote
15455 // server. But that's not something we can test here with a mock handler.
15456 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
15457 auth_handler->state());
15458
[email protected]7ef4cbbb2011-02-06 11:19:1015459 // Read the body since the fourth round was successful. This will also
15460 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4415461 scoped_refptr<IOBufferWithSize> io_buf =
15462 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1615463 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015464 if (rv == ERR_IO_PENDING)
15465 rv = callback.WaitForResult();
15466 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615467 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015468 EXPECT_EQ(0, rv);
15469 // There are still 0 idle sockets, since the trans_compete transaction
15470 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315471 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015472
15473 // The competing request can now finish. Wait for the headers and then
15474 // read the body.
15475 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0115476 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615477 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015478 if (rv == ERR_IO_PENDING)
15479 rv = callback.WaitForResult();
15480 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615481 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015482 EXPECT_EQ(0, rv);
15483
15484 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315485 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1415486}
15487
[email protected]65041fa2010-05-21 06:56:5315488// This tests the case that a request is issued via http instead of spdy after
15489// npn is negotiated.
bncd16676a2016-07-20 16:23:0115490TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5315491 HttpRequestInfo request;
15492 request.method = "GET";
bncce36dca22015-04-21 22:11:2315493 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015494 request.traffic_annotation =
15495 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5315496
15497 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2315498 MockWrite(
15499 "GET / HTTP/1.1\r\n"
15500 "Host: www.example.org\r\n"
15501 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5315502 };
15503
15504 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5215505 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4315506 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5215507 MockRead("\r\n"),
15508 MockRead("hello world"),
15509 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5315510 };
15511
[email protected]8ddf8322012-02-23 18:08:0615512 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615513 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5315514
[email protected]bb88e1d32013-05-03 23:11:0715515 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5315516
Ryan Sleevib8d7ea02018-05-07 20:01:0115517 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715518 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5315519
[email protected]49639fa2011-12-20 23:22:4115520 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5315521
danakj1fd259a02016-04-16 03:17:0915522 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615523 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5315524
tfarina42834112016-09-22 13:38:2015525 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5315526
robpercival214763f2016-07-01 23:27:0115527 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15528 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5315529
bnc691fda62016-08-12 00:43:1615530 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215531 ASSERT_TRUE(response);
15532 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5315533 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15534
15535 std::string response_data;
bnc691fda62016-08-12 00:43:1615536 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5315537 EXPECT_EQ("hello world", response_data);
15538
15539 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215540 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5315541}
[email protected]26ef6582010-06-24 02:30:4715542
bnc55ff9da2015-08-19 18:42:3515543// Simulate the SSL handshake completing with an NPN negotiation followed by an
15544// immediate server closing of the socket.
15545// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0115546TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4715547 HttpRequestInfo request;
15548 request.method = "GET";
bncce36dca22015-04-21 22:11:2315549 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015550 request.traffic_annotation =
15551 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4715552
[email protected]8ddf8322012-02-23 18:08:0615553 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615554 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715555 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4715556
Ryan Hamilton0239aac2018-05-19 00:03:1315557 spdy::SpdySerializedFrame req(
15558 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115559 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4715560
15561 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615562 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4715563 };
15564
Ryan Sleevib8d7ea02018-05-07 20:01:0115565 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715566 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4715567
[email protected]49639fa2011-12-20 23:22:4115568 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4715569
danakj1fd259a02016-04-16 03:17:0915570 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615571 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4715572
tfarina42834112016-09-22 13:38:2015573 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115574 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15575 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4715576}
[email protected]65d34382010-07-01 18:12:2615577
[email protected]795cbf82013-07-22 09:37:2715578// A subclass of HttpAuthHandlerMock that records the request URL when
15579// it gets it. This is needed since the auth handler may get destroyed
15580// before we get a chance to query it.
15581class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
15582 public:
15583 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
15584
Chris Watkins7a41d3552017-12-01 02:13:2715585 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2715586
15587 protected:
dchengb03027d2014-10-21 12:00:2015588 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
15589 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0915590 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2015591 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2715592 *url_ = request->url;
15593 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0915594 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2715595 }
15596
15597 private:
15598 GURL* url_;
15599};
15600
[email protected]8e6441ca2010-08-19 05:56:3815601// Test that if we cancel the transaction as the connection is completing, that
15602// everything tears down correctly.
bncd16676a2016-07-20 16:23:0115603TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3815604 // Setup everything about the connection to complete synchronously, so that
15605 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
15606 // for is the callback from the HttpStreamRequest.
15607 // Then cancel the transaction.
15608 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3615609 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3815610 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615611 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
15612 MockRead(SYNCHRONOUS, "hello world"),
15613 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3815614 };
15615
[email protected]8e6441ca2010-08-19 05:56:3815616 HttpRequestInfo request;
15617 request.method = "GET";
bncce36dca22015-04-21 22:11:2315618 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015619 request.traffic_annotation =
15620 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3815621
danakj1fd259a02016-04-16 03:17:0915622 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5815623 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1915624 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2715625
Ryan Sleevib8d7ea02018-05-07 20:01:0115626 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3815627 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0715628 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3815629
[email protected]49639fa2011-12-20 23:22:4115630 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3815631
vishal.b62985ca92015-04-17 08:45:5115632 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4115633 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115634 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3815635 trans.reset(); // Cancel the transaction here.
15636
fdoray92e35a72016-06-10 15:54:5515637 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3015638}
15639
[email protected]ecab6e052014-05-16 14:58:1215640// Test that if a transaction is cancelled after receiving the headers, the
15641// stream is drained properly and added back to the socket pool. The main
15642// purpose of this test is to make sure that an HttpStreamParser can be read
15643// from after the HttpNetworkTransaction and the objects it owns have been
15644// deleted.
15645// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0115646TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1215647 MockRead data_reads[] = {
15648 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
15649 MockRead(ASYNC, "Content-Length: 2\r\n"),
15650 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
15651 MockRead(ASYNC, "1"),
15652 // 2 async reads are necessary to trigger a ReadResponseBody call after the
15653 // HttpNetworkTransaction has been deleted.
15654 MockRead(ASYNC, "2"),
15655 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
15656 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115657 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1215658 session_deps_.socket_factory->AddSocketDataProvider(&data);
15659
danakj1fd259a02016-04-16 03:17:0915660 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1215661
15662 {
15663 HttpRequestInfo request;
15664 request.method = "GET";
bncce36dca22015-04-21 22:11:2315665 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015666 request.traffic_annotation =
15667 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1215668
dcheng48459ac22014-08-26 00:46:4115669 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1215670 TestCompletionCallback callback;
15671
tfarina42834112016-09-22 13:38:2015672 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115673 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1215674 callback.WaitForResult();
15675
15676 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215677 ASSERT_TRUE(response);
15678 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1215679 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15680
15681 // The transaction and HttpRequestInfo are deleted.
15682 }
15683
15684 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5515685 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1215686
15687 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4115688 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1215689}
15690
[email protected]76a505b2010-08-25 06:23:0015691// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0115692TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915693 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915694 ProxyResolutionService::CreateFixedFromPacResult(
15695 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115696 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715697 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915698 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015699
[email protected]76a505b2010-08-25 06:23:0015700 HttpRequestInfo request;
15701 request.method = "GET";
bncce36dca22015-04-21 22:11:2315702 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015703 request.traffic_annotation =
15704 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015705
15706 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2315707 MockWrite(
15708 "GET http://www.example.org/ HTTP/1.1\r\n"
15709 "Host: www.example.org\r\n"
15710 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015711 };
15712
15713 MockRead data_reads1[] = {
15714 MockRead("HTTP/1.1 200 OK\r\n"),
15715 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15716 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615717 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015718 };
15719
Ryan Sleevib8d7ea02018-05-07 20:01:0115720 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715721 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0015722
[email protected]49639fa2011-12-20 23:22:4115723 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015724
bnc691fda62016-08-12 00:43:1615725 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915726 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615727 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915728 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15729 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015730
bnc691fda62016-08-12 00:43:1615731 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115732 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015733
15734 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115735 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0015736
bnc691fda62016-08-12 00:43:1615737 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215738 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015739
15740 EXPECT_TRUE(response->headers->IsKeepAlive());
15741 EXPECT_EQ(200, response->headers->response_code());
15742 EXPECT_EQ(100, response->headers->GetContentLength());
15743 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715744 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15745 HostPortPair::FromString("myproxy:70")),
15746 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915747 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15748 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15749 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0015750 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2015751
15752 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615753 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015754 TestLoadTimingNotReusedWithPac(load_timing_info,
15755 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0015756}
15757
15758// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0115759TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915760 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915761 ProxyResolutionService::CreateFixedFromPacResult(
15762 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115763 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715764 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915765 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015766
[email protected]76a505b2010-08-25 06:23:0015767 HttpRequestInfo request;
15768 request.method = "GET";
bncce36dca22015-04-21 22:11:2315769 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015770 request.traffic_annotation =
15771 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015772
15773 // Since we have proxy, should try to establish tunnel.
15774 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715775 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15776 "Host: www.example.org:443\r\n"
15777 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015778
rsleevidb16bb02015-11-12 23:47:1715779 MockWrite("GET / HTTP/1.1\r\n"
15780 "Host: www.example.org\r\n"
15781 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015782 };
15783
15784 MockRead data_reads1[] = {
15785 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15786
15787 MockRead("HTTP/1.1 200 OK\r\n"),
15788 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15789 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615790 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015791 };
15792
Ryan Sleevib8d7ea02018-05-07 20:01:0115793 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715794 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615795 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715796 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015797
[email protected]49639fa2011-12-20 23:22:4115798 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015799
bnc691fda62016-08-12 00:43:1615800 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915801 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615802 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915803 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15804 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015805
bnc691fda62016-08-12 00:43:1615806 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115807 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015808
15809 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115810 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415811 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015812 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015813 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15814 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015815 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015816 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015817 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15818 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015819
bnc691fda62016-08-12 00:43:1615820 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215821 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015822
15823 EXPECT_TRUE(response->headers->IsKeepAlive());
15824 EXPECT_EQ(200, response->headers->response_code());
15825 EXPECT_EQ(100, response->headers->GetContentLength());
15826 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15827 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715828 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15829 HostPortPair::FromString("myproxy:70")),
15830 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915831 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15832 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15833 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2015834
15835 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615836 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015837 TestLoadTimingNotReusedWithPac(load_timing_info,
15838 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0015839}
15840
rsleevidb16bb02015-11-12 23:47:1715841// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
15842// literal host.
bncd16676a2016-07-20 16:23:0115843TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5915844 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915845 ProxyResolutionService::CreateFixedFromPacResult(
15846 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715847 BoundTestNetLog log;
15848 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915849 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1715850
15851 HttpRequestInfo request;
15852 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1515853 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e62018-02-07 07:41:1015854 request.traffic_annotation =
15855 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715856
15857 // Since we have proxy, should try to establish tunnel.
15858 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1515859 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
15860 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1715861 "Proxy-Connection: keep-alive\r\n\r\n"),
15862
15863 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1515864 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1715865 "Connection: keep-alive\r\n\r\n"),
15866 };
15867
15868 MockRead data_reads1[] = {
15869 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15870
15871 MockRead("HTTP/1.1 200 OK\r\n"),
15872 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15873 MockRead("Content-Length: 100\r\n\r\n"),
15874 MockRead(SYNCHRONOUS, OK),
15875 };
15876
Ryan Sleevib8d7ea02018-05-07 20:01:0115877 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1715878 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15879 SSLSocketDataProvider ssl(ASYNC, OK);
15880 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15881
15882 TestCompletionCallback callback1;
15883
bnc691fda62016-08-12 00:43:1615884 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1715885
bnc691fda62016-08-12 00:43:1615886 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115887 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1715888
15889 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115890 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415891 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1715892 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015893 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15894 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715895 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015896 entries, pos,
15897 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15898 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715899
bnc691fda62016-08-12 00:43:1615900 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215901 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1715902
15903 EXPECT_TRUE(response->headers->IsKeepAlive());
15904 EXPECT_EQ(200, response->headers->response_code());
15905 EXPECT_EQ(100, response->headers->GetContentLength());
15906 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15907 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715908 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15909 HostPortPair::FromString("myproxy:70")),
15910 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1715911
15912 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615913 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1715914 TestLoadTimingNotReusedWithPac(load_timing_info,
15915 CONNECT_TIMING_HAS_SSL_TIMES);
15916}
15917
[email protected]76a505b2010-08-25 06:23:0015918// Test a basic HTTPS GET request through a proxy, but the server hangs up
15919// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0115920TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4915921 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15922 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115923 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715924 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915925 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015926
[email protected]76a505b2010-08-25 06:23:0015927 HttpRequestInfo request;
15928 request.method = "GET";
bncce36dca22015-04-21 22:11:2315929 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015930 request.traffic_annotation =
15931 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015932
15933 // Since we have proxy, should try to establish tunnel.
15934 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715935 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15936 "Host: www.example.org:443\r\n"
15937 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015938
rsleevidb16bb02015-11-12 23:47:1715939 MockWrite("GET / HTTP/1.1\r\n"
15940 "Host: www.example.org\r\n"
15941 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015942 };
15943
15944 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0015945 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615946 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0015947 };
15948
Ryan Sleevib8d7ea02018-05-07 20:01:0115949 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715950 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615951 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715952 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015953
[email protected]49639fa2011-12-20 23:22:4115954 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015955
bnc691fda62016-08-12 00:43:1615956 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5015957
bnc691fda62016-08-12 00:43:1615958 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115959 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015960
15961 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115962 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5415963 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015964 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015965 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15966 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015967 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015968 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015969 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15970 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015971}
15972
[email protected]749eefa82010-09-13 22:14:0315973// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0115974TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1315975 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4915976 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115977 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0315978
Raul Tambre94493c652019-03-11 17:18:3515979 spdy::SpdySerializedFrame resp(
15980 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315981 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0315982 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115983 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0315984 };
15985
Ryan Sleevib8d7ea02018-05-07 20:01:0115986 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715987 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0315988
[email protected]8ddf8322012-02-23 18:08:0615989 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615990 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715991 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0315992
danakj1fd259a02016-04-16 03:17:0915993 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315994
15995 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315996 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015997 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115998 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3415999 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
16000 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2716001 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5216002 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0316003
16004 HttpRequestInfo request;
16005 request.method = "GET";
bncce36dca22015-04-21 22:11:2316006 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016007 request.traffic_annotation =
16008 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0316009
bnc691fda62016-08-12 00:43:1616010 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0316011
[email protected]41d64e82013-07-03 22:44:2616012 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016013 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116014 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16015 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0316016}
16017
[email protected]73b8dd222010-11-11 19:55:2416018// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1616019// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0216020void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0716021 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2916022 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716023 request_info.url = GURL("https://www.example.com/");
16024 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916025 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016026 request_info.traffic_annotation =
16027 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716028
[email protected]8ddf8322012-02-23 18:08:0616029 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2916030 MockWrite data_writes[] = {
16031 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2416032 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116033 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0716034 session_deps_.socket_factory->AddSocketDataProvider(&data);
16035 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2416036
danakj1fd259a02016-04-16 03:17:0916037 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616038 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2416039
[email protected]49639fa2011-12-20 23:22:4116040 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016041 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2916042 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2416043 rv = callback.WaitForResult();
16044 ASSERT_EQ(error, rv);
16045}
16046
bncd16676a2016-07-20 16:23:0116047TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2416048 // Just check a grab bag of cert errors.
16049 static const int kErrors[] = {
16050 ERR_CERT_COMMON_NAME_INVALID,
16051 ERR_CERT_AUTHORITY_INVALID,
16052 ERR_CERT_DATE_INVALID,
16053 };
Avi Drissman4365a4782018-12-28 19:26:2416054 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0616055 CheckErrorIsPassedBack(kErrors[i], ASYNC);
16056 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2416057 }
16058}
16059
[email protected]bd0b6772011-01-11 19:59:3016060// Ensure that a client certificate is removed from the SSL client auth
16061// cache when:
16062// 1) No proxy is involved.
16063// 2) TLS False Start is disabled.
16064// 3) The initial TLS handshake requests a client certificate.
16065// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116066TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916067 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716068 request_info.url = GURL("https://www.example.com/");
16069 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916070 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016071 request_info.traffic_annotation =
16072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716073
David Benjamin1c4b6d012019-07-08 17:12:5716074 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116075 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016076
16077 // [ssl_]data1 contains the data for the first SSL handshake. When a
16078 // CertificateRequest is received for the first time, the handshake will
16079 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2916080 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016081 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716082 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116083 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716084 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016085
16086 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
16087 // False Start is not being used, the result of the SSL handshake will be
16088 // returned as part of the SSLClientSocket::Connect() call. This test
16089 // matches the result of a server sending a handshake_failure alert,
16090 // rather than a Finished message, because it requires a client
16091 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2916092 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3016093 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716094 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0116095 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0716096 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016097
16098 // [ssl_]data3 contains the data for the third SSL handshake. When a
16099 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1316100 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
16101 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3016102 // of the HttpNetworkTransaction. Because this test failure is due to
16103 // requiring a client certificate, this fallback handshake should also
16104 // fail.
ttuttle859dc7a2015-04-23 19:42:2916105 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1316106 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3016107 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716108 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116109 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0716110 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016111
[email protected]80c75f682012-05-26 16:22:1716112 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
16113 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4216114 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
16115 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1716116 // of the HttpNetworkTransaction. Because this test failure is due to
16117 // requiring a client certificate, this fallback handshake should also
16118 // fail.
ttuttle859dc7a2015-04-23 19:42:2916119 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1716120 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716121 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116122 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0716123 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716124
danakj1fd259a02016-04-16 03:17:0916125 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616126 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016127
[email protected]bd0b6772011-01-11 19:59:3016128 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4116129 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016130 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116131 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016132
16133 // Complete the SSL handshake, which should abort due to requiring a
16134 // client certificate.
16135 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116136 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016137
16138 // Indicate that no certificate should be supplied. From the perspective
16139 // of SSLClientCertCache, NULL is just as meaningful as a real
16140 // certificate, so this is the same as supply a
16141 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516142 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116143 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016144
16145 // Ensure the certificate was added to the client auth cache before
16146 // allowing the connection to continue restarting.
16147 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416148 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116149 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416150 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216151 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016152
16153 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716154 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16155 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016156 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116157 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016158
16159 // Ensure that the client certificate is removed from the cache on a
16160 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116161 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416162 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016163}
16164
16165// Ensure that a client certificate is removed from the SSL client auth
16166// cache when:
16167// 1) No proxy is involved.
16168// 2) TLS False Start is enabled.
16169// 3) The initial TLS handshake requests a client certificate.
16170// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116171TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916172 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716173 request_info.url = GURL("https://www.example.com/");
16174 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916175 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016176 request_info.traffic_annotation =
16177 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716178
David Benjamin1c4b6d012019-07-08 17:12:5716179 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116180 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016181
16182 // When TLS False Start is used, SSLClientSocket::Connect() calls will
16183 // return successfully after reading up to the peer's Certificate message.
16184 // This is to allow the caller to call SSLClientSocket::Write(), which can
16185 // enqueue application data to be sent in the same packet as the
16186 // ChangeCipherSpec and Finished messages.
16187 // The actual handshake will be finished when SSLClientSocket::Read() is
16188 // called, which expects to process the peer's ChangeCipherSpec and
16189 // Finished messages. If there was an error negotiating with the peer,
16190 // such as due to the peer requiring a client certificate when none was
16191 // supplied, the alert sent by the peer won't be processed until Read() is
16192 // called.
16193
16194 // Like the non-False Start case, when a client certificate is requested by
16195 // the peer, the handshake is aborted during the Connect() call.
16196 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2916197 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016198 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716199 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116200 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716201 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016202
16203 // When a client certificate is supplied, Connect() will not be aborted
16204 // when the peer requests the certificate. Instead, the handshake will
16205 // artificially succeed, allowing the caller to write the HTTP request to
16206 // the socket. The handshake messages are not processed until Read() is
16207 // called, which then detects that the handshake was aborted, due to the
16208 // peer sending a handshake_failure because it requires a client
16209 // certificate.
ttuttle859dc7a2015-04-23 19:42:2916210 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016211 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716212 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2916213 MockRead data2_reads[] = {
16214 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3016215 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116216 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716217 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016218
16219 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1716220 // the data for the SSL handshake once the TLSv1.1 connection falls back to
16221 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916222 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016223 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716224 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116225 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716226 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016227
[email protected]80c75f682012-05-26 16:22:1716228 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
16229 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916230 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1716231 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116233 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716234 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716235
[email protected]7799de12013-05-30 05:52:5116236 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2916237 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5116238 ssl_data5.cert_request_info = cert_request.get();
16239 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0116240 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5116241 session_deps_.socket_factory->AddSocketDataProvider(&data5);
16242
danakj1fd259a02016-04-16 03:17:0916243 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616244 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016245
[email protected]bd0b6772011-01-11 19:59:3016246 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4116247 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016248 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116249 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016250
16251 // Complete the SSL handshake, which should abort due to requiring a
16252 // client certificate.
16253 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116254 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016255
16256 // Indicate that no certificate should be supplied. From the perspective
16257 // of SSLClientCertCache, NULL is just as meaningful as a real
16258 // certificate, so this is the same as supply a
16259 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516260 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116261 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016262
16263 // Ensure the certificate was added to the client auth cache before
16264 // allowing the connection to continue restarting.
16265 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416266 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116267 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416268 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216269 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016270
[email protected]bd0b6772011-01-11 19:59:3016271 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716272 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16273 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016274 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116275 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016276
16277 // Ensure that the client certificate is removed from the cache on a
16278 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116279 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416280 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016281}
16282
[email protected]8c405132011-01-11 22:03:1816283// Ensure that a client certificate is removed from the SSL client auth
16284// cache when:
16285// 1) An HTTPS proxy is involved.
16286// 3) The HTTPS proxy requests a client certificate.
16287// 4) The client supplies an invalid/unacceptable certificate for the
16288// proxy.
bncd16676a2016-07-20 16:23:0116289TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4916290 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
16291 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116292 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716293 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1816294
David Benjamin3b94b0f2019-04-25 23:07:5216295 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116296 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1816297
David Benjamin3b94b0f2019-04-25 23:07:5216298 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
16299 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2916300 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1816301 requests[0].url = GURL("https://www.example.com/");
16302 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916303 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016304 requests[0].traffic_annotation =
16305 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816306
David Benjamin3b94b0f2019-04-25 23:07:5216307 // HTTPS requests are tunneled.
16308 MockWrite https_writes[] = {
16309 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
16310 "Host: www.example.com:443\r\n"
16311 "Proxy-Connection: keep-alive\r\n\r\n"),
16312 };
16313
[email protected]8c405132011-01-11 22:03:1816314 requests[1].url = GURL("http://www.example.com/");
16315 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916316 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016317 requests[1].traffic_annotation =
16318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816319
David Benjamin3b94b0f2019-04-25 23:07:5216320 // HTTP requests are not.
16321 MockWrite http_writes[] = {
16322 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
16323 "Host: www.example.com\r\n"
16324 "Proxy-Connection: keep-alive\r\n\r\n"),
16325 };
[email protected]8c405132011-01-11 22:03:1816326
David Benjamin3b94b0f2019-04-25 23:07:5216327 // When the server rejects the client certificate, it will close the
16328 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
16329 // TLS 1.2 with False Start), the error is returned out of the first Read().
16330 for (bool reject_in_connect : {true, false}) {
16331 SCOPED_TRACE(reject_in_connect);
16332 // Client certificate errors are typically signaled with
16333 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
16334 // protocol error.
16335 for (Error reject_error :
16336 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
16337 SCOPED_TRACE(reject_error);
16338 // Tunneled and non-tunneled requests are handled differently. Test both.
16339 for (const HttpRequestInfo& request : requests) {
16340 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1816341
David Benjamin3b94b0f2019-04-25 23:07:5216342 session_deps_.socket_factory =
16343 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1816344
David Benjamin3b94b0f2019-04-25 23:07:5216345 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
16346 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
16347 // for proxies. Rather than represending the endpoint
16348 // (www.example.com:443), they represent failures with the HTTPS proxy
16349 // (proxy:70).
16350 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
16351 ssl_data1.cert_request_info = cert_request.get();
16352 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16353 StaticSocketDataProvider data1;
16354 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1816355
David Benjamin3b94b0f2019-04-25 23:07:5216356 base::Optional<SSLSocketDataProvider> ssl_data2;
16357 base::Optional<StaticSocketDataProvider> data2;
16358 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
16359 if (reject_in_connect) {
16360 ssl_data2.emplace(ASYNC, reject_error);
16361 // There are no reads or writes.
16362 data2.emplace();
16363 } else {
16364 ssl_data2.emplace(ASYNC, OK);
16365 // We will get one Write() in before observing the error in Read().
16366 if (request.url.SchemeIsCryptographic()) {
16367 data2.emplace(error_in_read, https_writes);
16368 } else {
16369 data2.emplace(error_in_read, http_writes);
16370 }
16371 }
16372 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1816373
David Benjamin3b94b0f2019-04-25 23:07:5216374 session_deps_.socket_factory->AddSSLSocketDataProvider(
16375 &ssl_data2.value());
16376 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1816377
David Benjamin3b94b0f2019-04-25 23:07:5216378 std::unique_ptr<HttpNetworkSession> session =
16379 CreateSession(&session_deps_);
16380 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16381
16382 // Begin the SSL handshake with the proxy.
16383 TestCompletionCallback callback;
16384 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16385 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16386
16387 // Complete the SSL handshake, which should abort due to requiring a
16388 // client certificate.
16389 rv = callback.WaitForResult();
16390 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16391
16392 // Indicate that no certificate should be supplied. From the
16393 // perspective of SSLClientCertCache, NULL is just as meaningful as a
16394 // real certificate, so this is the same as supply a
16395 // legitimate-but-unacceptable certificate.
16396 rv =
16397 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
16398 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16399
16400 // Ensure the certificate was added to the client auth cache before
16401 // allowing the connection to continue restarting.
16402 scoped_refptr<X509Certificate> client_cert;
16403 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116404 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216405 HostPortPair("proxy", 70), &client_cert, &client_private_key));
16406 ASSERT_FALSE(client_cert);
16407 // Ensure the certificate was NOT cached for the endpoint. This only
16408 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4116409 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216410 HostPortPair("www.example.com", 443), &client_cert,
16411 &client_private_key));
16412
16413 // Restart the handshake. This will consume ssl_data2. The result code
16414 // is checked against what ssl_data2 should return.
16415 rv = callback.WaitForResult();
16416 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
16417 IsError(reject_error)));
16418
16419 // Now that the new handshake has failed, ensure that the client
16420 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4116421 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216422 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4116423 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216424 HostPortPair("www.example.com", 443), &client_cert,
16425 &client_private_key));
16426 }
16427 }
[email protected]8c405132011-01-11 22:03:1816428 }
16429}
16430
David Benjamin1a0566082019-04-30 07:36:1916431// Test that HttpNetworkTransaction correctly handles (mocked) certificate
16432// requests during a TLS renegotiation.
16433TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
16434 HttpRequestInfo request_info;
16435 request_info.url = GURL("https://www.example.com/");
16436 request_info.method = "GET";
16437 request_info.load_flags = LOAD_NORMAL;
16438 request_info.traffic_annotation =
16439 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16440
16441 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
16442 cert_request->host_and_port = HostPortPair("www.example.com", 443);
16443
16444 std::unique_ptr<FakeClientCertIdentity> identity =
16445 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
16446 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
16447 ASSERT_TRUE(identity);
16448
16449 // The first connection's handshake succeeds, but we get
16450 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
16451 SSLSocketDataProvider ssl_data1(ASYNC, OK);
16452 ssl_data1.cert_request_info = cert_request.get();
16453 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16454 MockWrite data1_writes[] = {
16455 MockWrite("GET / HTTP/1.1\r\n"
16456 "Host: www.example.com\r\n"
16457 "Connection: keep-alive\r\n\r\n"),
16458 };
16459 MockRead data1_reads[] = {
16460 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
16461 };
16462 StaticSocketDataProvider data1(data1_reads, data1_writes);
16463 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16464
16465 // After supplying with certificate, we restart the request from the top,
16466 // which succeeds this time.
16467 SSLSocketDataProvider ssl_data2(ASYNC, OK);
16468 ssl_data2.expected_send_client_cert = true;
16469 ssl_data2.expected_client_cert = identity->certificate();
16470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
16471 MockWrite data2_writes[] = {
16472 MockWrite("GET / HTTP/1.1\r\n"
16473 "Host: www.example.com\r\n"
16474 "Connection: keep-alive\r\n\r\n"),
16475 };
16476 MockRead data2_reads[] = {
16477 MockRead("HTTP/1.1 200 OK\r\n"
16478 "Content-Length: 0\r\n\r\n"),
16479 };
16480 StaticSocketDataProvider data2(data2_reads, data2_writes);
16481 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16482
16483 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
16484 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16485
16486 TestCompletionCallback callback;
16487 int rv = callback.GetResult(
16488 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
16489 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16490
16491 rv = trans.RestartWithCertificate(identity->certificate(),
16492 identity->ssl_private_key(),
16493 callback.callback());
16494 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16495
16496 // Ensure the certificate was added to the client auth cache
16497 // allowing the connection to continue restarting.
16498 scoped_refptr<X509Certificate> client_cert;
16499 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116500 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916501 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16502 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16503
16504 // Complete the handshake. The request now succeeds.
16505 rv = callback.WaitForResult();
16506 ASSERT_THAT(rv, IsError(OK));
16507 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
16508
16509 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4116510 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916511 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16512 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16513}
16514
bncd16676a2016-07-20 16:23:0116515TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4616516 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916517 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916518 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616519
bnc032658ba2016-09-26 18:17:1516520 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616521
Ryan Hamilton0239aac2018-05-19 00:03:1316522 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916523 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816524 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316525 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716526 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616527 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116528 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616529 };
Ryan Hamilton0239aac2018-05-19 00:03:1316530 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516531 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316532 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116533 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316534 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516535 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316536 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116537 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616538 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116539 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16540 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316541 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616542 };
16543
eroman36d84e54432016-03-17 03:23:0216544 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216545 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116546 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716547 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616548
[email protected]aa22b242011-11-16 18:58:2916549 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616550 HttpRequestInfo request1;
16551 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316552 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616553 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016554 request1.traffic_annotation =
16555 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016556 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616557
tfarina42834112016-09-22 13:38:2016558 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116559 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16560 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616561
16562 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216563 ASSERT_TRUE(response);
16564 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216565 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616566
16567 std::string response_data;
robpercival214763f2016-07-01 23:27:0116568 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616569 EXPECT_EQ("hello!", response_data);
16570
bnca4d611d2016-09-22 19:55:3716571 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316572 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316573 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16574 base::nullopt);
robpercival214763f2016-07-01 23:27:0116575 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616576
16577 HttpRequestInfo request2;
16578 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716579 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616580 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016581 request2.traffic_annotation =
16582 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016583 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616584
tfarina42834112016-09-22 13:38:2016585 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116586 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16587 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616588
16589 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216590 ASSERT_TRUE(response);
16591 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216592 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616593 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216594 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116595 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616596 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616597}
16598
bncd16676a2016-07-20 16:23:0116599TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0216600 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916601 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916602 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0216603
bnc032658ba2016-09-26 18:17:1516604 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0216605
Ryan Hamilton0239aac2018-05-19 00:03:1316606 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916607 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816608 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316609 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716610 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0216611 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116612 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0216613 };
Ryan Hamilton0239aac2018-05-19 00:03:1316614 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516615 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316616 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116617 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316618 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516619 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316620 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116621 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0216622 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116623 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16624 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316625 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0216626 };
16627
eroman36d84e54432016-03-17 03:23:0216628 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216629 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116630 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716631 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0216632
16633 TestCompletionCallback callback;
16634 HttpRequestInfo request1;
16635 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316636 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0216637 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016638 request1.traffic_annotation =
16639 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016640 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216641
tfarina42834112016-09-22 13:38:2016642 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116643 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16644 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216645
16646 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216647 ASSERT_TRUE(response);
16648 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216649 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216650
16651 std::string response_data;
robpercival214763f2016-07-01 23:27:0116652 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216653 EXPECT_EQ("hello!", response_data);
16654
16655 HttpRequestInfo request2;
16656 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716657 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0216658 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016659 request2.traffic_annotation =
16660 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016661 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216662
tfarina42834112016-09-22 13:38:2016663 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116664 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16665 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216666
16667 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216668 ASSERT_TRUE(response);
16669 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216670 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216671 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216672 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116673 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216674 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0216675}
16676
bnc8016c1f2017-03-31 02:11:2916677// Regression test for https://crbug.com/546991.
16678// The server might not be able to serve an IP pooled request, and might send a
16679// 421 Misdirected Request response status to indicate this.
16680// HttpNetworkTransaction should reset the request and retry without IP pooling.
16681TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
16682 // Two hosts resolve to the same IP address.
16683 const std::string ip_addr = "1.2.3.4";
16684 IPAddress ip;
16685 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16686 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16687
Jeremy Roman0579ed62017-08-29 15:56:1916688 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2916689 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16690 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16691
16692 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16693
16694 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316695 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2916696 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16697 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316698 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2916699 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316700 spdy::SpdySerializedFrame rst(
16701 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2916702 MockWrite writes1[] = {
16703 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16704 CreateMockWrite(rst, 6),
16705 };
16706
16707 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316708 spdy::SpdySerializedFrame resp1(
16709 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16710 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16711 spdy::SpdyHeaderBlock response_headers;
16712 response_headers[spdy::kHttp2StatusHeader] = "421";
16713 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2916714 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
16715 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16716 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16717
16718 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116719 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2916720 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16721
16722 AddSSLSocketData();
16723
16724 // Retry the second request on a second connection.
16725 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316726 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2916727 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16728 MockWrite writes2[] = {
16729 CreateMockWrite(req3, 0),
16730 };
16731
Ryan Hamilton0239aac2018-05-19 00:03:1316732 spdy::SpdySerializedFrame resp3(
16733 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
16734 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2916735 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16736 MockRead(ASYNC, 0, 3)};
16737
16738 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116739 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2916740 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16741
16742 AddSSLSocketData();
16743
16744 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316745 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316746 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16747 base::nullopt);
bnc8016c1f2017-03-31 02:11:2916748 EXPECT_THAT(rv, IsOk());
16749
16750 HttpRequestInfo request1;
16751 request1.method = "GET";
16752 request1.url = GURL("https://www.example.org/");
16753 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016754 request1.traffic_annotation =
16755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916756 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16757
Eric Orthf4db66a2019-02-19 21:35:3316758 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2916759 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16760 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16761 rv = callback.WaitForResult();
16762 EXPECT_THAT(rv, IsOk());
16763
16764 const HttpResponseInfo* response = trans1.GetResponseInfo();
16765 ASSERT_TRUE(response);
16766 ASSERT_TRUE(response->headers);
16767 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16768 EXPECT_TRUE(response->was_fetched_via_spdy);
16769 EXPECT_TRUE(response->was_alpn_negotiated);
16770 std::string response_data;
16771 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16772 EXPECT_EQ("hello!", response_data);
16773
16774 HttpRequestInfo request2;
16775 request2.method = "GET";
16776 request2.url = GURL("https://mail.example.org/");
16777 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016778 request2.traffic_annotation =
16779 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916780 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16781
16782 BoundTestNetLog log;
16783 rv = trans2.Start(&request2, callback.callback(), log.bound());
16784 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16785 rv = callback.WaitForResult();
16786 EXPECT_THAT(rv, IsOk());
16787
16788 response = trans2.GetResponseInfo();
16789 ASSERT_TRUE(response);
16790 ASSERT_TRUE(response->headers);
16791 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16792 EXPECT_TRUE(response->was_fetched_via_spdy);
16793 EXPECT_TRUE(response->was_alpn_negotiated);
16794 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16795 EXPECT_EQ("hello!", response_data);
16796
Eric Roman79cc7552019-07-19 02:17:5416797 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5916798 ExpectLogContainsSomewhere(
16799 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2916800 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5916801}
16802
16803// Test that HTTP 421 responses are properly returned to the caller if received
16804// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
16805// portions of the response.
16806TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
16807 // Two hosts resolve to the same IP address.
16808 const std::string ip_addr = "1.2.3.4";
16809 IPAddress ip;
16810 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16811 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16812
Jeremy Roman0579ed62017-08-29 15:56:1916813 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5916814 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16815 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16816
16817 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16818
16819 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316820 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5916821 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16822 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316823 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5916824 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316825 spdy::SpdySerializedFrame rst(
16826 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5916827 MockWrite writes1[] = {
16828 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16829 CreateMockWrite(rst, 6),
16830 };
16831
16832 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316833 spdy::SpdySerializedFrame resp1(
16834 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16835 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16836 spdy::SpdyHeaderBlock response_headers;
16837 response_headers[spdy::kHttp2StatusHeader] = "421";
16838 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5916839 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
16840 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16841 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16842
16843 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116844 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5916845 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16846
16847 AddSSLSocketData();
16848
16849 // Retry the second request on a second connection. It returns 421 Misdirected
16850 // Retry again.
16851 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316852 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5916853 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16854 MockWrite writes2[] = {
16855 CreateMockWrite(req3, 0),
16856 };
16857
Ryan Hamilton0239aac2018-05-19 00:03:1316858 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5916859 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1316860 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5916861 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16862 MockRead(ASYNC, 0, 3)};
16863
16864 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116865 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5916866 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16867
16868 AddSSLSocketData();
16869
16870 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316871 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316872 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16873 base::nullopt);
davidbence688ae2017-05-04 15:12:5916874 EXPECT_THAT(rv, IsOk());
16875
16876 HttpRequestInfo request1;
16877 request1.method = "GET";
16878 request1.url = GURL("https://www.example.org/");
16879 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016880 request1.traffic_annotation =
16881 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916882 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16883
Eric Orthf4db66a2019-02-19 21:35:3316884 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5916885 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16886 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16887 rv = callback.WaitForResult();
16888 EXPECT_THAT(rv, IsOk());
16889
16890 const HttpResponseInfo* response = trans1.GetResponseInfo();
16891 ASSERT_TRUE(response);
16892 ASSERT_TRUE(response->headers);
16893 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16894 EXPECT_TRUE(response->was_fetched_via_spdy);
16895 EXPECT_TRUE(response->was_alpn_negotiated);
16896 std::string response_data;
16897 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16898 EXPECT_EQ("hello!", response_data);
16899
16900 HttpRequestInfo request2;
16901 request2.method = "GET";
16902 request2.url = GURL("https://mail.example.org/");
16903 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016904 request2.traffic_annotation =
16905 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916906 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16907
16908 BoundTestNetLog log;
16909 rv = trans2.Start(&request2, callback.callback(), log.bound());
16910 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16911 rv = callback.WaitForResult();
16912 EXPECT_THAT(rv, IsOk());
16913
16914 // After a retry, the 421 Misdirected Request is reported back up to the
16915 // caller.
16916 response = trans2.GetResponseInfo();
16917 ASSERT_TRUE(response);
16918 ASSERT_TRUE(response->headers);
16919 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
16920 EXPECT_TRUE(response->was_fetched_via_spdy);
16921 EXPECT_TRUE(response->was_alpn_negotiated);
16922 EXPECT_TRUE(response->ssl_info.cert);
16923 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16924 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2916925}
16926
bncd16676a2016-07-20 16:23:0116927TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1316928 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3416929 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
16930 session_deps_.host_resolver =
16931 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0916932 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616933
bnc032658ba2016-09-26 18:17:1516934 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616935
Ryan Hamilton0239aac2018-05-19 00:03:1316936 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916937 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816938 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316939 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716940 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616941 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116942 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616943 };
Ryan Hamilton0239aac2018-05-19 00:03:1316944 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516945 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316946 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116947 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316948 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516949 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316950 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116951 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616952 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116953 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16954 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316955 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616956 };
16957
eroman36d84e54432016-03-17 03:23:0216958 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216959 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116960 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716961 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616962
[email protected]aa22b242011-11-16 18:58:2916963 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616964 HttpRequestInfo request1;
16965 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316966 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616967 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016968 request1.traffic_annotation =
16969 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016970 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616971
tfarina42834112016-09-22 13:38:2016972 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116973 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16974 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616975
16976 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216977 ASSERT_TRUE(response);
16978 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216979 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616980
16981 std::string response_data;
robpercival214763f2016-07-01 23:27:0116982 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616983 EXPECT_EQ("hello!", response_data);
16984
16985 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316986 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316987 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16988 base::nullopt);
robpercival214763f2016-07-01 23:27:0116989 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616990
16991 HttpRequestInfo request2;
16992 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716993 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616994 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016995 request2.traffic_annotation =
16996 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016997 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616998
tfarina42834112016-09-22 13:38:2016999 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117000 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17001 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617002
17003 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217004 ASSERT_TRUE(response);
17005 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217006 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617007 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217008 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117009 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617010 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617011}
17012
bncd16676a2016-07-20 16:23:0117013TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2317014 const std::string https_url = "https://www.example.org:8080/";
17015 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417016
17017 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1317018 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917019 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0417020
17021 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117022 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0417023 };
17024
Raul Tambre94493c652019-03-11 17:18:3517025 spdy::SpdySerializedFrame resp1(
17026 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317027 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117028 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5917029 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0417030
Ryan Sleevib8d7ea02018-05-07 20:01:0117031 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417032 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717033 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417034
17035 // HTTP GET for the HTTP URL
17036 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1317037 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3417038 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2317039 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3417040 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0417041 };
17042
17043 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1317044 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
17045 MockRead(ASYNC, 2, "hello"),
17046 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0417047 };
17048
Ryan Sleevib8d7ea02018-05-07 20:01:0117049 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0417050
[email protected]8450d722012-07-02 19:14:0417051 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617052 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0717053 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17054 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17055 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0417056
danakj1fd259a02016-04-16 03:17:0917057 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0417058
17059 // Start the first transaction to set up the SpdySession
17060 HttpRequestInfo request1;
17061 request1.method = "GET";
17062 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417063 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017064 request1.traffic_annotation =
17065 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017066 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417067 TestCompletionCallback callback1;
17068 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017069 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517070 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417071
robpercival214763f2016-07-01 23:27:0117072 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417073 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17074
17075 // Now, start the HTTP request
17076 HttpRequestInfo request2;
17077 request2.method = "GET";
17078 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417079 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017080 request2.traffic_annotation =
17081 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017082 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417083 TestCompletionCallback callback2;
17084 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017085 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517086 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417087
robpercival214763f2016-07-01 23:27:0117088 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417089 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17090}
17091
bnc5452e2a2015-05-08 16:27:4217092// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
17093// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0117094TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2517095 url::SchemeHostPort server("https", "www.example.org", 443);
17096 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4217097
bnc8bef8da22016-05-30 01:28:2517098 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4217099 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617100 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217101 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17102
17103 // No data should be read from the alternative, because HTTP/1.1 is
17104 // negotiated.
17105 StaticSocketDataProvider data;
17106 session_deps_.socket_factory->AddSocketDataProvider(&data);
17107
17108 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4617109 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4217110 // mocked. This way the request relies on the alternate Job.
17111 StaticSocketDataProvider data_refused;
17112 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17113 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17114
zhongyi3d4a55e72016-04-22 20:36:4617115 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917116 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017117 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217118 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117119 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217120 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117121 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717122 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217123
bnc5452e2a2015-05-08 16:27:4217124 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4617125 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217126 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2517127 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e62018-02-07 07:41:1017128 request.traffic_annotation =
17129 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217130 TestCompletionCallback callback;
17131
17132 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5217133 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2017134 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5217135 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4217136}
17137
bnc40448a532015-05-11 19:13:1417138// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4617139// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1417140// succeeds, the request should succeed, even if the latter fails because
17141// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0117142TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2517143 url::SchemeHostPort server("https", "www.example.org", 443);
17144 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1417145
17146 // Negotiate HTTP/1.1 with alternative.
17147 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617148 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417149 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
17150
17151 // No data should be read from the alternative, because HTTP/1.1 is
17152 // negotiated.
17153 StaticSocketDataProvider data;
17154 session_deps_.socket_factory->AddSocketDataProvider(&data);
17155
zhongyi3d4a55e72016-04-22 20:36:4617156 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1417157 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617158 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417159 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
17160
17161 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2517162 MockWrite("GET / HTTP/1.1\r\n"
17163 "Host: www.example.org\r\n"
17164 "Connection: keep-alive\r\n\r\n"),
17165 MockWrite("GET /second HTTP/1.1\r\n"
17166 "Host: www.example.org\r\n"
17167 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1417168 };
17169
17170 MockRead http_reads[] = {
17171 MockRead("HTTP/1.1 200 OK\r\n"),
17172 MockRead("Content-Type: text/html\r\n"),
17173 MockRead("Content-Length: 6\r\n\r\n"),
17174 MockRead("foobar"),
17175 MockRead("HTTP/1.1 200 OK\r\n"),
17176 MockRead("Content-Type: text/html\r\n"),
17177 MockRead("Content-Length: 7\r\n\r\n"),
17178 MockRead("another"),
17179 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117180 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1417181 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17182
zhongyi3d4a55e72016-04-22 20:36:4617183 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917184 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017185 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1417186 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117187 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217188 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117189 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717190 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1417191
17192 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17193 HttpRequestInfo request1;
17194 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2517195 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1417196 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017197 request1.traffic_annotation =
17198 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417199 TestCompletionCallback callback1;
17200
tfarina42834112016-09-22 13:38:2017201 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417202 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117203 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417204
17205 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217206 ASSERT_TRUE(response1);
17207 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1417208 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
17209
17210 std::string response_data1;
robpercival214763f2016-07-01 23:27:0117211 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1417212 EXPECT_EQ("foobar", response_data1);
17213
17214 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
17215 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0517216 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
17217 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1417218
zhongyi3d4a55e72016-04-22 20:36:4617219 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1417220 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4617221 // to server.
bnc40448a532015-05-11 19:13:1417222 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17223 HttpRequestInfo request2;
17224 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2517225 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1417226 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017227 request2.traffic_annotation =
17228 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417229 TestCompletionCallback callback2;
17230
tfarina42834112016-09-22 13:38:2017231 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417232 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117233 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417234
17235 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217236 ASSERT_TRUE(response2);
17237 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1417238 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
17239
17240 std::string response_data2;
robpercival214763f2016-07-01 23:27:0117241 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1417242 EXPECT_EQ("another", response_data2);
17243}
17244
bnc5452e2a2015-05-08 16:27:4217245// Alternative service requires HTTP/2 (or SPDY), but there is already a
17246// HTTP/1.1 socket open to the alternative server. That socket should not be
17247// used.
bncd16676a2016-07-20 16:23:0117248TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4617249 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4217250 HostPortPair alternative("alternative.example.org", 443);
17251 std::string origin_url = "https://origin.example.org:443";
17252 std::string alternative_url = "https://alternative.example.org:443";
17253
17254 // Negotiate HTTP/1.1 with alternative.example.org.
17255 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617256 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217257 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17258
17259 // HTTP/1.1 data for |request1| and |request2|.
17260 MockWrite http_writes[] = {
17261 MockWrite(
17262 "GET / HTTP/1.1\r\n"
17263 "Host: alternative.example.org\r\n"
17264 "Connection: keep-alive\r\n\r\n"),
17265 MockWrite(
17266 "GET / HTTP/1.1\r\n"
17267 "Host: alternative.example.org\r\n"
17268 "Connection: keep-alive\r\n\r\n"),
17269 };
17270
17271 MockRead http_reads[] = {
17272 MockRead(
17273 "HTTP/1.1 200 OK\r\n"
17274 "Content-Type: text/html; charset=iso-8859-1\r\n"
17275 "Content-Length: 40\r\n\r\n"
17276 "first HTTP/1.1 response from alternative"),
17277 MockRead(
17278 "HTTP/1.1 200 OK\r\n"
17279 "Content-Type: text/html; charset=iso-8859-1\r\n"
17280 "Content-Length: 41\r\n\r\n"
17281 "second HTTP/1.1 response from alternative"),
17282 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117283 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4217284 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17285
17286 // This test documents that an alternate Job should not pool to an already
17287 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4617288 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4217289 StaticSocketDataProvider data_refused;
17290 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17291 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17292
zhongyi3d4a55e72016-04-22 20:36:4617293 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917294 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017295 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217296 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117297 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217298 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117299 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717300 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217301
17302 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4217303 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4617304 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217305 request1.method = "GET";
17306 request1.url = GURL(alternative_url);
17307 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017308 request1.traffic_annotation =
17309 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217310 TestCompletionCallback callback1;
17311
tfarina42834112016-09-22 13:38:2017312 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117313 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617314 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217315 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5217316 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4217317 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217318 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217319 EXPECT_FALSE(response1->was_fetched_via_spdy);
17320 std::string response_data1;
bnc691fda62016-08-12 00:43:1617321 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4217322 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
17323
17324 // Request for origin.example.org, which has an alternative service. This
17325 // will start two Jobs: the alternative looks for connections to pool to,
17326 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4617327 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4217328 // this request fails.
bnc5452e2a2015-05-08 16:27:4217329 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4617330 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217331 request2.method = "GET";
17332 request2.url = GURL(origin_url);
17333 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017334 request2.traffic_annotation =
17335 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217336 TestCompletionCallback callback2;
17337
tfarina42834112016-09-22 13:38:2017338 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117339 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4217340
17341 // Another transaction to alternative. This is to test that the HTTP/1.1
17342 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4217343 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4617344 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217345 request3.method = "GET";
17346 request3.url = GURL(alternative_url);
17347 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017348 request3.traffic_annotation =
17349 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217350 TestCompletionCallback callback3;
17351
tfarina42834112016-09-22 13:38:2017352 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117353 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617354 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217355 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5217356 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4217357 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217358 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217359 EXPECT_FALSE(response3->was_fetched_via_spdy);
17360 std::string response_data3;
bnc691fda62016-08-12 00:43:1617361 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4217362 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
17363}
17364
bncd16676a2016-07-20 16:23:0117365TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2317366 const std::string https_url = "https://www.example.org:8080/";
17367 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417368
rdsmithebb50aa2015-11-12 03:44:3817369 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0117370 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3817371
[email protected]8450d722012-07-02 19:14:0417372 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2317373 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0417374 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
17375 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
17376 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1317377 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917378 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317379 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0217380 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3917381
17382 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1317383 spdy::SpdyHeaderBlock req2_block;
17384 req2_block[spdy::kHttp2MethodHeader] = "GET";
17385 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
17386 req2_block[spdy::kHttp2SchemeHeader] = "http";
17387 req2_block[spdy::kHttp2PathHeader] = "/";
17388 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1517389 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0417390
17391 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117392 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
17393 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0417394 };
17395
Ryan Hamilton0239aac2018-05-19 00:03:1317396 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1517397 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317398 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1517399 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317400 spdy::SpdySerializedFrame body1(
17401 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
17402 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3817403 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317404 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3817405 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3517406 spdy::SpdySerializedFrame resp2(
17407 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317408 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3317409 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117410 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3317411 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4117412 CreateMockRead(wrapped_resp1, 4),
17413 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3317414 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4117415 CreateMockRead(resp2, 8),
17416 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3317417 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
17418 };
[email protected]8450d722012-07-02 19:14:0417419
Ryan Sleevib8d7ea02018-05-07 20:01:0117420 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417421 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717422 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417423
Lily Houghton8c2f97d2018-01-22 05:06:5917424 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917425 ProxyResolutionService::CreateFixedFromPacResult(
17426 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5117427 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0717428 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0417429 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617430 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317431 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0417432 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617433 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17435 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0417436
danakj1fd259a02016-04-16 03:17:0917437 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0417438
17439 // Start the first transaction to set up the SpdySession
17440 HttpRequestInfo request1;
17441 request1.method = "GET";
17442 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417443 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017444 request1.traffic_annotation =
17445 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017446 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417447 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2017448 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417449
mmenke666a6fea2015-12-19 04:16:3317450 // This pause is a hack to avoid running into https://crbug.com/497228.
17451 data1.RunUntilPaused();
17452 base::RunLoop().RunUntilIdle();
17453 data1.Resume();
robpercival214763f2016-07-01 23:27:0117454 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0417455 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17456
[email protected]f6c63db52013-02-02 00:35:2217457 LoadTimingInfo load_timing_info1;
17458 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
17459 TestLoadTimingNotReusedWithPac(load_timing_info1,
17460 CONNECT_TIMING_HAS_SSL_TIMES);
17461
mmenke666a6fea2015-12-19 04:16:3317462 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0417463 HttpRequestInfo request2;
17464 request2.method = "GET";
17465 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417466 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017467 request2.traffic_annotation =
17468 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017469 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417470 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2017471 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417472
mmenke666a6fea2015-12-19 04:16:3317473 // This pause is a hack to avoid running into https://crbug.com/497228.
17474 data1.RunUntilPaused();
17475 base::RunLoop().RunUntilIdle();
17476 data1.Resume();
robpercival214763f2016-07-01 23:27:0117477 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3317478
[email protected]8450d722012-07-02 19:14:0417479 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2217480
17481 LoadTimingInfo load_timing_info2;
17482 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
17483 // The established SPDY sessions is considered reused by the HTTP request.
17484 TestLoadTimingReusedWithPac(load_timing_info2);
17485 // HTTP requests over a SPDY session should have a different connection
17486 // socket_log_id than requests over a tunnel.
17487 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0417488}
17489
[email protected]2d88e7d2012-07-19 17:55:1717490// Test that in the case where we have a SPDY session to a SPDY proxy
17491// that we do not pool other origins that resolve to the same IP when
17492// the certificate does not match the new origin.
17493// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0117494TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2317495 const std::string url1 = "http://www.example.org/";
17496 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1717497 const std::string ip_addr = "1.2.3.4";
17498
rdsmithebb50aa2015-11-12 03:44:3817499 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0117500 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3817501
[email protected]2d88e7d2012-07-19 17:55:1717502 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1317503 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2317504 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1317505 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1517506 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1717507
17508 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117509 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1717510 };
17511
Raul Tambre94493c652019-03-11 17:18:3517512 spdy::SpdySerializedFrame resp1(
17513 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317514 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1717515 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117516 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
17517 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1717518 };
17519
Ryan Sleevib8d7ea02018-05-07 20:01:0117520 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3217521 IPAddress ip;
martijn654c8c42016-02-10 22:10:5917522 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1717523 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17524 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3317525 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1717526
17527 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1317528 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917529 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1717530
17531 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117532 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1717533 };
17534
Ryan Hamilton0239aac2018-05-19 00:03:1317535 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3517536 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317537 spdy::SpdySerializedFrame body2(
17538 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117539 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3317540 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1717541
Ryan Sleevib8d7ea02018-05-07 20:01:0117542 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1717543 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3317544 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1717545
17546 // Set up a proxy config that sends HTTP requests to a proxy, and
17547 // all others direct.
17548 ProxyConfig proxy_config;
17549 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4917550 session_deps_.proxy_resolution_service =
17551 std::make_unique<ProxyResolutionService>(
17552 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
17553 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
17554 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1717555
bncce36dca22015-04-21 22:11:2317556 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617557 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1717558 // Load a valid cert. Note, that this does not need to
17559 // be valid for proxy because the MockSSLClientSocket does
17560 // not actually verify it. But SpdySession will use this
17561 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4917562 ssl1.ssl_info.cert =
17563 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
17564 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3317565 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17566 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1717567
17568 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617569 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317570 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17571 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1717572
Jeremy Roman0579ed62017-08-29 15:56:1917573 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2317574 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0717575 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1717576
danakj1fd259a02016-04-16 03:17:0917577 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1717578
17579 // Start the first transaction to set up the SpdySession
17580 HttpRequestInfo request1;
17581 request1.method = "GET";
17582 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1717583 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017584 request1.traffic_annotation =
17585 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017586 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717587 TestCompletionCallback callback1;
17588 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017589 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3317590 // This pause is a hack to avoid running into https://crbug.com/497228.
17591 data1.RunUntilPaused();
17592 base::RunLoop().RunUntilIdle();
17593 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1717594
robpercival214763f2016-07-01 23:27:0117595 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717596 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17597
17598 // Now, start the HTTP request
17599 HttpRequestInfo request2;
17600 request2.method = "GET";
17601 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1717602 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017603 request2.traffic_annotation =
17604 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017605 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717606 TestCompletionCallback callback2;
17607 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017608 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517609 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1717610
17611 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0117612 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717613 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17614}
17615
[email protected]85f97342013-04-17 06:12:2417616// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
17617// error) in SPDY session, removes the socket from pool and closes the SPDY
17618// session. Verify that new url's from the same HttpNetworkSession (and a new
17619// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0117620TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2317621 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2417622
17623 MockRead reads1[] = {
17624 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
17625 };
17626
Ryan Sleevib8d7ea02018-05-07 20:01:0117627 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2417628
Ryan Hamilton0239aac2018-05-19 00:03:1317629 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917630 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2417631 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117632 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2417633 };
17634
Raul Tambre94493c652019-03-11 17:18:3517635 spdy::SpdySerializedFrame resp2(
17636 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317637 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2417638 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4117639 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
17640 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2417641 };
17642
Ryan Sleevib8d7ea02018-05-07 20:01:0117643 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2417644
[email protected]85f97342013-04-17 06:12:2417645 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617646 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017647 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17648 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2417649
17650 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617651 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017652 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17653 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2417654
danakj1fd259a02016-04-16 03:17:0917655 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5017656 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2417657
17658 // Start the first transaction to set up the SpdySession and verify that
17659 // connection was closed.
17660 HttpRequestInfo request1;
17661 request1.method = "GET";
17662 request1.url = GURL(https_url);
17663 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017664 request1.traffic_annotation =
17665 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017666 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417667 TestCompletionCallback callback1;
17668 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017669 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0117670 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2417671
17672 // Now, start the second request and make sure it succeeds.
17673 HttpRequestInfo request2;
17674 request2.method = "GET";
17675 request2.url = GURL(https_url);
17676 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017677 request2.traffic_annotation =
17678 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017679 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417680 TestCompletionCallback callback2;
17681 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017682 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2417683
robpercival214763f2016-07-01 23:27:0117684 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2417685 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17686}
17687
bncd16676a2016-07-20 16:23:0117688TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0317689 ClientSocketPoolManager::set_max_sockets_per_group(
17690 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17691 ClientSocketPoolManager::set_max_sockets_per_pool(
17692 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17693
17694 // Use two different hosts with different IPs so they don't get pooled.
17695 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
17696 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0917697 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0317698
17699 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617700 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317701 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617702 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317703 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17704 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17705
Ryan Hamilton0239aac2018-05-19 00:03:1317706 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917707 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317708 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117709 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0317710 };
Ryan Hamilton0239aac2018-05-19 00:03:1317711 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517712 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317713 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117714 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317715 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117716 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917717 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317718 };
17719
rdsmithebb50aa2015-11-12 03:44:3817720 // Use a separate test instance for the separate SpdySession that will be
17721 // created.
bncd16676a2016-07-20 16:23:0117722 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0117723 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1217724 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0317725
Ryan Hamilton0239aac2018-05-19 00:03:1317726 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4917727 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317728 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117729 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0317730 };
Ryan Hamilton0239aac2018-05-19 00:03:1317731 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517732 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317733 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117734 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317735 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117736 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917737 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317738 };
17739
Ryan Sleevib8d7ea02018-05-07 20:01:0117740 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1217741 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0317742
17743 MockWrite http_write[] = {
17744 MockWrite("GET / HTTP/1.1\r\n"
17745 "Host: www.a.com\r\n"
17746 "Connection: keep-alive\r\n\r\n"),
17747 };
17748
17749 MockRead http_read[] = {
17750 MockRead("HTTP/1.1 200 OK\r\n"),
17751 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
17752 MockRead("Content-Length: 6\r\n\r\n"),
17753 MockRead("hello!"),
17754 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117755 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0317756 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17757
17758 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117759 SpdySessionKey spdy_session_key_a(
17760 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417761 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17762 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317763 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617764 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317765
17766 TestCompletionCallback callback;
17767 HttpRequestInfo request1;
17768 request1.method = "GET";
17769 request1.url = GURL("https://www.a.com/");
17770 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017771 request1.traffic_annotation =
17772 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817773 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917774 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317775
tfarina42834112016-09-22 13:38:2017776 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117777 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17778 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317779
17780 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217781 ASSERT_TRUE(response);
17782 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217783 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317784 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217785 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0317786
17787 std::string response_data;
robpercival214763f2016-07-01 23:27:0117788 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317789 EXPECT_EQ("hello!", response_data);
17790 trans.reset();
17791 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617792 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317793
17794 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117795 SpdySessionKey spdy_session_key_b(
17796 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417797 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17798 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317799 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617800 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317801 HttpRequestInfo request2;
17802 request2.method = "GET";
17803 request2.url = GURL("https://www.b.com/");
17804 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017805 request2.traffic_annotation =
17806 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817807 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917808 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317809
tfarina42834112016-09-22 13:38:2017810 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117811 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17812 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317813
17814 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217815 ASSERT_TRUE(response);
17816 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217817 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317818 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217819 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117820 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317821 EXPECT_EQ("hello!", response_data);
17822 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617823 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317824 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617825 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317826
17827 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1117828 SpdySessionKey spdy_session_key_a1(
17829 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417830 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17831 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317832 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617833 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0317834 HttpRequestInfo request3;
17835 request3.method = "GET";
17836 request3.url = GURL("http://www.a.com/");
17837 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017838 request3.traffic_annotation =
17839 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817840 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917841 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317842
tfarina42834112016-09-22 13:38:2017843 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117844 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17845 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317846
17847 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217848 ASSERT_TRUE(response);
17849 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0317850 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17851 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217852 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117853 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317854 EXPECT_EQ("hello!", response_data);
17855 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617856 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317857 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617858 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317859}
17860
bncd16676a2016-07-20 16:23:0117861TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417862 HttpRequestInfo request;
17863 request.method = "GET";
bncce36dca22015-04-21 22:11:2317864 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017865 request.traffic_annotation =
17866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417867
danakj1fd259a02016-04-16 03:17:0917868 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617869 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417870
ttuttled9dbc652015-09-29 20:00:5917871 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417872 StaticSocketDataProvider data;
17873 data.set_connect_data(mock_connect);
17874 session_deps_.socket_factory->AddSocketDataProvider(&data);
17875
17876 TestCompletionCallback callback;
17877
tfarina42834112016-09-22 13:38:2017878 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117879 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417880
17881 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117882 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417883
ttuttle1f2d7e92015-04-28 16:17:4717884 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617885 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717886 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117887 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917888
17889 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617890 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917891 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417892}
17893
bncd16676a2016-07-20 16:23:0117894TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417895 HttpRequestInfo request;
17896 request.method = "GET";
bncce36dca22015-04-21 22:11:2317897 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017898 request.traffic_annotation =
17899 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417900
danakj1fd259a02016-04-16 03:17:0917901 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617902 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417903
ttuttled9dbc652015-09-29 20:00:5917904 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417905 StaticSocketDataProvider data;
17906 data.set_connect_data(mock_connect);
17907 session_deps_.socket_factory->AddSocketDataProvider(&data);
17908
17909 TestCompletionCallback callback;
17910
tfarina42834112016-09-22 13:38:2017911 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117912 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417913
17914 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117915 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417916
ttuttle1f2d7e92015-04-28 16:17:4717917 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617918 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717919 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117920 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917921
17922 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617923 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917924 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417925}
17926
bncd16676a2016-07-20 16:23:0117927TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417928 HttpRequestInfo request;
17929 request.method = "GET";
bncce36dca22015-04-21 22:11:2317930 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017931 request.traffic_annotation =
17932 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417933
danakj1fd259a02016-04-16 03:17:0917934 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617935 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417936
17937 MockWrite data_writes[] = {
17938 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17939 };
17940 MockRead data_reads[] = {
17941 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17942 };
17943
Ryan Sleevib8d7ea02018-05-07 20:01:0117944 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417945 session_deps_.socket_factory->AddSocketDataProvider(&data);
17946
17947 TestCompletionCallback callback;
17948
tfarina42834112016-09-22 13:38:2017949 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117950 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417951
17952 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117953 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417954}
17955
bncd16676a2016-07-20 16:23:0117956TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417957 HttpRequestInfo request;
17958 request.method = "GET";
bncce36dca22015-04-21 22:11:2317959 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017960 request.traffic_annotation =
17961 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417962
danakj1fd259a02016-04-16 03:17:0917963 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617964 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417965
17966 MockWrite data_writes[] = {
17967 MockWrite(ASYNC, ERR_CONNECTION_RESET),
17968 };
17969 MockRead data_reads[] = {
17970 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17971 };
17972
Ryan Sleevib8d7ea02018-05-07 20:01:0117973 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417974 session_deps_.socket_factory->AddSocketDataProvider(&data);
17975
17976 TestCompletionCallback callback;
17977
tfarina42834112016-09-22 13:38:2017978 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417980
17981 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117982 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417983}
17984
bncd16676a2016-07-20 16:23:0117985TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417986 HttpRequestInfo request;
17987 request.method = "GET";
bncce36dca22015-04-21 22:11:2317988 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017989 request.traffic_annotation =
17990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417991
danakj1fd259a02016-04-16 03:17:0917992 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617993 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417994
17995 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317996 MockWrite(
17997 "GET / HTTP/1.1\r\n"
17998 "Host: www.example.org\r\n"
17999 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418000 };
18001 MockRead data_reads[] = {
18002 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
18003 };
18004
Ryan Sleevib8d7ea02018-05-07 20:01:0118005 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418006 session_deps_.socket_factory->AddSocketDataProvider(&data);
18007
18008 TestCompletionCallback callback;
18009
tfarina42834112016-09-22 13:38:2018010 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118011 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418012
18013 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118014 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418015}
18016
bncd16676a2016-07-20 16:23:0118017TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418018 HttpRequestInfo request;
18019 request.method = "GET";
bncce36dca22015-04-21 22:11:2318020 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018021 request.traffic_annotation =
18022 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418023
danakj1fd259a02016-04-16 03:17:0918024 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618025 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418026
18027 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318028 MockWrite(
18029 "GET / HTTP/1.1\r\n"
18030 "Host: www.example.org\r\n"
18031 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418032 };
18033 MockRead data_reads[] = {
18034 MockRead(ASYNC, ERR_CONNECTION_RESET),
18035 };
18036
Ryan Sleevib8d7ea02018-05-07 20:01:0118037 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418038 session_deps_.socket_factory->AddSocketDataProvider(&data);
18039
18040 TestCompletionCallback callback;
18041
tfarina42834112016-09-22 13:38:2018042 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118043 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418044
18045 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118046 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418047}
18048
[email protected]043b68c82013-08-22 23:41:5218049// Tests that when a used socket is returned to the SSL socket pool, it's closed
18050// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118051TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5218052 ClientSocketPoolManager::set_max_sockets_per_group(
18053 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18054 ClientSocketPoolManager::set_max_sockets_per_pool(
18055 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18056
18057 // Set up SSL request.
18058
18059 HttpRequestInfo ssl_request;
18060 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2318061 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018062 ssl_request.traffic_annotation =
18063 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218064
18065 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2318066 MockWrite(
18067 "GET / HTTP/1.1\r\n"
18068 "Host: www.example.org\r\n"
18069 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218070 };
18071 MockRead ssl_reads[] = {
18072 MockRead("HTTP/1.1 200 OK\r\n"),
18073 MockRead("Content-Length: 11\r\n\r\n"),
18074 MockRead("hello world"),
18075 MockRead(SYNCHRONOUS, OK),
18076 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118077 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5218078 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18079
18080 SSLSocketDataProvider ssl(ASYNC, OK);
18081 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18082
18083 // Set up HTTP request.
18084
18085 HttpRequestInfo http_request;
18086 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318087 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018088 http_request.traffic_annotation =
18089 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218090
18091 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318092 MockWrite(
18093 "GET / HTTP/1.1\r\n"
18094 "Host: www.example.org\r\n"
18095 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218096 };
18097 MockRead http_reads[] = {
18098 MockRead("HTTP/1.1 200 OK\r\n"),
18099 MockRead("Content-Length: 7\r\n\r\n"),
18100 MockRead("falafel"),
18101 MockRead(SYNCHRONOUS, OK),
18102 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118103 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218104 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18105
danakj1fd259a02016-04-16 03:17:0918106 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218107
18108 // Start the SSL request.
18109 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1618110 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018111 ASSERT_EQ(ERR_IO_PENDING,
18112 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
18113 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5218114
18115 // Start the HTTP request. Pool should stall.
18116 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618117 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018118 ASSERT_EQ(ERR_IO_PENDING,
18119 http_trans.Start(&http_request, http_callback.callback(),
18120 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118121 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218122
18123 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0118124 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218125 std::string response_data;
bnc691fda62016-08-12 00:43:1618126 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218127 EXPECT_EQ("hello world", response_data);
18128
18129 // The SSL socket should automatically be closed, so the HTTP request can
18130 // start.
Matt Menke9d5e2c92019-02-05 01:42:2318131 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4118132 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218133
18134 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0118135 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1618136 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218137 EXPECT_EQ("falafel", response_data);
18138
dcheng48459ac22014-08-26 00:46:4118139 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218140}
18141
18142// Tests that when a SSL connection is established but there's no corresponding
18143// request that needs it, the new socket is closed if the transport socket pool
18144// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118145TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5218146 ClientSocketPoolManager::set_max_sockets_per_group(
18147 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18148 ClientSocketPoolManager::set_max_sockets_per_pool(
18149 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18150
18151 // Set up an ssl request.
18152
18153 HttpRequestInfo ssl_request;
18154 ssl_request.method = "GET";
18155 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1018156 ssl_request.traffic_annotation =
18157 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218158
18159 // No data will be sent on the SSL socket.
18160 StaticSocketDataProvider ssl_data;
18161 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18162
18163 SSLSocketDataProvider ssl(ASYNC, OK);
18164 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18165
18166 // Set up HTTP request.
18167
18168 HttpRequestInfo http_request;
18169 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318170 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018171 http_request.traffic_annotation =
18172 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218173
18174 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318175 MockWrite(
18176 "GET / HTTP/1.1\r\n"
18177 "Host: www.example.org\r\n"
18178 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218179 };
18180 MockRead http_reads[] = {
18181 MockRead("HTTP/1.1 200 OK\r\n"),
18182 MockRead("Content-Length: 7\r\n\r\n"),
18183 MockRead("falafel"),
18184 MockRead(SYNCHRONOUS, OK),
18185 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118186 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218187 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18188
danakj1fd259a02016-04-16 03:17:0918189 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218190
18191 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
18192 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2918193 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5918194 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2318195 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218196
18197 // Start the HTTP request. Pool should stall.
18198 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618199 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018200 ASSERT_EQ(ERR_IO_PENDING,
18201 http_trans.Start(&http_request, http_callback.callback(),
18202 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118203 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218204
18205 // The SSL connection will automatically be closed once the connection is
18206 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0118207 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218208 std::string response_data;
bnc691fda62016-08-12 00:43:1618209 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218210 EXPECT_EQ("falafel", response_data);
18211
dcheng48459ac22014-08-26 00:46:4118212 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218213}
18214
bncd16676a2016-07-20 16:23:0118215TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918216 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218217 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918218 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218219 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418220
18221 HttpRequestInfo request;
18222 request.method = "POST";
18223 request.url = GURL("http://www.foo.com/");
18224 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018225 request.traffic_annotation =
18226 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418227
danakj1fd259a02016-04-16 03:17:0918228 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618229 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418230 // Send headers successfully, but get an error while sending the body.
18231 MockWrite data_writes[] = {
18232 MockWrite("POST / HTTP/1.1\r\n"
18233 "Host: www.foo.com\r\n"
18234 "Connection: keep-alive\r\n"
18235 "Content-Length: 3\r\n\r\n"),
18236 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18237 };
18238
18239 MockRead data_reads[] = {
18240 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18241 MockRead("hello world"),
18242 MockRead(SYNCHRONOUS, OK),
18243 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118244 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418245 session_deps_.socket_factory->AddSocketDataProvider(&data);
18246
18247 TestCompletionCallback callback;
18248
tfarina42834112016-09-22 13:38:2018249 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118250 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418251
18252 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118253 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418254
bnc691fda62016-08-12 00:43:1618255 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218256 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418257
wezca1070932016-05-26 20:30:5218258 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418259 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18260
18261 std::string response_data;
bnc691fda62016-08-12 00:43:1618262 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118263 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418264 EXPECT_EQ("hello world", response_data);
18265}
18266
18267// This test makes sure the retry logic doesn't trigger when reading an error
18268// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0118269TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418270 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0918271 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5418272 MockWrite data_writes[] = {
18273 MockWrite("GET / HTTP/1.1\r\n"
18274 "Host: www.foo.com\r\n"
18275 "Connection: keep-alive\r\n\r\n"),
18276 MockWrite("POST / HTTP/1.1\r\n"
18277 "Host: www.foo.com\r\n"
18278 "Connection: keep-alive\r\n"
18279 "Content-Length: 3\r\n\r\n"),
18280 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18281 };
18282
18283 MockRead data_reads[] = {
18284 MockRead("HTTP/1.1 200 Peachy\r\n"
18285 "Content-Length: 14\r\n\r\n"),
18286 MockRead("first response"),
18287 MockRead("HTTP/1.1 400 Not OK\r\n"
18288 "Content-Length: 15\r\n\r\n"),
18289 MockRead("second response"),
18290 MockRead(SYNCHRONOUS, OK),
18291 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118292 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418293 session_deps_.socket_factory->AddSocketDataProvider(&data);
18294
18295 TestCompletionCallback callback;
18296 HttpRequestInfo request1;
18297 request1.method = "GET";
18298 request1.url = GURL("http://www.foo.com/");
18299 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018300 request1.traffic_annotation =
18301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418302
bnc87dcefc2017-05-25 12:47:5818303 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1918304 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018305 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118306 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418307
18308 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118309 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418310
18311 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5218312 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5418313
wezca1070932016-05-26 20:30:5218314 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5418315 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
18316
18317 std::string response_data1;
18318 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0118319 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418320 EXPECT_EQ("first response", response_data1);
18321 // Delete the transaction to release the socket back into the socket pool.
18322 trans1.reset();
18323
danakj1fd259a02016-04-16 03:17:0918324 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218325 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918326 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218327 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418328
18329 HttpRequestInfo request2;
18330 request2.method = "POST";
18331 request2.url = GURL("http://www.foo.com/");
18332 request2.upload_data_stream = &upload_data_stream;
18333 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018334 request2.traffic_annotation =
18335 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418336
bnc691fda62016-08-12 00:43:1618337 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018338 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118339 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418340
18341 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118342 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418343
bnc691fda62016-08-12 00:43:1618344 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5218345 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5418346
wezca1070932016-05-26 20:30:5218347 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5418348 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
18349
18350 std::string response_data2;
bnc691fda62016-08-12 00:43:1618351 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0118352 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418353 EXPECT_EQ("second response", response_data2);
18354}
18355
bncd16676a2016-07-20 16:23:0118356TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418357 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0918358 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218359 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918360 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218361 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418362
18363 HttpRequestInfo request;
18364 request.method = "POST";
18365 request.url = GURL("http://www.foo.com/");
18366 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018367 request.traffic_annotation =
18368 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418369
danakj1fd259a02016-04-16 03:17:0918370 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618371 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418372 // Send headers successfully, but get an error while sending the body.
18373 MockWrite data_writes[] = {
18374 MockWrite("POST / HTTP/1.1\r\n"
18375 "Host: www.foo.com\r\n"
18376 "Connection: keep-alive\r\n"
18377 "Content-Length: 3\r\n\r\n"
18378 "fo"),
18379 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18380 };
18381
18382 MockRead data_reads[] = {
18383 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18384 MockRead("hello world"),
18385 MockRead(SYNCHRONOUS, OK),
18386 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118387 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418388 session_deps_.socket_factory->AddSocketDataProvider(&data);
18389
18390 TestCompletionCallback callback;
18391
tfarina42834112016-09-22 13:38:2018392 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118393 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418394
18395 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118396 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418397
bnc691fda62016-08-12 00:43:1618398 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218399 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418400
wezca1070932016-05-26 20:30:5218401 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418402 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18403
18404 std::string response_data;
bnc691fda62016-08-12 00:43:1618405 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118406 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418407 EXPECT_EQ("hello world", response_data);
18408}
18409
18410// This tests the more common case than the previous test, where headers and
18411// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0118412TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0718413 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5418414
18415 HttpRequestInfo request;
18416 request.method = "POST";
18417 request.url = GURL("http://www.foo.com/");
18418 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018419 request.traffic_annotation =
18420 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418421
danakj1fd259a02016-04-16 03:17:0918422 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618423 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418424 // Send headers successfully, but get an error while sending the body.
18425 MockWrite data_writes[] = {
18426 MockWrite("POST / HTTP/1.1\r\n"
18427 "Host: www.foo.com\r\n"
18428 "Connection: keep-alive\r\n"
18429 "Transfer-Encoding: chunked\r\n\r\n"),
18430 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18431 };
18432
18433 MockRead data_reads[] = {
18434 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18435 MockRead("hello world"),
18436 MockRead(SYNCHRONOUS, OK),
18437 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118438 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418439 session_deps_.socket_factory->AddSocketDataProvider(&data);
18440
18441 TestCompletionCallback callback;
18442
tfarina42834112016-09-22 13:38:2018443 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118444 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418445 // Make sure the headers are sent before adding a chunk. This ensures that
18446 // they can't be merged with the body in a single send. Not currently
18447 // necessary since a chunked body is never merged with headers, but this makes
18448 // the test more future proof.
18449 base::RunLoop().RunUntilIdle();
18450
mmenkecbc2b712014-10-09 20:29:0718451 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5418452
18453 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118454 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418455
bnc691fda62016-08-12 00:43:1618456 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218457 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418458
wezca1070932016-05-26 20:30:5218459 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418460 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18461
18462 std::string response_data;
bnc691fda62016-08-12 00:43:1618463 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118464 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418465 EXPECT_EQ("hello world", response_data);
18466}
18467
bncd16676a2016-07-20 16:23:0118468TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918469 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218470 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918471 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218472 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418473
18474 HttpRequestInfo request;
18475 request.method = "POST";
18476 request.url = GURL("http://www.foo.com/");
18477 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018478 request.traffic_annotation =
18479 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418480
danakj1fd259a02016-04-16 03:17:0918481 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618482 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418483
18484 MockWrite data_writes[] = {
18485 MockWrite("POST / HTTP/1.1\r\n"
18486 "Host: www.foo.com\r\n"
18487 "Connection: keep-alive\r\n"
18488 "Content-Length: 3\r\n\r\n"),
18489 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18490 };
18491
18492 MockRead data_reads[] = {
18493 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18494 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18495 MockRead("hello world"),
18496 MockRead(SYNCHRONOUS, OK),
18497 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118498 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418499 session_deps_.socket_factory->AddSocketDataProvider(&data);
18500
18501 TestCompletionCallback callback;
18502
tfarina42834112016-09-22 13:38:2018503 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118504 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418505
18506 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118507 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418508
bnc691fda62016-08-12 00:43:1618509 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218510 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418511
wezca1070932016-05-26 20:30:5218512 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418513 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18514
18515 std::string response_data;
bnc691fda62016-08-12 00:43:1618516 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118517 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418518 EXPECT_EQ("hello world", response_data);
18519}
18520
bncd16676a2016-07-20 16:23:0118521TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918522 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218523 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918524 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218525 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418526
18527 HttpRequestInfo request;
18528 request.method = "POST";
18529 request.url = GURL("http://www.foo.com/");
18530 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018531 request.traffic_annotation =
18532 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418533
danakj1fd259a02016-04-16 03:17:0918534 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618535 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418536 // Send headers successfully, but get an error while sending the body.
18537 MockWrite data_writes[] = {
18538 MockWrite("POST / HTTP/1.1\r\n"
18539 "Host: www.foo.com\r\n"
18540 "Connection: keep-alive\r\n"
18541 "Content-Length: 3\r\n\r\n"),
18542 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18543 };
18544
18545 MockRead data_reads[] = {
18546 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
18547 MockRead("hello world"),
18548 MockRead(SYNCHRONOUS, OK),
18549 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118550 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418551 session_deps_.socket_factory->AddSocketDataProvider(&data);
18552
18553 TestCompletionCallback callback;
18554
tfarina42834112016-09-22 13:38:2018555 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118556 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418557
18558 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118559 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418560}
18561
bncd16676a2016-07-20 16:23:0118562TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418563 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918564 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218565 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918566 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218567 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418568
18569 HttpRequestInfo request;
18570 request.method = "POST";
18571 request.url = GURL("http://www.foo.com/");
18572 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018573 request.traffic_annotation =
18574 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418575
danakj1fd259a02016-04-16 03:17:0918576 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618577 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418578 // Send headers successfully, but get an error while sending the body.
18579 MockWrite data_writes[] = {
18580 MockWrite("POST / HTTP/1.1\r\n"
18581 "Host: www.foo.com\r\n"
18582 "Connection: keep-alive\r\n"
18583 "Content-Length: 3\r\n\r\n"),
18584 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18585 };
18586
18587 MockRead data_reads[] = {
18588 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18589 MockRead("HTTP/1.0 302 Redirect\r\n"),
18590 MockRead("Location: http://somewhere-else.com/\r\n"),
18591 MockRead("Content-Length: 0\r\n\r\n"),
18592 MockRead(SYNCHRONOUS, OK),
18593 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118594 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418595 session_deps_.socket_factory->AddSocketDataProvider(&data);
18596
18597 TestCompletionCallback callback;
18598
tfarina42834112016-09-22 13:38:2018599 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118600 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418601
18602 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118603 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418604}
18605
bncd16676a2016-07-20 16:23:0118606TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918607 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218608 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918609 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218610 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418611
18612 HttpRequestInfo request;
18613 request.method = "POST";
18614 request.url = GURL("http://www.foo.com/");
18615 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018616 request.traffic_annotation =
18617 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418618
danakj1fd259a02016-04-16 03:17:0918619 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618620 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418621 // Send headers successfully, but get an error while sending the body.
18622 MockWrite data_writes[] = {
18623 MockWrite("POST / HTTP/1.1\r\n"
18624 "Host: www.foo.com\r\n"
18625 "Connection: keep-alive\r\n"
18626 "Content-Length: 3\r\n\r\n"),
18627 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18628 };
18629
18630 MockRead data_reads[] = {
18631 MockRead("HTTP 0.9 rocks!"),
18632 MockRead(SYNCHRONOUS, OK),
18633 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118634 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418635 session_deps_.socket_factory->AddSocketDataProvider(&data);
18636
18637 TestCompletionCallback callback;
18638
tfarina42834112016-09-22 13:38:2018639 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118640 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418641
18642 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118643 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418644}
18645
bncd16676a2016-07-20 16:23:0118646TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0918647 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218648 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918649 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218650 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418651
18652 HttpRequestInfo request;
18653 request.method = "POST";
18654 request.url = GURL("http://www.foo.com/");
18655 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018656 request.traffic_annotation =
18657 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418658
danakj1fd259a02016-04-16 03:17:0918659 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618660 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418661 // Send headers successfully, but get an error while sending the body.
18662 MockWrite data_writes[] = {
18663 MockWrite("POST / HTTP/1.1\r\n"
18664 "Host: www.foo.com\r\n"
18665 "Connection: keep-alive\r\n"
18666 "Content-Length: 3\r\n\r\n"),
18667 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18668 };
18669
18670 MockRead data_reads[] = {
18671 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
18672 MockRead(SYNCHRONOUS, OK),
18673 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118674 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418675 session_deps_.socket_factory->AddSocketDataProvider(&data);
18676
18677 TestCompletionCallback callback;
18678
tfarina42834112016-09-22 13:38:2018679 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118680 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418681
18682 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118683 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418684}
18685
Bence Békydca6bd92018-01-30 13:43:0618686#if BUILDFLAG(ENABLE_WEBSOCKETS)
18687
18688namespace {
18689
18690void AddWebSocketHeaders(HttpRequestHeaders* headers) {
18691 headers->SetHeader("Connection", "Upgrade");
18692 headers->SetHeader("Upgrade", "websocket");
18693 headers->SetHeader("Origin", "http://www.example.org");
18694 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0618695}
18696
18697} // namespace
18698
18699TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0118700 for (bool secure : {true, false}) {
18701 MockWrite data_writes[] = {
18702 MockWrite("GET / HTTP/1.1\r\n"
18703 "Host: www.example.org\r\n"
18704 "Connection: Upgrade\r\n"
18705 "Upgrade: websocket\r\n"
18706 "Origin: http://www.example.org\r\n"
18707 "Sec-WebSocket-Version: 13\r\n"
18708 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18709 "Sec-WebSocket-Extensions: permessage-deflate; "
18710 "client_max_window_bits\r\n\r\n")};
18711
18712 MockRead data_reads[] = {
18713 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18714 "Upgrade: websocket\r\n"
18715 "Connection: Upgrade\r\n"
18716 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
18717
Ryan Sleevib8d7ea02018-05-07 20:01:0118718 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0118719 session_deps_.socket_factory->AddSocketDataProvider(&data);
18720 SSLSocketDataProvider ssl(ASYNC, OK);
18721 if (secure)
18722 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0618723
18724 HttpRequestInfo request;
18725 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0118726 request.url =
18727 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18728 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e62018-02-07 07:41:1018729 request.traffic_annotation =
18730 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0618731
Bence Béky2fcf4fa2018-04-06 20:06:0118732 TestWebSocketHandshakeStreamCreateHelper
18733 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1518734
Bence Béky2fcf4fa2018-04-06 20:06:0118735 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0618736 HttpNetworkTransaction trans(LOW, session.get());
18737 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0118738 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0618739
18740 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0118741 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18742 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0618743
Bence Béky2fcf4fa2018-04-06 20:06:0118744 const HttpStreamRequest* stream_request = trans.stream_request_.get();
18745 ASSERT_TRUE(stream_request);
18746 EXPECT_EQ(&websocket_handshake_stream_create_helper,
18747 stream_request->websocket_handshake_stream_create_helper());
18748
18749 rv = callback.WaitForResult();
18750 EXPECT_THAT(rv, IsOk());
18751
18752 EXPECT_TRUE(data.AllReadDataConsumed());
18753 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0618754 }
18755}
18756
Adam Rice425cf122015-01-19 06:18:2418757// Verify that proxy headers are not sent to the destination server when
18758// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0118759TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2418760 HttpRequestInfo request;
18761 request.method = "GET";
bncce36dca22015-04-21 22:11:2318762 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018763 request.traffic_annotation =
18764 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418765 AddWebSocketHeaders(&request.extra_headers);
18766
18767 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918768 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918769 ProxyResolutionService::CreateFixedFromPacResult(
18770 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418771
danakj1fd259a02016-04-16 03:17:0918772 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418773
18774 // Since a proxy is configured, try to establish a tunnel.
18775 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1718776 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18777 "Host: www.example.org:443\r\n"
18778 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418779
18780 // After calling trans->RestartWithAuth(), this is the request we should
18781 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1718782 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18783 "Host: www.example.org:443\r\n"
18784 "Proxy-Connection: keep-alive\r\n"
18785 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418786
rsleevidb16bb02015-11-12 23:47:1718787 MockWrite("GET / HTTP/1.1\r\n"
18788 "Host: www.example.org\r\n"
18789 "Connection: Upgrade\r\n"
18790 "Upgrade: websocket\r\n"
18791 "Origin: http://www.example.org\r\n"
18792 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1518793 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18794 "Sec-WebSocket-Extensions: permessage-deflate; "
18795 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418796
18797 // The proxy responds to the connect with a 407, using a persistent
18798 // connection.
18799 MockRead data_reads[] = {
18800 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1518801 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
18802 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
18803 "Content-Length: 0\r\n"
18804 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418805
18806 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18807
Bence Béky8d1c6052018-02-07 12:48:1518808 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18809 "Upgrade: websocket\r\n"
18810 "Connection: Upgrade\r\n"
18811 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418812
Ryan Sleevib8d7ea02018-05-07 20:01:0118813 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418814 session_deps_.socket_factory->AddSocketDataProvider(&data);
18815 SSLSocketDataProvider ssl(ASYNC, OK);
18816 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18817
Bence Béky8d1c6052018-02-07 12:48:1518818 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18819
bnc87dcefc2017-05-25 12:47:5818820 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918821 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418822 trans->SetWebSocketHandshakeStreamCreateHelper(
18823 &websocket_stream_create_helper);
18824
18825 {
18826 TestCompletionCallback callback;
18827
tfarina42834112016-09-22 13:38:2018828 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118829 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418830
18831 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118832 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418833 }
18834
18835 const HttpResponseInfo* response = trans->GetResponseInfo();
18836 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218837 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418838 EXPECT_EQ(407, response->headers->response_code());
18839
18840 {
18841 TestCompletionCallback callback;
18842
18843 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
18844 callback.callback());
robpercival214763f2016-07-01 23:27:0118845 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418846
18847 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118848 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418849 }
18850
18851 response = trans->GetResponseInfo();
18852 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218853 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418854
18855 EXPECT_EQ(101, response->headers->response_code());
18856
18857 trans.reset();
18858 session->CloseAllConnections();
18859}
18860
18861// Verify that proxy headers are not sent to the destination server when
18862// establishing a tunnel for an insecure WebSocket connection.
18863// This requires the authentication info to be injected into the auth cache
18864// due to crbug.com/395064
18865// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0118866TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2418867 HttpRequestInfo request;
18868 request.method = "GET";
bncce36dca22015-04-21 22:11:2318869 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018870 request.traffic_annotation =
18871 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418872 AddWebSocketHeaders(&request.extra_headers);
18873
18874 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918875 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918876 ProxyResolutionService::CreateFixedFromPacResult(
18877 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418878
danakj1fd259a02016-04-16 03:17:0918879 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418880
18881 MockWrite data_writes[] = {
18882 // Try to establish a tunnel for the WebSocket connection, with
18883 // credentials. Because WebSockets have a separate set of socket pools,
18884 // they cannot and will not use the same TCP/IP connection as the
18885 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1518886 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
18887 "Host: www.example.org:80\r\n"
18888 "Proxy-Connection: keep-alive\r\n"
18889 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418890
Bence Béky8d1c6052018-02-07 12:48:1518891 MockWrite("GET / HTTP/1.1\r\n"
18892 "Host: www.example.org\r\n"
18893 "Connection: Upgrade\r\n"
18894 "Upgrade: websocket\r\n"
18895 "Origin: http://www.example.org\r\n"
18896 "Sec-WebSocket-Version: 13\r\n"
18897 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18898 "Sec-WebSocket-Extensions: permessage-deflate; "
18899 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418900
18901 MockRead data_reads[] = {
18902 // HTTP CONNECT with credentials.
18903 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18904
18905 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1518906 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18907 "Upgrade: websocket\r\n"
18908 "Connection: Upgrade\r\n"
18909 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418910
Ryan Sleevib8d7ea02018-05-07 20:01:0118911 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418912 session_deps_.socket_factory->AddSocketDataProvider(&data);
18913
18914 session->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:3318915 GURL("http://myproxy:70/"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:2618916 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
18917 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Adam Rice425cf122015-01-19 06:18:2418918
Bence Béky8d1c6052018-02-07 12:48:1518919 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18920
bnc87dcefc2017-05-25 12:47:5818921 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918922 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418923 trans->SetWebSocketHandshakeStreamCreateHelper(
18924 &websocket_stream_create_helper);
18925
18926 TestCompletionCallback callback;
18927
tfarina42834112016-09-22 13:38:2018928 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118929 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418930
18931 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118932 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418933
18934 const HttpResponseInfo* response = trans->GetResponseInfo();
18935 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218936 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418937
18938 EXPECT_EQ(101, response->headers->response_code());
18939
18940 trans.reset();
18941 session->CloseAllConnections();
18942}
18943
Matt Menke1d6093e32019-03-22 17:33:4318944// WebSockets over QUIC is not supported, including over QUIC proxies.
18945TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
18946 for (bool secure : {true, false}) {
18947 SCOPED_TRACE(secure);
18948 session_deps_.proxy_resolution_service =
18949 ProxyResolutionService::CreateFixedFromPacResult(
18950 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
18951 session_deps_.enable_quic = true;
18952
18953 HttpRequestInfo request;
18954 request.url =
18955 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18956 AddWebSocketHeaders(&request.extra_headers);
18957 request.traffic_annotation =
18958 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18959
18960 TestWebSocketHandshakeStreamCreateHelper
18961 websocket_handshake_stream_create_helper;
18962
18963 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18964 HttpNetworkTransaction trans(LOW, session.get());
18965 trans.SetWebSocketHandshakeStreamCreateHelper(
18966 &websocket_handshake_stream_create_helper);
18967
18968 TestCompletionCallback callback;
18969 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18970 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18971
18972 rv = callback.WaitForResult();
18973 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
18974 }
18975}
18976
Bence Békydca6bd92018-01-30 13:43:0618977#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
18978
bncd16676a2016-07-20 16:23:0118979TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0918980 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218981 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918982 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218983 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218984
18985 HttpRequestInfo request;
18986 request.method = "POST";
18987 request.url = GURL("http://www.foo.com/");
18988 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018989 request.traffic_annotation =
18990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218991
danakj1fd259a02016-04-16 03:17:0918992 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618993 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218994 MockWrite data_writes[] = {
18995 MockWrite("POST / HTTP/1.1\r\n"
18996 "Host: www.foo.com\r\n"
18997 "Connection: keep-alive\r\n"
18998 "Content-Length: 3\r\n\r\n"),
18999 MockWrite("foo"),
19000 };
19001
19002 MockRead data_reads[] = {
19003 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19004 MockRead(SYNCHRONOUS, OK),
19005 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119006 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219007 session_deps_.socket_factory->AddSocketDataProvider(&data);
19008
19009 TestCompletionCallback callback;
19010
19011 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019012 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119013 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219014
19015 std::string response_data;
bnc691fda62016-08-12 00:43:1619016 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219017
Ryan Sleevib8d7ea02018-05-07 20:01:0119018 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19019 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219020}
19021
bncd16676a2016-07-20 16:23:0119022TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0919023 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219024 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919025 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219026 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219027
19028 HttpRequestInfo request;
19029 request.method = "POST";
19030 request.url = GURL("http://www.foo.com/");
19031 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019032 request.traffic_annotation =
19033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219034
danakj1fd259a02016-04-16 03:17:0919035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619036 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219037 MockWrite data_writes[] = {
19038 MockWrite("POST / HTTP/1.1\r\n"
19039 "Host: www.foo.com\r\n"
19040 "Connection: keep-alive\r\n"
19041 "Content-Length: 3\r\n\r\n"),
19042 MockWrite("foo"),
19043 };
19044
19045 MockRead data_reads[] = {
19046 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
19047 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19048 MockRead(SYNCHRONOUS, OK),
19049 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119050 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219051 session_deps_.socket_factory->AddSocketDataProvider(&data);
19052
19053 TestCompletionCallback callback;
19054
19055 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019056 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119057 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219058
19059 std::string response_data;
bnc691fda62016-08-12 00:43:1619060 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219061
Ryan Sleevib8d7ea02018-05-07 20:01:0119062 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19063 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219064}
19065
bncd16676a2016-07-20 16:23:0119066TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2219067 ChunkedUploadDataStream upload_data_stream(0);
19068
19069 HttpRequestInfo request;
19070 request.method = "POST";
19071 request.url = GURL("http://www.foo.com/");
19072 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019073 request.traffic_annotation =
19074 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219075
danakj1fd259a02016-04-16 03:17:0919076 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619077 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219078 // Send headers successfully, but get an error while sending the body.
19079 MockWrite data_writes[] = {
19080 MockWrite("POST / HTTP/1.1\r\n"
19081 "Host: www.foo.com\r\n"
19082 "Connection: keep-alive\r\n"
19083 "Transfer-Encoding: chunked\r\n\r\n"),
19084 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
19085 };
19086
19087 MockRead data_reads[] = {
19088 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19089 MockRead(SYNCHRONOUS, OK),
19090 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119091 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219092 session_deps_.socket_factory->AddSocketDataProvider(&data);
19093
19094 TestCompletionCallback callback;
19095
19096 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019097 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2219098
19099 base::RunLoop().RunUntilIdle();
19100 upload_data_stream.AppendData("f", 1, false);
19101
19102 base::RunLoop().RunUntilIdle();
19103 upload_data_stream.AppendData("oo", 2, true);
19104
robpercival214763f2016-07-01 23:27:0119105 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219106
19107 std::string response_data;
bnc691fda62016-08-12 00:43:1619108 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219109
Ryan Sleevib8d7ea02018-05-07 20:01:0119110 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19111 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219112}
19113
eustasc7d27da2017-04-06 10:33:2019114void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
19115 const std::string& accept_encoding,
19116 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0319117 const std::string& location,
eustasc7d27da2017-04-06 10:33:2019118 bool should_match) {
19119 HttpRequestInfo request;
19120 request.method = "GET";
19121 request.url = GURL("http://www.foo.com/");
19122 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
19123 accept_encoding);
Ramin Halavatib5e433e62018-02-07 07:41:1019124 request.traffic_annotation =
19125 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2019126
19127 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
19128 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19129 // Send headers successfully, but get an error while sending the body.
19130 MockWrite data_writes[] = {
19131 MockWrite("GET / HTTP/1.1\r\n"
19132 "Host: www.foo.com\r\n"
19133 "Connection: keep-alive\r\n"
19134 "Accept-Encoding: "),
19135 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
19136 };
19137
sky50576f32017-05-01 19:28:0319138 std::string response_code = "200 OK";
19139 std::string extra;
19140 if (!location.empty()) {
19141 response_code = "301 Redirect\r\nLocation: ";
19142 response_code.append(location);
19143 }
19144
eustasc7d27da2017-04-06 10:33:2019145 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0319146 MockRead("HTTP/1.0 "),
19147 MockRead(response_code.data()),
19148 MockRead("\r\nContent-Encoding: "),
19149 MockRead(content_encoding.data()),
19150 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2019151 MockRead(SYNCHRONOUS, OK),
19152 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119153 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2019154 session_deps->socket_factory->AddSocketDataProvider(&data);
19155
19156 TestCompletionCallback callback;
19157
19158 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19159 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19160
19161 rv = callback.WaitForResult();
19162 if (should_match) {
19163 EXPECT_THAT(rv, IsOk());
19164 } else {
19165 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
19166 }
19167}
19168
19169TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0319170 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2019171}
19172
19173TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0319174 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
19175 true);
eustasc7d27da2017-04-06 10:33:2019176}
19177
19178TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
19179 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0319180 "", false);
19181}
19182
19183TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
19184 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
19185 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2019186}
19187
xunjieli96f2a402017-06-05 17:24:2719188TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
19189 ProxyConfig proxy_config;
19190 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19191 proxy_config.set_pac_mandatory(true);
19192 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5919193 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4919194 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19195 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0419196 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2719197
19198 HttpRequestInfo request;
19199 request.method = "GET";
19200 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019201 request.traffic_annotation =
19202 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719203
19204 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19205 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19206
19207 TestCompletionCallback callback;
19208
19209 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19210 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19211 EXPECT_THAT(callback.WaitForResult(),
19212 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19213}
19214
19215TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
19216 ProxyConfig proxy_config;
19217 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19218 proxy_config.set_pac_mandatory(true);
19219 MockAsyncProxyResolverFactory* proxy_resolver_factory =
19220 new MockAsyncProxyResolverFactory(false);
19221 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5919222 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4919223 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19224 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5919225 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2719226 HttpRequestInfo request;
19227 request.method = "GET";
19228 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019229 request.traffic_annotation =
19230 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719231
19232 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19233 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19234
19235 TestCompletionCallback callback;
19236 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19237 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19238
19239 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
19240 ERR_FAILED, &resolver);
19241 EXPECT_THAT(callback.WaitForResult(),
19242 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19243}
19244
19245TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5919246 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4919247 ProxyResolutionService::CreateFixedFromPacResult(
19248 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719249 session_deps_.enable_quic = false;
19250 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19251
19252 HttpRequestInfo request;
19253 request.method = "GET";
19254 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019255 request.traffic_annotation =
19256 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719257
19258 TestCompletionCallback callback;
19259 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19260 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19261 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19262
19263 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
19264}
19265
Douglas Creager3cb042052018-11-06 23:08:5219266//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1419267// Reporting tests
19268
19269#if BUILDFLAG(ENABLE_REPORTING)
19270class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
19271 protected:
19272 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619273 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1419274 auto test_reporting_context = std::make_unique<TestReportingContext>(
19275 &clock_, &tick_clock_, ReportingPolicy());
19276 test_reporting_context_ = test_reporting_context.get();
19277 session_deps_.reporting_service =
19278 ReportingService::CreateForTesting(std::move(test_reporting_context));
19279 }
19280
19281 TestReportingContext* reporting_context() const {
19282 return test_reporting_context_;
19283 }
19284
19285 void clear_reporting_service() {
19286 session_deps_.reporting_service.reset();
19287 test_reporting_context_ = nullptr;
19288 }
19289
19290 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4219291 void RequestPolicy(CertStatus cert_status = 0) {
19292 HttpRequestInfo request;
19293 request.method = "GET";
19294 request.url = GURL(url_);
19295 request.traffic_annotation =
19296 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19297
Lily Chend3930e72019-03-01 19:31:1119298 MockWrite data_writes[] = {
19299 MockWrite("GET / HTTP/1.1\r\n"
19300 "Host: www.example.org\r\n"
19301 "Connection: keep-alive\r\n\r\n"),
19302 };
Douglas Creager134b52e2018-11-09 18:00:1419303 MockRead data_reads[] = {
19304 MockRead("HTTP/1.0 200 OK\r\n"),
19305 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
19306 "\"endpoints\": [{\"url\": "
19307 "\"https://www.example.org/upload/\"}]}\r\n"),
19308 MockRead("\r\n"),
19309 MockRead("hello world"),
19310 MockRead(SYNCHRONOUS, OK),
19311 };
Douglas Creager134b52e2018-11-09 18:00:1419312
Lily Chenfec60d92019-01-24 01:16:4219313 StaticSocketDataProvider reads(data_reads, data_writes);
19314 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1419315
19316 SSLSocketDataProvider ssl(ASYNC, OK);
19317 if (request.url.SchemeIsCryptographic()) {
19318 ssl.ssl_info.cert =
19319 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19320 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219321 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1419322 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19323 }
19324
Douglas Creager134b52e2018-11-09 18:00:1419325 TestCompletionCallback callback;
19326 auto session = CreateSession(&session_deps_);
19327 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19328 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4219329 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1419330 }
19331
19332 protected:
19333 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1419334
19335 private:
19336 TestReportingContext* test_reporting_context_;
19337};
19338
19339TEST_F(HttpNetworkTransactionReportingTest,
19340 DontProcessReportToHeaderNoService) {
19341 base::HistogramTester histograms;
19342 clear_reporting_service();
19343 RequestPolicy();
19344 histograms.ExpectBucketCount(
19345 ReportingHeaderParser::kHeaderOutcomeHistogram,
19346 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
19347}
19348
19349TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
19350 base::HistogramTester histograms;
19351 url_ = "http://www.example.org/";
19352 RequestPolicy();
19353 histograms.ExpectBucketCount(
19354 ReportingHeaderParser::kHeaderOutcomeHistogram,
19355 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
19356}
19357
19358TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
19359 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5419360 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1019361 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5419362 reporting_context()->cache()->GetEndpointForTesting(
19363 url::Origin::Create(GURL("https://www.example.org/")), "nel",
19364 GURL("https://www.example.org/upload/"));
19365 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1419366}
19367
19368TEST_F(HttpNetworkTransactionReportingTest,
19369 DontProcessReportToHeaderInvalidHttps) {
19370 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219371 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19372 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1419373 histograms.ExpectBucketCount(
19374 ReportingHeaderParser::kHeaderOutcomeHistogram,
19375 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
19376}
19377#endif // BUILDFLAG(ENABLE_REPORTING)
19378
19379//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5219380// Network Error Logging tests
19381
19382#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4219383namespace {
19384
19385const char kUserAgent[] = "Mozilla/1.0";
19386const char kReferrer[] = "https://www.referrer.org/";
19387
19388} // namespace
19389
Douglas Creager3cb042052018-11-06 23:08:5219390class HttpNetworkTransactionNetworkErrorLoggingTest
19391 : public HttpNetworkTransactionTest {
19392 protected:
19393 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619394 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5219395 auto network_error_logging_service =
19396 std::make_unique<TestNetworkErrorLoggingService>();
19397 test_network_error_logging_service_ = network_error_logging_service.get();
19398 session_deps_.network_error_logging_service =
19399 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4219400
19401 extra_headers_.SetHeader("User-Agent", kUserAgent);
19402 extra_headers_.SetHeader("Referer", kReferrer);
19403
19404 request_.method = "GET";
19405 request_.url = GURL(url_);
19406 request_.extra_headers = extra_headers_;
19407 request_.reporting_upload_depth = reporting_upload_depth_;
19408 request_.traffic_annotation =
19409 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5219410 }
19411
19412 TestNetworkErrorLoggingService* network_error_logging_service() const {
19413 return test_network_error_logging_service_;
19414 }
19415
19416 void clear_network_error_logging_service() {
19417 session_deps_.network_error_logging_service.reset();
19418 test_network_error_logging_service_ = nullptr;
19419 }
19420
19421 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4219422 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3619423 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319424 MockWrite data_writes[] = {
19425 MockWrite("GET / HTTP/1.1\r\n"
19426 "Host: www.example.org\r\n"
19427 "Connection: keep-alive\r\n"),
19428 MockWrite(ASYNC, extra_header_string.data(),
19429 extra_header_string.size()),
19430 };
Lily Chend3930e72019-03-01 19:31:1119431 MockRead data_reads[] = {
19432 MockRead("HTTP/1.0 200 OK\r\n"),
19433 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19434 MockRead("\r\n"),
19435 MockRead("hello world"),
19436 MockRead(SYNCHRONOUS, OK),
19437 };
Douglas Creager3cb042052018-11-06 23:08:5219438
Lily Chenfec60d92019-01-24 01:16:4219439 StaticSocketDataProvider reads(data_reads, data_writes);
19440 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5219441
19442 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4219443 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5219444 ssl.ssl_info.cert =
19445 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19446 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219447 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5219448 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19449 }
19450
Douglas Creager3cb042052018-11-06 23:08:5219451 TestCompletionCallback callback;
19452 auto session = CreateSession(&session_deps_);
19453 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4219454 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
19455 EXPECT_THAT(callback.GetResult(rv), IsOk());
19456
19457 std::string response_data;
19458 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
19459 EXPECT_EQ("hello world", response_data);
19460 }
19461
19462 void CheckReport(size_t index,
19463 int status_code,
19464 int error_type,
19465 IPAddress server_ip = IPAddress::IPv4Localhost()) {
19466 ASSERT_LT(index, network_error_logging_service()->errors().size());
19467
19468 const NetworkErrorLoggingService::RequestDetails& error =
19469 network_error_logging_service()->errors()[index];
19470 EXPECT_EQ(url_, error.uri);
19471 EXPECT_EQ(kReferrer, error.referrer);
19472 EXPECT_EQ(kUserAgent, error.user_agent);
19473 EXPECT_EQ(server_ip, error.server_ip);
19474 EXPECT_EQ("http/1.1", error.protocol);
19475 EXPECT_EQ("GET", error.method);
19476 EXPECT_EQ(status_code, error.status_code);
19477 EXPECT_EQ(error_type, error.type);
19478 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5219479 }
19480
19481 protected:
19482 std::string url_ = "https://www.example.org/";
19483 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4219484 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3619485 HttpRequestHeaders extra_headers_;
19486 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5219487
19488 private:
19489 TestNetworkErrorLoggingService* test_network_error_logging_service_;
19490};
19491
19492TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19493 DontProcessNelHeaderNoService) {
19494 base::HistogramTester histograms;
19495 clear_network_error_logging_service();
19496 RequestPolicy();
19497 histograms.ExpectBucketCount(
19498 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19499 NetworkErrorLoggingService::HeaderOutcome::
19500 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
19501 1);
19502}
19503
19504TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19505 DontProcessNelHeaderHttp) {
19506 base::HistogramTester histograms;
19507 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4219508 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5219509 RequestPolicy();
19510 histograms.ExpectBucketCount(
19511 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19512 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
19513}
19514
Lily Chen90ae93cc2019-02-14 01:15:3919515// Don't set NEL policies received on a proxied connection.
19516TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19517 DontProcessNelHeaderProxy) {
19518 session_deps_.proxy_resolution_service =
19519 ProxyResolutionService::CreateFixedFromPacResult(
19520 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19521 BoundTestNetLog log;
19522 session_deps_.net_log = log.bound().net_log();
19523 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19524
19525 HttpRequestInfo request;
19526 request.method = "GET";
19527 request.url = GURL("https://www.example.org/");
19528 request.traffic_annotation =
19529 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19530
19531 // Since we have proxy, should try to establish tunnel.
19532 MockWrite data_writes1[] = {
19533 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19534 "Host: www.example.org:443\r\n"
19535 "Proxy-Connection: keep-alive\r\n\r\n"),
19536
19537 MockWrite("GET / HTTP/1.1\r\n"
19538 "Host: www.example.org\r\n"
19539 "Connection: keep-alive\r\n\r\n"),
19540 };
19541
19542 MockRead data_reads1[] = {
19543 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19544
19545 MockRead("HTTP/1.1 200 OK\r\n"),
19546 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19547 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19548 MockRead("Content-Length: 100\r\n\r\n"),
19549 MockRead(SYNCHRONOUS, OK),
19550 };
19551
19552 StaticSocketDataProvider data1(data_reads1, data_writes1);
19553 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19554 SSLSocketDataProvider ssl(ASYNC, OK);
19555 ssl.ssl_info.cert =
19556 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19557 ASSERT_TRUE(ssl.ssl_info.cert);
19558 ssl.ssl_info.cert_status = 0;
19559 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19560
19561 TestCompletionCallback callback1;
19562 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19563
19564 int rv = trans.Start(&request, callback1.callback(), log.bound());
19565 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19566
19567 rv = callback1.WaitForResult();
19568 EXPECT_THAT(rv, IsOk());
19569
19570 const HttpResponseInfo* response = trans.GetResponseInfo();
19571 ASSERT_TRUE(response);
19572 EXPECT_EQ(200, response->headers->response_code());
19573 EXPECT_TRUE(response->was_fetched_via_proxy);
19574
19575 // No NEL header was set.
19576 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
19577}
19578
Douglas Creager3cb042052018-11-06 23:08:5219579TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
19580 RequestPolicy();
19581 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
19582 const auto& header = network_error_logging_service()->headers()[0];
19583 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
19584 header.origin);
19585 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
19586 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
19587}
19588
19589TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19590 DontProcessNelHeaderInvalidHttps) {
19591 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219592 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19593 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5219594 histograms.ExpectBucketCount(
19595 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19596 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
19597 1);
19598}
Douglas Creageref5eecdc2018-11-09 20:50:3619599
Lily Chenfec60d92019-01-24 01:16:4219600TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3619601 RequestPolicy();
19602 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219603 CheckReport(0 /* index */, 200 /* status_code */, OK);
19604}
19605
19606TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19607 CreateReportErrorAfterStart) {
19608 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19609 auto trans =
19610 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19611
19612 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
19613 StaticSocketDataProvider data;
19614 data.set_connect_data(mock_connect);
19615 session_deps_.socket_factory->AddSocketDataProvider(&data);
19616
19617 TestCompletionCallback callback;
19618
19619 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19620 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19621
19622 trans.reset();
19623
19624 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19625 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19626 IPAddress() /* server_ip */);
19627}
19628
19629// Same as above except the error is ASYNC
19630TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19631 CreateReportErrorAfterStartAsync) {
19632 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19633 auto trans =
19634 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19635
19636 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
19637 StaticSocketDataProvider data;
19638 data.set_connect_data(mock_connect);
19639 session_deps_.socket_factory->AddSocketDataProvider(&data);
19640
19641 TestCompletionCallback callback;
19642
19643 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19644 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19645
19646 trans.reset();
19647
19648 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19649 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19650 IPAddress() /* server_ip */);
19651}
19652
19653TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19654 CreateReportReadBodyError) {
19655 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319656 MockWrite data_writes[] = {
19657 MockWrite("GET / HTTP/1.1\r\n"
19658 "Host: www.example.org\r\n"
19659 "Connection: keep-alive\r\n"),
19660 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19661 };
Lily Chend3930e72019-03-01 19:31:1119662 MockRead data_reads[] = {
19663 MockRead("HTTP/1.0 200 OK\r\n"),
19664 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19665 MockRead("hello world"),
19666 MockRead(SYNCHRONOUS, OK),
19667 };
Lily Chenfec60d92019-01-24 01:16:4219668
19669 StaticSocketDataProvider reads(data_reads, data_writes);
19670 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19671
19672 SSLSocketDataProvider ssl(ASYNC, OK);
19673 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19674
19675 // Log start time
19676 base::TimeTicks start_time = base::TimeTicks::Now();
19677
19678 TestCompletionCallback callback;
19679 auto session = CreateSession(&session_deps_);
19680 auto trans =
19681 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19682 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19683 EXPECT_THAT(callback.GetResult(rv), IsOk());
19684
19685 const HttpResponseInfo* response = trans->GetResponseInfo();
19686 ASSERT_TRUE(response);
19687
19688 EXPECT_TRUE(response->headers);
19689 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19690
19691 std::string response_data;
19692 rv = ReadTransaction(trans.get(), &response_data);
19693 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19694
19695 trans.reset();
19696
19697 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19698
19699 CheckReport(0 /* index */, 200 /* status_code */,
19700 ERR_CONTENT_LENGTH_MISMATCH);
19701 const NetworkErrorLoggingService::RequestDetails& error =
19702 network_error_logging_service()->errors()[0];
19703 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19704}
19705
19706// Same as above except the final read is ASYNC.
19707TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19708 CreateReportReadBodyErrorAsync) {
19709 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319710 MockWrite data_writes[] = {
19711 MockWrite("GET / HTTP/1.1\r\n"
19712 "Host: www.example.org\r\n"
19713 "Connection: keep-alive\r\n"),
19714 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19715 };
Lily Chend3930e72019-03-01 19:31:1119716 MockRead data_reads[] = {
19717 MockRead("HTTP/1.0 200 OK\r\n"),
19718 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19719 MockRead("hello world"),
19720 MockRead(ASYNC, OK),
19721 };
Lily Chenfec60d92019-01-24 01:16:4219722
19723 StaticSocketDataProvider reads(data_reads, data_writes);
19724 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19725
19726 SSLSocketDataProvider ssl(ASYNC, OK);
19727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19728
19729 // Log start time
19730 base::TimeTicks start_time = base::TimeTicks::Now();
19731
19732 TestCompletionCallback callback;
19733 auto session = CreateSession(&session_deps_);
19734 auto trans =
19735 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19736 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19737 EXPECT_THAT(callback.GetResult(rv), IsOk());
19738
19739 const HttpResponseInfo* response = trans->GetResponseInfo();
19740 ASSERT_TRUE(response);
19741
19742 EXPECT_TRUE(response->headers);
19743 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19744
19745 std::string response_data;
19746 rv = ReadTransaction(trans.get(), &response_data);
19747 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19748
19749 trans.reset();
19750
19751 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19752
19753 CheckReport(0 /* index */, 200 /* status_code */,
19754 ERR_CONTENT_LENGTH_MISMATCH);
19755 const NetworkErrorLoggingService::RequestDetails& error =
19756 network_error_logging_service()->errors()[0];
19757 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19758}
19759
19760TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19761 CreateReportRestartWithAuth) {
19762 std::string extra_header_string = extra_headers_.ToString();
19763 static const base::TimeDelta kSleepDuration =
19764 base::TimeDelta::FromMilliseconds(10);
19765
19766 MockWrite data_writes1[] = {
19767 MockWrite("GET / HTTP/1.1\r\n"
19768 "Host: www.example.org\r\n"
19769 "Connection: keep-alive\r\n"),
19770 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19771 };
19772
19773 MockRead data_reads1[] = {
19774 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19775 // Give a couple authenticate options (only the middle one is actually
19776 // supported).
19777 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19778 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19779 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19780 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19781 // Large content-length -- won't matter, as connection will be reset.
19782 MockRead("Content-Length: 10000\r\n\r\n"),
19783 MockRead(SYNCHRONOUS, ERR_FAILED),
19784 };
19785
19786 // After calling trans->RestartWithAuth(), this is the request we should
19787 // be issuing -- the final header line contains the credentials.
19788 MockWrite data_writes2[] = {
19789 MockWrite("GET / HTTP/1.1\r\n"
19790 "Host: www.example.org\r\n"
19791 "Connection: keep-alive\r\n"
19792 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19793 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19794 };
19795
19796 // Lastly, the server responds with the actual content.
19797 MockRead data_reads2[] = {
19798 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19799 MockRead("hello world"),
19800 MockRead(SYNCHRONOUS, OK),
19801 };
19802
19803 StaticSocketDataProvider data1(data_reads1, data_writes1);
19804 StaticSocketDataProvider data2(data_reads2, data_writes2);
19805 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19806 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19807
19808 SSLSocketDataProvider ssl1(ASYNC, OK);
19809 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19810 SSLSocketDataProvider ssl2(ASYNC, OK);
19811 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19812
19813 base::TimeTicks start_time = base::TimeTicks::Now();
19814 base::TimeTicks restart_time;
19815
19816 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19817 auto trans =
19818 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19819
19820 TestCompletionCallback callback1;
19821
19822 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19823 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19824
19825 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19826
19827 TestCompletionCallback callback2;
19828
19829 // Wait 10 ms then restart with auth
19830 FastForwardBy(kSleepDuration);
19831 restart_time = base::TimeTicks::Now();
19832 rv =
19833 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19834 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19835
19836 std::string response_data;
19837 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19838 EXPECT_EQ("hello world", response_data);
19839
19840 trans.reset();
19841
19842 // One 401 report for the auth challenge, then a 200 report for the successful
19843 // retry. Note that we don't report the error draining the body, as the first
19844 // request already generated a report for the auth challenge.
19845 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19846
19847 // Check error report contents
19848 CheckReport(0 /* index */, 401 /* status_code */, OK);
19849 CheckReport(1 /* index */, 200 /* status_code */, OK);
19850
19851 const NetworkErrorLoggingService::RequestDetails& error1 =
19852 network_error_logging_service()->errors()[0];
19853 const NetworkErrorLoggingService::RequestDetails& error2 =
19854 network_error_logging_service()->errors()[1];
19855
19856 // Sanity-check elapsed time values
19857 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19858 // Check that the start time is refreshed when restarting with auth.
19859 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19860}
19861
19862// Same as above, except draining the body before restarting fails
19863// asynchronously.
19864TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19865 CreateReportRestartWithAuthAsync) {
19866 std::string extra_header_string = extra_headers_.ToString();
19867 static const base::TimeDelta kSleepDuration =
19868 base::TimeDelta::FromMilliseconds(10);
19869
19870 MockWrite data_writes1[] = {
19871 MockWrite("GET / HTTP/1.1\r\n"
19872 "Host: www.example.org\r\n"
19873 "Connection: keep-alive\r\n"),
19874 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19875 };
19876
19877 MockRead data_reads1[] = {
19878 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19879 // Give a couple authenticate options (only the middle one is actually
19880 // supported).
19881 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19882 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19883 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19884 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19885 // Large content-length -- won't matter, as connection will be reset.
19886 MockRead("Content-Length: 10000\r\n\r\n"),
19887 MockRead(ASYNC, ERR_FAILED),
19888 };
19889
19890 // After calling trans->RestartWithAuth(), this is the request we should
19891 // be issuing -- the final header line contains the credentials.
19892 MockWrite data_writes2[] = {
19893 MockWrite("GET / HTTP/1.1\r\n"
19894 "Host: www.example.org\r\n"
19895 "Connection: keep-alive\r\n"
19896 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19897 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19898 };
19899
19900 // Lastly, the server responds with the actual content.
19901 MockRead data_reads2[] = {
19902 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19903 MockRead("hello world"),
19904 MockRead(SYNCHRONOUS, OK),
19905 };
19906
19907 StaticSocketDataProvider data1(data_reads1, data_writes1);
19908 StaticSocketDataProvider data2(data_reads2, data_writes2);
19909 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19910 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19911
19912 SSLSocketDataProvider ssl1(ASYNC, OK);
19913 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19914 SSLSocketDataProvider ssl2(ASYNC, OK);
19915 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19916
19917 base::TimeTicks start_time = base::TimeTicks::Now();
19918 base::TimeTicks restart_time;
19919
19920 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19921 auto trans =
19922 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19923
19924 TestCompletionCallback callback1;
19925
19926 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19927 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19928
19929 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19930
19931 TestCompletionCallback callback2;
19932
19933 // Wait 10 ms then restart with auth
19934 FastForwardBy(kSleepDuration);
19935 restart_time = base::TimeTicks::Now();
19936 rv =
19937 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19938 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19939
19940 std::string response_data;
19941 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19942 EXPECT_EQ("hello world", response_data);
19943
19944 trans.reset();
19945
19946 // One 401 report for the auth challenge, then a 200 report for the successful
19947 // retry. Note that we don't report the error draining the body, as the first
19948 // request already generated a report for the auth challenge.
19949 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19950
19951 // Check error report contents
19952 CheckReport(0 /* index */, 401 /* status_code */, OK);
19953 CheckReport(1 /* index */, 200 /* status_code */, OK);
19954
19955 const NetworkErrorLoggingService::RequestDetails& error1 =
19956 network_error_logging_service()->errors()[0];
19957 const NetworkErrorLoggingService::RequestDetails& error2 =
19958 network_error_logging_service()->errors()[1];
19959
19960 // Sanity-check elapsed time values
19961 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19962 // Check that the start time is refreshed when restarting with auth.
19963 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19964}
19965
19966TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19967 CreateReportRetryKeepAliveConnectionReset) {
19968 std::string extra_header_string = extra_headers_.ToString();
19969 MockWrite data_writes1[] = {
19970 MockWrite("GET / HTTP/1.1\r\n"
19971 "Host: www.example.org\r\n"
19972 "Connection: keep-alive\r\n"),
19973 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19974 MockWrite("GET / HTTP/1.1\r\n"
19975 "Host: www.example.org\r\n"
19976 "Connection: keep-alive\r\n"),
19977 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19978 };
19979
19980 MockRead data_reads1[] = {
19981 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19982 MockRead("hello"),
19983 // Connection is reset
19984 MockRead(ASYNC, ERR_CONNECTION_RESET),
19985 };
19986
19987 // Successful retry
19988 MockRead data_reads2[] = {
19989 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19990 MockRead("world"),
19991 MockRead(ASYNC, OK),
19992 };
19993
19994 StaticSocketDataProvider data1(data_reads1, data_writes1);
19995 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19996 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19997 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19998
19999 SSLSocketDataProvider ssl1(ASYNC, OK);
20000 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20001 SSLSocketDataProvider ssl2(ASYNC, OK);
20002 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20003
20004 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20005 auto trans1 =
20006 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20007
20008 TestCompletionCallback callback1;
20009
20010 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20011 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20012
20013 std::string response_data;
20014 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20015 EXPECT_EQ("hello", response_data);
20016
20017 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20018
20019 auto trans2 =
20020 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20021
20022 TestCompletionCallback callback2;
20023
20024 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20025 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20026
20027 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20028 EXPECT_EQ("world", response_data);
20029
20030 trans1.reset();
20031 trans2.reset();
20032
20033 // One OK report from first request, then a ERR_CONNECTION_RESET report from
20034 // the second request, then an OK report from the successful retry.
20035 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20036
20037 // Check error report contents
20038 CheckReport(0 /* index */, 200 /* status_code */, OK);
20039 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
20040 CheckReport(2 /* index */, 200 /* status_code */, OK);
20041}
20042
20043TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20044 CreateReportRetryKeepAlive408) {
20045 std::string extra_header_string = extra_headers_.ToString();
20046 MockWrite data_writes1[] = {
20047 MockWrite("GET / HTTP/1.1\r\n"
20048 "Host: www.example.org\r\n"
20049 "Connection: keep-alive\r\n"),
20050 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20051 MockWrite("GET / HTTP/1.1\r\n"
20052 "Host: www.example.org\r\n"
20053 "Connection: keep-alive\r\n"),
20054 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20055 };
20056
20057 MockRead data_reads1[] = {
20058 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20059 MockRead("hello"),
20060 // 408 Request Timeout
20061 MockRead(SYNCHRONOUS,
20062 "HTTP/1.1 408 Request Timeout\r\n"
20063 "Connection: Keep-Alive\r\n"
20064 "Content-Length: 6\r\n\r\n"
20065 "Pickle"),
20066 };
20067
20068 // Successful retry
20069 MockRead data_reads2[] = {
20070 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20071 MockRead("world"),
20072 MockRead(ASYNC, OK),
20073 };
20074
20075 StaticSocketDataProvider data1(data_reads1, data_writes1);
20076 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20077 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20078 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20079
20080 SSLSocketDataProvider ssl1(ASYNC, OK);
20081 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20082 SSLSocketDataProvider ssl2(ASYNC, OK);
20083 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20084
20085 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20086 auto trans1 =
20087 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20088
20089 TestCompletionCallback callback1;
20090
20091 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20092 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20093
20094 std::string response_data;
20095 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20096 EXPECT_EQ("hello", response_data);
20097
20098 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20099
20100 auto trans2 =
20101 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20102
20103 TestCompletionCallback callback2;
20104
20105 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20106 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20107
20108 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20109 EXPECT_EQ("world", response_data);
20110
20111 trans1.reset();
20112 trans2.reset();
20113
20114 // One 200 report from first request, then a 408 report from
20115 // the second request, then a 200 report from the successful retry.
20116 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20117
20118 // Check error report contents
20119 CheckReport(0 /* index */, 200 /* status_code */, OK);
20120 CheckReport(1 /* index */, 408 /* status_code */, OK);
20121 CheckReport(2 /* index */, 200 /* status_code */, OK);
20122}
20123
20124TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20125 CreateReportRetry421WithoutConnectionPooling) {
20126 // Two hosts resolve to the same IP address.
20127 const std::string ip_addr = "1.2.3.4";
20128 IPAddress ip;
20129 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20130 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20131
20132 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20133 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20134 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20135
20136 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20137
20138 // Two requests on the first connection.
20139 spdy::SpdySerializedFrame req1(
20140 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20141 spdy_util_.UpdateWithStreamDestruction(1);
20142 spdy::SpdySerializedFrame req2(
20143 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20144 spdy::SpdySerializedFrame rst(
20145 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20146 MockWrite writes1[] = {
20147 CreateMockWrite(req1, 0),
20148 CreateMockWrite(req2, 3),
20149 CreateMockWrite(rst, 6),
20150 };
20151
20152 // The first one succeeds, the second gets error 421 Misdirected Request.
20153 spdy::SpdySerializedFrame resp1(
20154 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20155 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
20156 spdy::SpdyHeaderBlock response_headers;
20157 response_headers[spdy::kHttp2StatusHeader] = "421";
20158 spdy::SpdySerializedFrame resp2(
20159 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
20160 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20161 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20162
20163 MockConnect connect1(ASYNC, OK, peer_addr);
20164 SequencedSocketData data1(connect1, reads1, writes1);
20165 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20166
20167 AddSSLSocketData();
20168
20169 // Retry the second request on a second connection.
20170 SpdyTestUtil spdy_util2;
20171 spdy::SpdySerializedFrame req3(
20172 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20173 MockWrite writes2[] = {
20174 CreateMockWrite(req3, 0),
20175 };
20176
20177 spdy::SpdySerializedFrame resp3(
20178 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20179 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20180 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20181 MockRead(ASYNC, 0, 3)};
20182
20183 MockConnect connect2(ASYNC, OK, peer_addr);
20184 SequencedSocketData data2(connect2, reads2, writes2);
20185 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20186
20187 AddSSLSocketData();
20188
20189 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3320190 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3320191 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
20192 base::nullopt);
Eric Orthf4db66a2019-02-19 21:35:3320193 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4220194
20195 HttpRequestInfo request1;
20196 request1.method = "GET";
20197 request1.url = GURL("https://www.example.org/");
20198 request1.load_flags = 0;
20199 request1.traffic_annotation =
20200 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20201 auto trans1 =
20202 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20203
Eric Orthf4db66a2019-02-19 21:35:3320204 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220205 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20206 EXPECT_THAT(callback.GetResult(rv), IsOk());
20207
20208 const HttpResponseInfo* response = trans1->GetResponseInfo();
20209 ASSERT_TRUE(response);
20210 ASSERT_TRUE(response->headers);
20211 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20212 EXPECT_TRUE(response->was_fetched_via_spdy);
20213 EXPECT_TRUE(response->was_alpn_negotiated);
20214 std::string response_data;
20215 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20216 EXPECT_EQ("hello!", response_data);
20217
20218 trans1.reset();
20219
20220 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20221
20222 HttpRequestInfo request2;
20223 request2.method = "GET";
20224 request2.url = GURL("https://mail.example.org/");
20225 request2.load_flags = 0;
20226 request2.traffic_annotation =
20227 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20228 auto trans2 =
20229 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20230
20231 BoundTestNetLog log;
20232 rv = trans2->Start(&request2, callback.callback(), log.bound());
20233 EXPECT_THAT(callback.GetResult(rv), IsOk());
20234
20235 response = trans2->GetResponseInfo();
20236 ASSERT_TRUE(response);
20237 ASSERT_TRUE(response->headers);
20238 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20239 EXPECT_TRUE(response->was_fetched_via_spdy);
20240 EXPECT_TRUE(response->was_alpn_negotiated);
20241 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20242 EXPECT_EQ("hello!", response_data);
20243
20244 trans2.reset();
20245
20246 // One 200 report from the first request, then a 421 report from the
20247 // second request, then a 200 report from the successful retry.
20248 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20249
20250 // Check error report contents
20251 const NetworkErrorLoggingService::RequestDetails& error1 =
20252 network_error_logging_service()->errors()[0];
20253 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
20254 EXPECT_TRUE(error1.referrer.is_empty());
20255 EXPECT_EQ("", error1.user_agent);
20256 EXPECT_EQ(ip, error1.server_ip);
20257 EXPECT_EQ("h2", error1.protocol);
20258 EXPECT_EQ("GET", error1.method);
20259 EXPECT_EQ(200, error1.status_code);
20260 EXPECT_EQ(OK, error1.type);
20261 EXPECT_EQ(0, error1.reporting_upload_depth);
20262
20263 const NetworkErrorLoggingService::RequestDetails& error2 =
20264 network_error_logging_service()->errors()[1];
20265 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
20266 EXPECT_TRUE(error2.referrer.is_empty());
20267 EXPECT_EQ("", error2.user_agent);
20268 EXPECT_EQ(ip, error2.server_ip);
20269 EXPECT_EQ("h2", error2.protocol);
20270 EXPECT_EQ("GET", error2.method);
20271 EXPECT_EQ(421, error2.status_code);
20272 EXPECT_EQ(OK, error2.type);
20273 EXPECT_EQ(0, error2.reporting_upload_depth);
20274
20275 const NetworkErrorLoggingService::RequestDetails& error3 =
20276 network_error_logging_service()->errors()[2];
20277 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
20278 EXPECT_TRUE(error3.referrer.is_empty());
20279 EXPECT_EQ("", error3.user_agent);
20280 EXPECT_EQ(ip, error3.server_ip);
20281 EXPECT_EQ("h2", error3.protocol);
20282 EXPECT_EQ("GET", error3.method);
20283 EXPECT_EQ(200, error3.status_code);
20284 EXPECT_EQ(OK, error3.type);
20285 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3620286}
20287
Lily Chend3930e72019-03-01 19:31:1120288TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20289 CreateReportCancelAfterStart) {
20290 StaticSocketDataProvider data;
20291 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
20292 session_deps_.socket_factory->AddSocketDataProvider(&data);
20293
20294 TestCompletionCallback callback;
20295 auto session = CreateSession(&session_deps_);
20296 auto trans =
20297 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20298 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20299 EXPECT_EQ(rv, ERR_IO_PENDING);
20300
20301 // Cancel after start.
20302 trans.reset();
20303
20304 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20305 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
20306 IPAddress() /* server_ip */);
20307}
20308
20309TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20310 CreateReportCancelBeforeReadingBody) {
20311 std::string extra_header_string = extra_headers_.ToString();
20312 MockWrite data_writes[] = {
20313 MockWrite("GET / HTTP/1.1\r\n"
20314 "Host: www.example.org\r\n"
20315 "Connection: keep-alive\r\n"),
20316 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20317 };
20318 MockRead data_reads[] = {
20319 MockRead("HTTP/1.0 200 OK\r\n"),
20320 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
20321 };
20322
20323 StaticSocketDataProvider data(data_reads, data_writes);
20324 session_deps_.socket_factory->AddSocketDataProvider(&data);
20325
20326 SSLSocketDataProvider ssl(ASYNC, OK);
20327 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20328
20329 TestCompletionCallback callback;
20330 auto session = CreateSession(&session_deps_);
20331 auto trans =
20332 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20333 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20334 EXPECT_THAT(callback.GetResult(rv), IsOk());
20335
20336 const HttpResponseInfo* response = trans->GetResponseInfo();
20337 ASSERT_TRUE(response);
20338
20339 EXPECT_TRUE(response->headers);
20340 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20341
20342 // Cancel before reading the body.
20343 trans.reset();
20344
20345 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20346 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
20347}
20348
Lily Chen00196ab62018-12-04 19:52:2920349TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
20350 base::HistogramTester histograms;
20351 RequestPolicy();
20352 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20353 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20354
20355 // Make HTTP request
20356 std::string extra_header_string = extra_headers_.ToString();
20357 MockRead data_reads[] = {
20358 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20359 MockRead("hello world"),
20360 MockRead(SYNCHRONOUS, OK),
20361 };
20362 MockWrite data_writes[] = {
20363 MockWrite("GET / HTTP/1.1\r\n"
20364 "Host: www.example.org\r\n"
20365 "Connection: keep-alive\r\n"),
20366 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20367 };
20368
Lily Chend3930e72019-03-01 19:31:1120369 StaticSocketDataProvider data(data_reads, data_writes);
20370 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2920371
Lily Chenfec60d92019-01-24 01:16:4220372 // Insecure url
20373 url_ = "http://www.example.org/";
20374 request_.url = GURL(url_);
20375
Lily Chen00196ab62018-12-04 19:52:2920376 TestCompletionCallback callback;
20377 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4220378 auto trans =
20379 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20380 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20381 EXPECT_THAT(callback.GetResult(rv), IsOk());
20382
20383 std::string response_data;
20384 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20385 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2920386
20387 // Insecure request does not generate a report
20388 histograms.ExpectBucketCount(
20389 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0520390 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2920391
20392 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20393}
20394
20395TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20396 DontCreateReportHttpError) {
20397 base::HistogramTester histograms;
20398 RequestPolicy();
20399 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20400 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20401
20402 // Make HTTP request that fails
20403 MockRead data_reads[] = {
20404 MockRead("hello world"),
20405 MockRead(SYNCHRONOUS, OK),
20406 };
20407
20408 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
20409 session_deps_.socket_factory->AddSocketDataProvider(&data);
20410
Lily Chenfec60d92019-01-24 01:16:4220411 url_ = "http://www.originwithoutpolicy.com:2000/";
20412 request_.url = GURL(url_);
20413
Lily Chen00196ab62018-12-04 19:52:2920414 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20415
Lily Chen00196ab62018-12-04 19:52:2920416 auto trans =
20417 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2920418 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220419 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2920420 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
20421
20422 // Insecure request does not generate a report, regardless of existence of a
20423 // policy for the origin.
20424 histograms.ExpectBucketCount(
20425 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0520426 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2920427
20428 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20429}
20430
Lily Chen90ae93cc2019-02-14 01:15:3920431// Don't report on proxy auth challenges, don't report if connecting through a
20432// proxy.
20433TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
20434 HttpRequestInfo request;
20435 request.method = "GET";
20436 request.url = GURL("https://www.example.org/");
20437 request.traffic_annotation =
20438 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20439
20440 // Configure against proxy server "myproxy:70".
20441 session_deps_.proxy_resolution_service =
20442 ProxyResolutionService::CreateFixedFromPacResult(
20443 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20444 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20445
20446 // Since we have proxy, should try to establish tunnel.
20447 MockWrite data_writes1[] = {
20448 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20449 "Host: www.example.org:443\r\n"
20450 "Proxy-Connection: keep-alive\r\n\r\n"),
20451 };
20452
20453 // The proxy responds to the connect with a 407, using a non-persistent
20454 // connection.
20455 MockRead data_reads1[] = {
20456 // No credentials.
20457 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
20458 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20459 MockRead("Proxy-Connection: close\r\n\r\n"),
20460 };
20461
20462 MockWrite data_writes2[] = {
20463 // After calling trans->RestartWithAuth(), this is the request we should
20464 // be issuing -- the final header line contains the credentials.
20465 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20466 "Host: www.example.org:443\r\n"
20467 "Proxy-Connection: keep-alive\r\n"
20468 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
20469
20470 MockWrite("GET / HTTP/1.1\r\n"
20471 "Host: www.example.org\r\n"
20472 "Connection: keep-alive\r\n\r\n"),
20473 };
20474
20475 MockRead data_reads2[] = {
20476 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
20477
20478 MockRead("HTTP/1.1 200 OK\r\n"),
20479 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20480 MockRead("Content-Length: 5\r\n\r\n"),
20481 MockRead(SYNCHRONOUS, "hello"),
20482 };
20483
20484 StaticSocketDataProvider data1(data_reads1, data_writes1);
20485 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20486 StaticSocketDataProvider data2(data_reads2, data_writes2);
20487 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20488 SSLSocketDataProvider ssl(ASYNC, OK);
20489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20490
20491 TestCompletionCallback callback1;
20492
20493 auto trans =
20494 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20495
20496 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
20497 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20498
20499 const HttpResponseInfo* response = trans->GetResponseInfo();
20500 EXPECT_EQ(407, response->headers->response_code());
20501
20502 std::string response_data;
20503 rv = ReadTransaction(trans.get(), &response_data);
20504 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
20505
20506 // No NEL report is generated for the 407.
20507 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20508
20509 TestCompletionCallback callback2;
20510
20511 rv =
20512 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20513 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20514
20515 response = trans->GetResponseInfo();
20516 EXPECT_EQ(200, response->headers->response_code());
20517
20518 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20519 EXPECT_EQ("hello", response_data);
20520
20521 trans.reset();
20522
20523 // No NEL report is generated because we are behind a proxy.
20524 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20525}
20526
Douglas Creageref5eecdc2018-11-09 20:50:3620527TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20528 ReportContainsUploadDepth) {
20529 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4220530 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3620531 RequestPolicy();
20532 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220533 const NetworkErrorLoggingService::RequestDetails& error =
20534 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3620535 EXPECT_EQ(7, error.reporting_upload_depth);
20536}
20537
Lily Chenfec60d92019-01-24 01:16:4220538TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
20539 std::string extra_header_string = extra_headers_.ToString();
20540 static const base::TimeDelta kSleepDuration =
20541 base::TimeDelta::FromMilliseconds(10);
20542
20543 std::vector<MockWrite> data_writes = {
20544 MockWrite(ASYNC, 0,
20545 "GET / HTTP/1.1\r\n"
20546 "Host: www.example.org\r\n"
20547 "Connection: keep-alive\r\n"),
20548 MockWrite(ASYNC, 1, extra_header_string.data()),
20549 };
20550
20551 std::vector<MockRead> data_reads = {
20552 // Write one byte of the status line, followed by a pause.
20553 MockRead(ASYNC, 2, "H"),
20554 MockRead(ASYNC, ERR_IO_PENDING, 3),
20555 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
20556 MockRead(ASYNC, 5, "hello world"),
20557 MockRead(SYNCHRONOUS, OK, 6),
20558 };
20559
20560 SequencedSocketData data(data_reads, data_writes);
20561 session_deps_.socket_factory->AddSocketDataProvider(&data);
20562
20563 SSLSocketDataProvider ssl(ASYNC, OK);
20564 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20565
20566 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20567
20568 auto trans =
20569 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20570
20571 TestCompletionCallback callback;
20572
20573 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20574 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20575
20576 data.RunUntilPaused();
20577 ASSERT_TRUE(data.IsPaused());
20578 FastForwardBy(kSleepDuration);
20579 data.Resume();
20580
20581 EXPECT_THAT(callback.GetResult(rv), IsOk());
20582
20583 std::string response_data;
20584 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20585 EXPECT_EQ("hello world", response_data);
20586
20587 trans.reset();
20588
Douglas Creageref5eecdc2018-11-09 20:50:3620589 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220590
20591 CheckReport(0 /* index */, 200 /* status_code */, OK);
20592
20593 const NetworkErrorLoggingService::RequestDetails& error =
20594 network_error_logging_service()->errors()[0];
20595
20596 // Sanity-check elapsed time in error report
20597 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3620598}
Lily Chenfec60d92019-01-24 01:16:4220599
Douglas Creager3cb042052018-11-06 23:08:5220600#endif // BUILDFLAG(ENABLE_REPORTING)
20601
Batalov Vladislava4e97a502019-04-11 15:35:2320602TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
20603 HttpRequestInfo request;
20604 request.method = "GET";
20605 request.url = GURL("http://example.org/");
20606
20607 request.load_flags = LOAD_ONLY_FROM_CACHE;
20608
20609 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20610 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
20611 TestCompletionCallback callback1;
20612 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
20613
20614 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
20615}
20616
Steven Valdez1c1859172019-04-10 15:33:2820617TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
David Benjaminbae08ba2019-10-18 21:06:1520618 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820619 HttpRequestInfo request;
20620 request.method = "GET";
20621 request.url = GURL("https://www.example.org/");
20622 request.traffic_annotation =
20623 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20624
20625 MockWrite data_writes[] = {
20626 MockWrite("GET / HTTP/1.1\r\n"
20627 "Host: www.example.org\r\n"
20628 "Connection: keep-alive\r\n\r\n"),
20629 };
20630
Steven Valdez1c1859172019-04-10 15:33:2820631 MockRead data_reads[] = {
20632 MockRead("HTTP/1.1 200 OK\r\n"),
20633 MockRead("Content-Length: 1\r\n\r\n"),
20634 MockRead(SYNCHRONOUS, "1"),
20635 };
20636
20637 StaticSocketDataProvider data(data_reads, data_writes);
20638 session_deps_.socket_factory->AddSocketDataProvider(&data);
20639 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520640 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820641 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520642 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820643 session_deps_.enable_early_data = true;
20644 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20645
20646 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20647
20648 TestCompletionCallback callback;
20649 auto trans =
20650 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20651
David Benjaminbae08ba2019-10-18 21:06:1520652 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820653 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20654 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20655
20656 rv = callback.WaitForResult();
20657 EXPECT_THAT(rv, IsOk());
20658
20659 const HttpResponseInfo* response = trans->GetResponseInfo();
20660 ASSERT_TRUE(response);
20661 ASSERT_TRUE(response->headers);
20662 EXPECT_EQ(200, response->headers->response_code());
20663 EXPECT_EQ(1, response->headers->GetContentLength());
20664
20665 // Check that ConfirmHandshake wasn't called.
20666 ASSERT_FALSE(ssl.ConfirmDataConsumed());
20667 ASSERT_TRUE(ssl.WriteBeforeConfirm());
20668
David Benjaminbae08ba2019-10-18 21:06:1520669 // The handshake time should include the time it took to run Connect(), but
20670 // not ConfirmHandshake().
20671 LoadTimingInfo load_timing_info;
20672 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
20673 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
20674 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
20675 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
20676 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
20677
Steven Valdez1c1859172019-04-10 15:33:2820678 trans.reset();
20679
20680 session->CloseAllConnections();
20681}
20682
20683TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1520684 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820685 HttpRequestInfo request;
20686 request.method = "POST";
20687 request.url = GURL("https://www.example.org/");
20688 request.traffic_annotation =
20689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20690
20691 MockWrite data_writes[] = {
20692 MockWrite(SYNCHRONOUS,
20693 "POST / HTTP/1.1\r\n"
20694 "Host: www.example.org\r\n"
20695 "Connection: keep-alive\r\n"
20696 "Content-Length: 0\r\n\r\n"),
20697 };
20698
Steven Valdez1c1859172019-04-10 15:33:2820699 MockRead data_reads[] = {
20700 MockRead("HTTP/1.1 200 OK\r\n"),
20701 MockRead("Content-Length: 1\r\n\r\n"),
20702 MockRead(SYNCHRONOUS, "1"),
20703 };
20704
20705 StaticSocketDataProvider data(data_reads, data_writes);
20706 session_deps_.socket_factory->AddSocketDataProvider(&data);
20707 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520708 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820709 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520710 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820711 session_deps_.enable_early_data = true;
20712 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20713
20714 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20715
20716 TestCompletionCallback callback;
20717 auto trans =
20718 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20719
David Benjaminbae08ba2019-10-18 21:06:1520720 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820721 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20722 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20723
20724 rv = callback.WaitForResult();
20725 EXPECT_THAT(rv, IsOk());
20726
20727 const HttpResponseInfo* response = trans->GetResponseInfo();
20728 ASSERT_TRUE(response);
20729 ASSERT_TRUE(response->headers);
20730 EXPECT_EQ(200, response->headers->response_code());
20731 EXPECT_EQ(1, response->headers->GetContentLength());
20732
20733 // Check that the Write didn't get called before ConfirmHandshake completed.
20734 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20735
David Benjaminbae08ba2019-10-18 21:06:1520736 // The handshake time should include the time it took to run Connect(), but
20737 // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
20738 // assume the connection did not negotiate 0-RTT or the handshake was already
20739 // confirmed.
20740 LoadTimingInfo load_timing_info;
20741 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
20742 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
20743 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
20744 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
20745 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
20746
Steven Valdez1c1859172019-04-10 15:33:2820747 trans.reset();
20748
20749 session->CloseAllConnections();
20750}
20751
20752TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
20753 HttpRequestInfo request;
20754 request.method = "POST";
20755 request.url = GURL("https://www.example.org/");
20756 request.traffic_annotation =
20757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20758
20759 MockWrite data_writes[] = {
20760 MockWrite(ASYNC,
20761 "POST / HTTP/1.1\r\n"
20762 "Host: www.example.org\r\n"
20763 "Connection: keep-alive\r\n"
20764 "Content-Length: 0\r\n\r\n"),
20765 };
20766
Steven Valdez1c1859172019-04-10 15:33:2820767 MockRead data_reads[] = {
20768 MockRead("HTTP/1.1 200 OK\r\n"),
20769 MockRead("Content-Length: 1\r\n\r\n"),
20770 MockRead(SYNCHRONOUS, "1"),
20771 };
20772
20773 StaticSocketDataProvider data(data_reads, data_writes);
20774 session_deps_.socket_factory->AddSocketDataProvider(&data);
20775 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20776 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20777 session_deps_.enable_early_data = true;
20778 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20779
20780 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20781
20782 TestCompletionCallback callback;
20783 auto trans =
20784 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20785
20786 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20787 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20788
20789 rv = callback.WaitForResult();
20790 EXPECT_THAT(rv, IsOk());
20791
20792 const HttpResponseInfo* response = trans->GetResponseInfo();
20793 ASSERT_TRUE(response);
20794 ASSERT_TRUE(response->headers);
20795 EXPECT_EQ(200, response->headers->response_code());
20796 EXPECT_EQ(1, response->headers->GetContentLength());
20797
20798 // Check that the Write didn't get called before ConfirmHandshake completed.
20799 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20800
20801 trans.reset();
20802
20803 session->CloseAllConnections();
20804}
20805
20806TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1520807 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2820808 HttpRequestInfo request;
20809 request.method = "POST";
20810 request.url = GURL("https://www.example.org/");
20811 request.traffic_annotation =
20812 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20813
20814 MockWrite data_writes[] = {
20815 MockWrite(SYNCHRONOUS,
20816 "POST / HTTP/1.1\r\n"
20817 "Host: www.example.org\r\n"
20818 "Connection: keep-alive\r\n"
20819 "Content-Length: 0\r\n\r\n"),
20820 };
20821
Steven Valdez1c1859172019-04-10 15:33:2820822 MockRead data_reads[] = {
20823 MockRead("HTTP/1.1 200 OK\r\n"),
20824 MockRead("Content-Length: 1\r\n\r\n"),
20825 MockRead(SYNCHRONOUS, "1"),
20826 };
20827
20828 StaticSocketDataProvider data(data_reads, data_writes);
20829 session_deps_.socket_factory->AddSocketDataProvider(&data);
20830 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1520831 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820832 ssl.confirm = MockConfirm(ASYNC, OK);
David Benjaminbae08ba2019-10-18 21:06:1520833 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2820834 session_deps_.enable_early_data = true;
20835 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20836
20837 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20838
20839 TestCompletionCallback callback;
20840 auto trans =
20841 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20842
David Benjaminbae08ba2019-10-18 21:06:1520843 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2820844 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20845 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20846
20847 rv = callback.WaitForResult();
20848 EXPECT_THAT(rv, IsOk());
20849
20850 const HttpResponseInfo* response = trans->GetResponseInfo();
20851 ASSERT_TRUE(response);
20852 ASSERT_TRUE(response->headers);
20853 EXPECT_EQ(200, response->headers->response_code());
20854 EXPECT_EQ(1, response->headers->GetContentLength());
20855
20856 // Check that the Write didn't get called before ConfirmHandshake completed.
20857 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20858
David Benjaminbae08ba2019-10-18 21:06:1520859 // The handshake time should include the time it took to run Connect() and
20860 // ConfirmHandshake().
20861 LoadTimingInfo load_timing_info;
20862 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
20863 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
20864 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
20865 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
20866 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
20867 start_time + 2 * kDelay);
20868
Steven Valdez1c1859172019-04-10 15:33:2820869 trans.reset();
20870
20871 session->CloseAllConnections();
20872}
20873
20874TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
20875 HttpRequestInfo request;
20876 request.method = "POST";
20877 request.url = GURL("https://www.example.org/");
20878 request.traffic_annotation =
20879 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20880
20881 MockWrite data_writes[] = {
20882 MockWrite(ASYNC,
20883 "POST / HTTP/1.1\r\n"
20884 "Host: www.example.org\r\n"
20885 "Connection: keep-alive\r\n"
20886 "Content-Length: 0\r\n\r\n"),
20887 };
20888
Steven Valdez1c1859172019-04-10 15:33:2820889 MockRead data_reads[] = {
20890 MockRead("HTTP/1.1 200 OK\r\n"),
20891 MockRead("Content-Length: 1\r\n\r\n"),
20892 MockRead(SYNCHRONOUS, "1"),
20893 };
20894
20895 StaticSocketDataProvider data(data_reads, data_writes);
20896 session_deps_.socket_factory->AddSocketDataProvider(&data);
20897 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20898 ssl.confirm = MockConfirm(ASYNC, OK);
20899 session_deps_.enable_early_data = true;
20900 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20901
20902 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20903
20904 TestCompletionCallback callback;
20905 auto trans =
20906 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20907
20908 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20909 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20910
20911 rv = callback.WaitForResult();
20912 EXPECT_THAT(rv, IsOk());
20913
20914 const HttpResponseInfo* response = trans->GetResponseInfo();
20915 ASSERT_TRUE(response);
20916 ASSERT_TRUE(response->headers);
20917 EXPECT_EQ(200, response->headers->response_code());
20918 EXPECT_EQ(1, response->headers->GetContentLength());
20919
20920 // Check that the Write didn't get called before ConfirmHandshake completed.
20921 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20922
20923 trans.reset();
20924
20925 session->CloseAllConnections();
20926}
20927
David Benjaminfb976932019-05-15 13:39:1520928// 0-RTT rejects are handled at HttpNetworkTransaction.
20929TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
20930 enum class RejectType {
20931 kRead,
20932 kWrite,
20933 kConfirm,
20934 };
20935
20936 for (RejectType type :
20937 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
20938 SCOPED_TRACE(static_cast<int>(type));
20939 for (Error reject_error :
20940 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
20941 SCOPED_TRACE(reject_error);
20942 session_deps_.socket_factory =
20943 std::make_unique<MockClientSocketFactory>();
20944
20945 HttpRequestInfo request;
20946 request.method = type == RejectType::kConfirm ? "POST" : "GET";
20947 request.url = GURL("https://www.example.org/");
20948 request.traffic_annotation =
20949 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20950
20951 // The first request fails.
20952 std::vector<MockWrite> data1_writes;
20953 std::vector<MockRead> data1_reads;
20954 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
20955 switch (type) {
20956 case RejectType::kRead:
20957 data1_writes.emplace_back(
20958 "GET / HTTP/1.1\r\n"
20959 "Host: www.example.org\r\n"
20960 "Connection: keep-alive\r\n\r\n");
20961 data1_reads.emplace_back(ASYNC, reject_error);
20962 // Cause ConfirmHandshake to hang (it should not be called).
20963 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20964 break;
20965 case RejectType::kWrite:
20966 data1_writes.emplace_back(ASYNC, reject_error);
20967 // Cause ConfirmHandshake to hang (it should not be called).
20968 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20969 break;
20970 case RejectType::kConfirm:
20971 // The request never gets far enough to read or write.
20972 ssl1.confirm = MockConfirm(ASYNC, reject_error);
20973 break;
20974 }
20975
20976 StaticSocketDataProvider data1(data1_reads, data1_writes);
20977 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20978 session_deps_.enable_early_data = true;
20979 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20980
20981 // The retry succeeds.
20982 //
20983 // TODO(https://crbug.com/950705): If |reject_error| is
20984 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
20985 MockWrite data2_writes[] = {
20986 request.method == "POST"
20987 ? MockWrite("POST / HTTP/1.1\r\n"
20988 "Host: www.example.org\r\n"
20989 "Connection: keep-alive\r\n"
20990 "Content-Length: 0\r\n\r\n")
20991 : MockWrite("GET / HTTP/1.1\r\n"
20992 "Host: www.example.org\r\n"
20993 "Connection: keep-alive\r\n\r\n"),
20994 };
20995
20996 MockRead data2_reads[] = {
20997 MockRead("HTTP/1.1 200 OK\r\n"),
20998 MockRead("Content-Length: 1\r\n\r\n"),
20999 MockRead(SYNCHRONOUS, "1"),
21000 };
21001
21002 StaticSocketDataProvider data2(data2_reads, data2_writes);
21003 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21004 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
21005 ssl2.confirm = MockConfirm(ASYNC, OK);
21006 session_deps_.enable_early_data = true;
21007 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21008
21009 std::unique_ptr<HttpNetworkSession> session(
21010 CreateSession(&session_deps_));
21011
21012 TestCompletionCallback callback;
21013 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21014 session.get());
21015
21016 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21017 NetLogWithSource())),
21018 IsOk());
21019
21020 const HttpResponseInfo* response = trans->GetResponseInfo();
21021 ASSERT_TRUE(response);
21022 ASSERT_TRUE(response->headers);
21023 EXPECT_EQ(200, response->headers->response_code());
21024 EXPECT_EQ(1, response->headers->GetContentLength());
21025 }
21026 }
21027}
21028
Steven Valdez1c1859172019-04-10 15:33:2821029TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
21030 HttpRequestInfo request;
21031 request.method = "POST";
21032 request.url = GURL("https://www.example.org/");
21033 request.traffic_annotation =
21034 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21035
21036 MockWrite data_writes[] = {
21037 MockWrite("POST / HTTP/1.1\r\n"
21038 "Host: www.example.org\r\n"
21039 "Connection: keep-alive\r\n"
21040 "Content-Length: 0\r\n\r\n"),
21041 };
21042
Steven Valdez1c1859172019-04-10 15:33:2821043 MockRead data_reads[] = {
21044 MockRead("HTTP/1.1 200 OK\r\n"),
21045 MockRead("Content-Length: 1\r\n\r\n"),
21046 MockRead(SYNCHRONOUS, "1"),
21047 };
21048
21049 StaticSocketDataProvider data(data_reads, data_writes);
21050 session_deps_.socket_factory->AddSocketDataProvider(&data);
21051 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21052 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
21053 session_deps_.enable_early_data = true;
21054 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21055
21056 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21057
21058 TestCompletionCallback callback;
21059 auto trans =
21060 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21061
21062 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21064
21065 rv = callback.WaitForResult();
21066 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21067
21068 // Check that the Write didn't get called before ConfirmHandshake completed.
21069 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21070
21071 trans.reset();
21072
21073 session->CloseAllConnections();
21074}
21075
21076TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
21077 HttpRequestInfo request;
21078 request.method = "POST";
21079 request.url = GURL("https://www.example.org/");
21080 request.traffic_annotation =
21081 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21082
21083 MockWrite data_writes[] = {
21084 MockWrite("POST / HTTP/1.1\r\n"
21085 "Host: www.example.org\r\n"
21086 "Connection: keep-alive\r\n"
21087 "Content-Length: 0\r\n\r\n"),
21088 };
21089
Steven Valdez1c1859172019-04-10 15:33:2821090 MockRead data_reads[] = {
21091 MockRead("HTTP/1.1 200 OK\r\n"),
21092 MockRead("Content-Length: 1\r\n\r\n"),
21093 MockRead(SYNCHRONOUS, "1"),
21094 };
21095
21096 StaticSocketDataProvider data(data_reads, data_writes);
21097 session_deps_.socket_factory->AddSocketDataProvider(&data);
21098 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21099 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
21100 session_deps_.enable_early_data = true;
21101 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21102
21103 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21104
21105 TestCompletionCallback callback;
21106 auto trans =
21107 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21108
21109 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21110 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21111
21112 rv = callback.WaitForResult();
21113 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21114
21115 // Check that the Write didn't get called before ConfirmHandshake completed.
21116 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21117
21118 trans.reset();
21119
21120 session->CloseAllConnections();
21121}
21122
David Benjamin2eb827f2019-04-29 18:31:0421123// Test the proxy and origin server each requesting both TLS client certificates
21124// and HTTP auth. This is a regression test for https://crbug.com/946406.
21125TEST_F(HttpNetworkTransactionTest, AuthEverything) {
21126 // Note these hosts must match the CheckBasic*Auth() functions.
21127 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21128 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21129
21130 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21131 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21132
21133 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21134 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21135 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21136 ASSERT_TRUE(identity_proxy);
21137
21138 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21139 cert_request_info_origin->host_and_port =
21140 HostPortPair("www.example.org", 443);
21141
21142 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21143 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21144 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21145 ASSERT_TRUE(identity_origin);
21146
21147 HttpRequestInfo request;
21148 request.method = "GET";
21149 request.url = GURL("https://www.example.org/");
21150 request.traffic_annotation =
21151 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21152
David Benjamin7ebab032019-04-30 21:51:3021153 // First, the client connects to the proxy, which requests a client
21154 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421155 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21156 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21157 ssl_proxy1.expected_send_client_cert = false;
David Benjamin2eb827f2019-04-29 18:31:0421158 StaticSocketDataProvider data1;
21159 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021160 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421161
David Benjamin7ebab032019-04-30 21:51:3021162 // The client responds with a certificate on a new connection. The handshake
21163 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421164 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21165 ssl_proxy2.expected_send_client_cert = true;
21166 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021167 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421168 std::vector<MockWrite> mock_writes2;
21169 std::vector<MockRead> mock_reads2;
21170 mock_writes2.emplace_back(
21171 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21172 "Host: www.example.org:443\r\n"
21173 "Proxy-Connection: keep-alive\r\n\r\n");
21174 mock_reads2.emplace_back(
21175 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21176 "Content-Length: 0\r\n"
21177 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021178 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0421179 mock_writes2.emplace_back(
21180 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21181 "Host: www.example.org:443\r\n"
21182 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021183 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421184 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21185 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21186 // The origin requests client certificates.
21187 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21188 ssl_origin2.cert_request_info = cert_request_info_origin.get();
David Benjamin2eb827f2019-04-29 18:31:0421189 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21190 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021191 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21192 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0421193
David Benjamin7ebab032019-04-30 21:51:3021194 // The client responds to the origin client certificate request on a new
21195 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421196 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21197 ssl_proxy3.expected_send_client_cert = true;
21198 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
David Benjamin2eb827f2019-04-29 18:31:0421199 std::vector<MockWrite> mock_writes3;
21200 std::vector<MockRead> mock_reads3;
21201 mock_writes3.emplace_back(
21202 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21203 "Host: www.example.org:443\r\n"
21204 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021205 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421206 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21207 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21208 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
21209 ssl_origin3.expected_send_client_cert = true;
21210 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021211 // The client sends the origin HTTP request, which results in another HTTP
21212 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0421213 mock_writes3.emplace_back(
21214 "GET / HTTP/1.1\r\n"
21215 "Host: www.example.org\r\n"
21216 "Connection: keep-alive\r\n\r\n");
21217 mock_reads3.emplace_back(
21218 "HTTP/1.1 401 Unauthorized\r\n"
21219 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21220 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021221 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421222 mock_writes3.emplace_back(
21223 "GET / HTTP/1.1\r\n"
21224 "Host: www.example.org\r\n"
21225 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021226 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421227 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21228 mock_reads3.emplace_back(
21229 "HTTP/1.1 200 OK\r\n"
21230 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4121231 // The client makes another request. This should reuse the socket with all
21232 // credentials cached.
21233 mock_writes3.emplace_back(
21234 "GET / HTTP/1.1\r\n"
21235 "Host: www.example.org\r\n"
21236 "Connection: keep-alive\r\n"
21237 // Authenticate as user:pass.
21238 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21239 mock_reads3.emplace_back(
21240 "HTTP/1.1 200 OK\r\n"
21241 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0421242 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21243 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021244 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21245 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421246
21247 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21248
21249 // Start the request.
21250 TestCompletionCallback callback;
21251 auto trans =
21252 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21253 int rv = callback.GetResult(
21254 trans->Start(&request, callback.callback(), NetLogWithSource()));
21255
21256 // Handle the proxy client certificate challenge.
21257 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21258 SSLCertRequestInfo* cert_request_info =
21259 trans->GetResponseInfo()->cert_request_info.get();
21260 ASSERT_TRUE(cert_request_info);
21261 EXPECT_TRUE(cert_request_info->is_proxy);
21262 EXPECT_EQ(cert_request_info->host_and_port,
21263 cert_request_info_proxy->host_and_port);
21264 rv = callback.GetResult(trans->RestartWithCertificate(
21265 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21266 callback.callback()));
21267
21268 // Handle the proxy HTTP auth challenge.
21269 ASSERT_THAT(rv, IsOk());
21270 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21271 EXPECT_TRUE(
21272 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21273 rv = callback.GetResult(trans->RestartWithAuth(
21274 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21275 callback.callback()));
21276
21277 // Handle the origin client certificate challenge.
21278 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21279 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21280 ASSERT_TRUE(cert_request_info);
21281 EXPECT_FALSE(cert_request_info->is_proxy);
21282 EXPECT_EQ(cert_request_info->host_and_port,
21283 cert_request_info_origin->host_and_port);
21284 rv = callback.GetResult(trans->RestartWithCertificate(
21285 identity_origin->certificate(), identity_origin->ssl_private_key(),
21286 callback.callback()));
21287
21288 // Handle the origin HTTP auth challenge.
21289 ASSERT_THAT(rv, IsOk());
21290 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21291 EXPECT_TRUE(
21292 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21293 rv = callback.GetResult(trans->RestartWithAuth(
21294 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21295 callback.callback()));
21296
21297 // The request completes.
21298 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021299 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121300
21301 // Make a second request. This time all credentials are cached.
21302 trans =
21303 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21304 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21305 NetLogWithSource())),
21306 IsOk());
21307 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421308}
21309
21310// Test the proxy and origin server each requesting both TLS client certificates
21311// and HTTP auth and each HTTP auth closing the connection. This is a regression
21312// test for https://crbug.com/946406.
21313TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
21314 // Note these hosts must match the CheckBasic*Auth() functions.
21315 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21316 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21317
21318 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21319 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21320
21321 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21322 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21323 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21324 ASSERT_TRUE(identity_proxy);
21325
21326 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21327 cert_request_info_origin->host_and_port =
21328 HostPortPair("www.example.org", 443);
21329
21330 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21331 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21332 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21333 ASSERT_TRUE(identity_origin);
21334
21335 HttpRequestInfo request;
21336 request.method = "GET";
21337 request.url = GURL("https://www.example.org/");
21338 request.traffic_annotation =
21339 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21340
David Benjamin7ebab032019-04-30 21:51:3021341 // First, the client connects to the proxy, which requests a client
21342 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421343 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21344 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21345 ssl_proxy1.expected_send_client_cert = false;
21346 StaticSocketDataProvider data1;
21347 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021348 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421349
David Benjamin7ebab032019-04-30 21:51:3021350 // The client responds with a certificate on a new connection. The handshake
21351 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421352 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21353 ssl_proxy2.expected_send_client_cert = true;
21354 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021355 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421356 std::vector<MockWrite> mock_writes2;
21357 std::vector<MockRead> mock_reads2;
21358 mock_writes2.emplace_back(
21359 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21360 "Host: www.example.org:443\r\n"
21361 "Proxy-Connection: keep-alive\r\n\r\n");
21362 mock_reads2.emplace_back(
21363 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21364 "Content-Length: 0\r\n"
21365 "Proxy-Connection: close\r\n"
21366 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21367 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21368 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021369 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0421370
David Benjamin7ebab032019-04-30 21:51:3021371 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0421372 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21373 ssl_proxy3.expected_send_client_cert = true;
21374 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21375 std::vector<MockWrite> mock_writes3;
21376 std::vector<MockRead> mock_reads3;
21377 mock_writes3.emplace_back(
21378 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21379 "Host: www.example.org:443\r\n"
21380 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021381 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421382 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21383 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21384 // The origin requests client certificates.
21385 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21386 ssl_origin3.cert_request_info = cert_request_info_origin.get();
21387 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21388 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021389 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21390 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421391
David Benjamin7ebab032019-04-30 21:51:3021392 // The client responds to the origin client certificate request on a new
21393 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421394 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
21395 ssl_proxy4.expected_send_client_cert = true;
21396 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
21397 std::vector<MockWrite> mock_writes4;
21398 std::vector<MockRead> mock_reads4;
21399 mock_writes4.emplace_back(
21400 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21401 "Host: www.example.org:443\r\n"
21402 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021403 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421404 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21405 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21406 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
21407 ssl_origin4.expected_send_client_cert = true;
21408 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021409 // The client sends the origin HTTP request, which results in another HTTP
21410 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0421411 mock_writes4.emplace_back(
21412 "GET / HTTP/1.1\r\n"
21413 "Host: www.example.org\r\n"
21414 "Connection: keep-alive\r\n\r\n");
21415 mock_reads4.emplace_back(
21416 "HTTP/1.1 401 Unauthorized\r\n"
21417 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21418 "Connection: close\r\n"
21419 "Content-Length: 0\r\n\r\n");
21420 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
21421 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3021422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
21423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0421424
David Benjamin7ebab032019-04-30 21:51:3021425 // The client retries with credentials on a new connection, and the request
21426 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421427 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
21428 ssl_proxy5.expected_send_client_cert = true;
21429 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
21430 std::vector<MockWrite> mock_writes5;
21431 std::vector<MockRead> mock_reads5;
21432 mock_writes5.emplace_back(
21433 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21434 "Host: www.example.org:443\r\n"
21435 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021436 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421437 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21438 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21439 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
21440 ssl_origin5.expected_send_client_cert = true;
21441 ssl_origin5.expected_client_cert = identity_origin->certificate();
21442 mock_writes5.emplace_back(
21443 "GET / HTTP/1.1\r\n"
21444 "Host: www.example.org\r\n"
21445 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021446 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421447 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21448 mock_reads5.emplace_back(
21449 "HTTP/1.1 200 OK\r\n"
21450 "Connection: close\r\n"
21451 "Content-Length: 0\r\n\r\n");
21452 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
21453 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3021454 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
21455 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0421456
David Benjaminbac8dff2019-08-07 01:30:4121457 // The client makes a second request. This needs yet another connection, but
21458 // all credentials are cached.
21459 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
21460 ssl_proxy6.expected_send_client_cert = true;
21461 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
21462 std::vector<MockWrite> mock_writes6;
21463 std::vector<MockRead> mock_reads6;
21464 mock_writes6.emplace_back(
21465 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21466 "Host: www.example.org:443\r\n"
21467 "Proxy-Connection: keep-alive\r\n"
21468 // Authenticate as proxyuser:proxypass.
21469 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21470 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21471 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
21472 ssl_origin6.expected_send_client_cert = true;
21473 ssl_origin6.expected_client_cert = identity_origin->certificate();
21474 mock_writes6.emplace_back(
21475 "GET / HTTP/1.1\r\n"
21476 "Host: www.example.org\r\n"
21477 "Connection: keep-alive\r\n"
21478 // Authenticate as user:pass.
21479 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21480 mock_reads6.emplace_back(
21481 "HTTP/1.1 200 OK\r\n"
21482 "Connection: close\r\n"
21483 "Content-Length: 0\r\n\r\n");
21484 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
21485 session_deps_.socket_factory->AddSocketDataProvider(&data6);
21486 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
21487 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
21488
David Benjamin2eb827f2019-04-29 18:31:0421489 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21490
21491 // Start the request.
21492 TestCompletionCallback callback;
21493 auto trans =
21494 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21495 int rv = callback.GetResult(
21496 trans->Start(&request, callback.callback(), NetLogWithSource()));
21497
21498 // Handle the proxy client certificate challenge.
21499 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21500 SSLCertRequestInfo* cert_request_info =
21501 trans->GetResponseInfo()->cert_request_info.get();
21502 ASSERT_TRUE(cert_request_info);
21503 EXPECT_TRUE(cert_request_info->is_proxy);
21504 EXPECT_EQ(cert_request_info->host_and_port,
21505 cert_request_info_proxy->host_and_port);
21506 rv = callback.GetResult(trans->RestartWithCertificate(
21507 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21508 callback.callback()));
21509
21510 // Handle the proxy HTTP auth challenge.
21511 ASSERT_THAT(rv, IsOk());
21512 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21513 EXPECT_TRUE(
21514 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21515 rv = callback.GetResult(trans->RestartWithAuth(
21516 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21517 callback.callback()));
21518
21519 // Handle the origin client certificate challenge.
21520 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21521 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21522 ASSERT_TRUE(cert_request_info);
21523 EXPECT_FALSE(cert_request_info->is_proxy);
21524 EXPECT_EQ(cert_request_info->host_and_port,
21525 cert_request_info_origin->host_and_port);
21526 rv = callback.GetResult(trans->RestartWithCertificate(
21527 identity_origin->certificate(), identity_origin->ssl_private_key(),
21528 callback.callback()));
21529
21530 // Handle the origin HTTP auth challenge.
21531 ASSERT_THAT(rv, IsOk());
21532 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21533 EXPECT_TRUE(
21534 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21535 rv = callback.GetResult(trans->RestartWithAuth(
21536 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21537 callback.callback()));
21538
21539 // The request completes.
21540 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021541 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121542
21543 // Make a second request. This time all credentials are cached.
21544 trans =
21545 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21546 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21547 NetLogWithSource())),
21548 IsOk());
21549 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3021550}
21551
21552// Test the proxy requesting HTTP auth and the server requesting TLS client
21553// certificates. This is a regression test for https://crbug.com/946406.
21554TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
21555 // Note these hosts must match the CheckBasic*Auth() functions.
21556 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21557 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21558
21559 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21560 cert_request_info_origin->host_and_port =
21561 HostPortPair("www.example.org", 443);
21562
21563 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21564 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21565 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21566 ASSERT_TRUE(identity_origin);
21567
21568 HttpRequestInfo request;
21569 request.method = "GET";
21570 request.url = GURL("https://www.example.org/");
21571 request.traffic_annotation =
21572 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21573
21574 // The client connects to the proxy. The handshake succeeds.
21575 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21576 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
21577 std::vector<MockWrite> mock_writes1;
21578 std::vector<MockRead> mock_reads1;
21579 mock_writes1.emplace_back(
21580 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21581 "Host: www.example.org:443\r\n"
21582 "Proxy-Connection: keep-alive\r\n\r\n");
21583 mock_reads1.emplace_back(
21584 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21585 "Content-Length: 0\r\n"
21586 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21587 // The client retries with credentials, and the request finally succeeds.
21588 mock_writes1.emplace_back(
21589 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21590 "Host: www.example.org:443\r\n"
21591 "Proxy-Connection: keep-alive\r\n"
21592 // Authenticate as proxyuser:proxypass.
21593 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21594 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21595 // The origin requests client certificates.
21596 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21597 ssl_origin1.cert_request_info = cert_request_info_origin.get();
21598 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
21599 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21601 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21602
21603 // The client responds to the origin client certificate request on a new
21604 // connection.
21605 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21606 std::vector<MockWrite> mock_writes2;
21607 std::vector<MockRead> mock_reads2;
21608 mock_writes2.emplace_back(
21609 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21610 "Host: www.example.org:443\r\n"
21611 "Proxy-Connection: keep-alive\r\n"
21612 // Authenticate as proxyuser:proxypass.
21613 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21614 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21615 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
21616 ssl_origin2.expected_send_client_cert = true;
21617 ssl_origin2.expected_client_cert = identity_origin->certificate();
21618 // The client sends the origin HTTP request, which succeeds.
21619 mock_writes2.emplace_back(
21620 "GET / HTTP/1.1\r\n"
21621 "Host: www.example.org\r\n"
21622 "Connection: keep-alive\r\n\r\n");
21623 mock_reads2.emplace_back(
21624 "HTTP/1.1 200 OK\r\n"
21625 "Content-Length: 0\r\n\r\n");
21626 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21627 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21628 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21629 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
21630
21631 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21632
21633 // Start the request.
21634 TestCompletionCallback callback;
21635 auto trans =
21636 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21637 int rv = callback.GetResult(
21638 trans->Start(&request, callback.callback(), NetLogWithSource()));
21639
21640 // Handle the proxy HTTP auth challenge.
21641 ASSERT_THAT(rv, IsOk());
21642 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21643 EXPECT_TRUE(
21644 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21645 rv = callback.GetResult(trans->RestartWithAuth(
21646 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21647 callback.callback()));
21648
21649 // Handle the origin client certificate challenge.
21650 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21651 SSLCertRequestInfo* cert_request_info =
21652 trans->GetResponseInfo()->cert_request_info.get();
21653 ASSERT_TRUE(cert_request_info);
21654 EXPECT_FALSE(cert_request_info->is_proxy);
21655 EXPECT_EQ(cert_request_info->host_and_port,
21656 cert_request_info_origin->host_and_port);
21657 rv = callback.GetResult(trans->RestartWithCertificate(
21658 identity_origin->certificate(), identity_origin->ssl_private_key(),
21659 callback.callback()));
21660
21661 // The request completes.
21662 ASSERT_THAT(rv, IsOk());
21663 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421664}
21665
David Benjamin6e673a82019-04-30 22:52:5821666// Test that socket reuse works with client certificates.
21667TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
21668 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
21669 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
21670
21671 std::unique_ptr<FakeClientCertIdentity> identity =
21672 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21673 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21674 ASSERT_TRUE(identity);
21675
21676 HttpRequestInfo request1;
21677 request1.method = "GET";
21678 request1.url = GURL("https://www.example.org/a");
21679 request1.traffic_annotation =
21680 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21681
21682 HttpRequestInfo request2;
21683 request2.method = "GET";
21684 request2.url = GURL("https://www.example.org/b");
21685 request2.traffic_annotation =
21686 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21687
21688 // The first connection results in a client certificate request.
21689 StaticSocketDataProvider data1;
21690 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21691 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21692 ssl1.cert_request_info = cert_request_info.get();
21693 ssl1.expected_send_client_cert = false;
21694 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21695
21696 // The second connection succeeds and is usable for both requests.
21697 MockWrite mock_writes[] = {
21698 MockWrite("GET /a HTTP/1.1\r\n"
21699 "Host: www.example.org\r\n"
21700 "Connection: keep-alive\r\n\r\n"),
21701 MockWrite("GET /b HTTP/1.1\r\n"
21702 "Host: www.example.org\r\n"
21703 "Connection: keep-alive\r\n\r\n"),
21704 };
21705 MockRead mock_reads[] = {
21706 MockRead("HTTP/1.1 200 OK\r\n"
21707 "Content-Length: 0\r\n\r\n"),
21708 MockRead("HTTP/1.1 200 OK\r\n"
21709 "Content-Length: 0\r\n\r\n"),
21710 };
21711 StaticSocketDataProvider data2(mock_reads, mock_writes);
21712 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21713 SSLSocketDataProvider ssl2(ASYNC, OK);
21714 ssl2.expected_send_client_cert = true;
21715 ssl2.expected_client_cert = identity->certificate();
21716 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21717
21718 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21719
21720 // Start the first request. It succeeds after providing client certificates.
21721 TestCompletionCallback callback;
21722 auto trans =
21723 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21724 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
21725 NetLogWithSource())),
21726 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21727
21728 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
21729 ASSERT_TRUE(info);
21730 EXPECT_FALSE(info->is_proxy);
21731 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
21732
21733 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
21734 identity->certificate(), identity->ssl_private_key(),
21735 callback.callback())),
21736 IsOk());
21737 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21738
21739 // Make the second request. It completes without requesting client
21740 // certificates.
21741 trans =
21742 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21743 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
21744 NetLogWithSource())),
21745 IsOk());
21746 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21747}
21748
Matt Menke166443c2019-05-24 18:45:5921749// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
21750// sequence with two different NetworkIsolationKeys, the first and last have the
21751// same key, the second a different one. Checks that the requests are
21752// partitioned across sockets as expected.
21753TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2721754 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21755 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21756 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21757 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5921758
21759 for (bool partition_connections : {false, true}) {
21760 SCOPED_TRACE(partition_connections);
21761
21762 base::test::ScopedFeatureList feature_list;
21763 if (partition_connections) {
21764 feature_list.InitAndEnableFeature(
21765 features::kPartitionConnectionsByNetworkIsolationKey);
21766 } else {
21767 feature_list.InitAndDisableFeature(
21768 features::kPartitionConnectionsByNetworkIsolationKey);
21769 }
21770
21771 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21772
21773 // Reads and writes for the unpartitioned case, where only one socket is
21774 // used.
21775
21776 const MockWrite kUnpartitionedWrites[] = {
21777 MockWrite("GET /1 HTTP/1.1\r\n"
21778 "Host: foo.test\r\n"
21779 "Connection: keep-alive\r\n\r\n"),
21780 MockWrite("GET /2 HTTP/1.1\r\n"
21781 "Host: foo.test\r\n"
21782 "Connection: keep-alive\r\n\r\n"),
21783 MockWrite("GET /3 HTTP/1.1\r\n"
21784 "Host: foo.test\r\n"
21785 "Connection: keep-alive\r\n\r\n"),
21786 };
21787
21788 const MockRead kUnpartitionedReads[] = {
21789 MockRead("HTTP/1.1 200 OK\r\n"
21790 "Connection: keep-alive\r\n"
21791 "Content-Length: 1\r\n\r\n"
21792 "1"),
21793 MockRead("HTTP/1.1 200 OK\r\n"
21794 "Connection: keep-alive\r\n"
21795 "Content-Length: 1\r\n\r\n"
21796 "2"),
21797 MockRead("HTTP/1.1 200 OK\r\n"
21798 "Connection: keep-alive\r\n"
21799 "Content-Length: 1\r\n\r\n"
21800 "3"),
21801 };
21802
21803 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
21804 kUnpartitionedWrites);
21805
21806 // Reads and writes for the partitioned case, where two sockets are used.
21807
21808 const MockWrite kPartitionedWrites1[] = {
21809 MockWrite("GET /1 HTTP/1.1\r\n"
21810 "Host: foo.test\r\n"
21811 "Connection: keep-alive\r\n\r\n"),
21812 MockWrite("GET /3 HTTP/1.1\r\n"
21813 "Host: foo.test\r\n"
21814 "Connection: keep-alive\r\n\r\n"),
21815 };
21816
21817 const MockRead kPartitionedReads1[] = {
21818 MockRead("HTTP/1.1 200 OK\r\n"
21819 "Connection: keep-alive\r\n"
21820 "Content-Length: 1\r\n\r\n"
21821 "1"),
21822 MockRead("HTTP/1.1 200 OK\r\n"
21823 "Connection: keep-alive\r\n"
21824 "Content-Length: 1\r\n\r\n"
21825 "3"),
21826 };
21827
21828 const MockWrite kPartitionedWrites2[] = {
21829 MockWrite("GET /2 HTTP/1.1\r\n"
21830 "Host: foo.test\r\n"
21831 "Connection: keep-alive\r\n\r\n"),
21832 };
21833
21834 const MockRead kPartitionedReads2[] = {
21835 MockRead("HTTP/1.1 200 OK\r\n"
21836 "Connection: keep-alive\r\n"
21837 "Content-Length: 1\r\n\r\n"
21838 "2"),
21839 };
21840
21841 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
21842 kPartitionedWrites1);
21843 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
21844 kPartitionedWrites2);
21845
21846 if (partition_connections) {
21847 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21848 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21849 } else {
21850 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
21851 }
21852
21853 TestCompletionCallback callback;
21854 HttpRequestInfo request1;
21855 request1.method = "GET";
21856 request1.url = GURL("http://foo.test/1");
21857 request1.traffic_annotation =
21858 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21859 request1.network_isolation_key = network_isolation_key1;
21860 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21861 session.get());
21862 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21863 EXPECT_THAT(callback.GetResult(rv), IsOk());
21864 std::string response_data1;
21865 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21866 EXPECT_EQ("1", response_data1);
21867 trans1.reset();
21868
21869 HttpRequestInfo request2;
21870 request2.method = "GET";
21871 request2.url = GURL("http://foo.test/2");
21872 request2.traffic_annotation =
21873 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21874 request2.network_isolation_key = network_isolation_key2;
21875 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21876 session.get());
21877 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21878 EXPECT_THAT(callback.GetResult(rv), IsOk());
21879 std::string response_data2;
21880 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21881 EXPECT_EQ("2", response_data2);
21882 trans2.reset();
21883
21884 HttpRequestInfo request3;
21885 request3.method = "GET";
21886 request3.url = GURL("http://foo.test/3");
21887 request3.traffic_annotation =
21888 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21889 request3.network_isolation_key = network_isolation_key1;
21890 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21891 session.get());
21892 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21893 EXPECT_THAT(callback.GetResult(rv), IsOk());
21894 std::string response_data3;
21895 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21896 EXPECT_EQ("3", response_data3);
21897 trans3.reset();
21898 }
21899}
21900
Matt Menkeae58eeb2019-05-24 21:09:5021901TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2721902 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21903 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21904 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21905 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5021906
21907 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
21908 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
21909 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
21910 // the same way as the HTTP over H2 proxy case.
21911 for (bool use_proxy : {false, true}) {
21912 SCOPED_TRACE(use_proxy);
21913 if (use_proxy) {
21914 session_deps_.proxy_resolution_service =
21915 ProxyResolutionService::CreateFixedFromPacResult(
21916 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
21917 } else {
21918 session_deps_.proxy_resolution_service =
21919 ProxyResolutionService::CreateDirect();
21920 }
21921 const char* url1 = nullptr;
21922 const char* url2 = nullptr;
21923 const char* url3 = nullptr;
21924 if (use_proxy) {
21925 url1 = "http://foo.test/1";
21926 url2 = "http://foo.test/2";
21927 url3 = "http://foo.test/3";
21928 } else {
21929 url1 = "https://foo.test/1";
21930 url2 = "https://foo.test/2";
21931 url3 = "https://foo.test/3";
21932 }
21933
21934 for (bool partition_connections : {false, true}) {
21935 SCOPED_TRACE(partition_connections);
21936
21937 base::test::ScopedFeatureList feature_list;
21938 if (partition_connections) {
21939 feature_list.InitAndEnableFeature(
21940 features::kPartitionConnectionsByNetworkIsolationKey);
21941 } else {
21942 feature_list.InitAndDisableFeature(
21943 features::kPartitionConnectionsByNetworkIsolationKey);
21944 }
21945
21946 std::unique_ptr<HttpNetworkSession> session(
21947 CreateSession(&session_deps_));
21948
21949 // Reads and writes for the unpartitioned case, where only one socket is
21950 // used.
21951
21952 SpdyTestUtil spdy_util;
21953 spdy::SpdySerializedFrame unpartitioned_req1(
21954 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
21955 spdy::SpdySerializedFrame unpartitioned_response1(
21956 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
21957 spdy::SpdySerializedFrame unpartitioned_body1(
21958 spdy_util.ConstructSpdyDataFrame(1, "1", true));
21959 spdy_util.UpdateWithStreamDestruction(1);
21960
21961 spdy::SpdySerializedFrame unpartitioned_req2(
21962 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
21963 spdy::SpdySerializedFrame unpartitioned_response2(
21964 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
21965 spdy::SpdySerializedFrame unpartitioned_body2(
21966 spdy_util.ConstructSpdyDataFrame(3, "2", true));
21967 spdy_util.UpdateWithStreamDestruction(3);
21968
21969 spdy::SpdySerializedFrame unpartitioned_req3(
21970 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
21971 spdy::SpdySerializedFrame unpartitioned_response3(
21972 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
21973 spdy::SpdySerializedFrame unpartitioned_body3(
21974 spdy_util.ConstructSpdyDataFrame(5, "3", true));
21975
21976 const MockWrite kUnpartitionedWrites[] = {
21977 CreateMockWrite(unpartitioned_req1, 0),
21978 CreateMockWrite(unpartitioned_req2, 3),
21979 CreateMockWrite(unpartitioned_req3, 6),
21980 };
21981
21982 const MockRead kUnpartitionedReads[] = {
21983 CreateMockRead(unpartitioned_response1, 1),
21984 CreateMockRead(unpartitioned_body1, 2),
21985 CreateMockRead(unpartitioned_response2, 4),
21986 CreateMockRead(unpartitioned_body2, 5),
21987 CreateMockRead(unpartitioned_response3, 7),
21988 CreateMockRead(unpartitioned_body3, 8),
21989 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
21990 };
21991
21992 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
21993 kUnpartitionedWrites);
21994
21995 // Reads and writes for the partitioned case, where two sockets are used.
21996
21997 SpdyTestUtil spdy_util2;
21998 spdy::SpdySerializedFrame partitioned_req1(
21999 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
22000 spdy::SpdySerializedFrame partitioned_response1(
22001 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
22002 spdy::SpdySerializedFrame partitioned_body1(
22003 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
22004 spdy_util2.UpdateWithStreamDestruction(1);
22005
22006 spdy::SpdySerializedFrame partitioned_req3(
22007 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
22008 spdy::SpdySerializedFrame partitioned_response3(
22009 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
22010 spdy::SpdySerializedFrame partitioned_body3(
22011 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
22012
22013 const MockWrite kPartitionedWrites1[] = {
22014 CreateMockWrite(partitioned_req1, 0),
22015 CreateMockWrite(partitioned_req3, 3),
22016 };
22017
22018 const MockRead kPartitionedReads1[] = {
22019 CreateMockRead(partitioned_response1, 1),
22020 CreateMockRead(partitioned_body1, 2),
22021 CreateMockRead(partitioned_response3, 4),
22022 CreateMockRead(partitioned_body3, 5),
22023 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
22024 };
22025
22026 SpdyTestUtil spdy_util3;
22027 spdy::SpdySerializedFrame partitioned_req2(
22028 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
22029 spdy::SpdySerializedFrame partitioned_response2(
22030 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
22031 spdy::SpdySerializedFrame partitioned_body2(
22032 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
22033
22034 const MockWrite kPartitionedWrites2[] = {
22035 CreateMockWrite(partitioned_req2, 0),
22036 };
22037
22038 const MockRead kPartitionedReads2[] = {
22039 CreateMockRead(partitioned_response2, 1),
22040 CreateMockRead(partitioned_body2, 2),
22041 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
22042 };
22043
22044 SequencedSocketData partitioned_data1(kPartitionedReads1,
22045 kPartitionedWrites1);
22046 SequencedSocketData partitioned_data2(kPartitionedReads2,
22047 kPartitionedWrites2);
22048
22049 // No need to segment SSLDataProviders by whether or not partitioning is
22050 // enabled.
22051 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22052 ssl_data1.next_proto = kProtoHTTP2;
22053 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22054 ssl_data2.next_proto = kProtoHTTP2;
22055
22056 if (partition_connections) {
22057 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22058 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22059 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22060 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22061 } else {
22062 session_deps_.socket_factory->AddSocketDataProvider(
22063 &unpartitioned_data);
22064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22065 }
22066
22067 TestCompletionCallback callback;
22068 HttpRequestInfo request1;
22069 request1.method = "GET";
22070 request1.url = GURL(url1);
22071 request1.traffic_annotation =
22072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22073 request1.network_isolation_key = network_isolation_key1;
22074 auto trans1 =
22075 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22076 int rv =
22077 trans1->Start(&request1, callback.callback(), NetLogWithSource());
22078 EXPECT_THAT(callback.GetResult(rv), IsOk());
22079 std::string response_data1;
22080 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22081 EXPECT_EQ("1", response_data1);
22082 trans1.reset();
22083
22084 HttpRequestInfo request2;
22085 request2.method = "GET";
22086 request2.url = GURL(url2);
22087 request2.traffic_annotation =
22088 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22089 request2.network_isolation_key = network_isolation_key2;
22090 auto trans2 =
22091 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22092 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22093 EXPECT_THAT(callback.GetResult(rv), IsOk());
22094 std::string response_data2;
22095 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22096 EXPECT_EQ("2", response_data2);
22097 trans2.reset();
22098
22099 HttpRequestInfo request3;
22100 request3.method = "GET";
22101 request3.url = GURL(url3);
22102 request3.traffic_annotation =
22103 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22104 request3.network_isolation_key = network_isolation_key1;
22105 auto trans3 =
22106 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22107 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22108 EXPECT_THAT(callback.GetResult(rv), IsOk());
22109 std::string response_data3;
22110 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22111 EXPECT_EQ("3", response_data3);
22112 trans3.reset();
22113 }
22114 }
22115}
22116
Matt Menke7281f872019-06-25 19:29:2522117// Preconnect two sockets with different NetworkIsolationKeys when
22118// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
22119// request and make sure the correct socket is used. Loops three times,
22120// expecting to use the first preconnect, second preconnect, and neither.
22121TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
22122 base::test::ScopedFeatureList feature_list;
22123 feature_list.InitAndEnableFeature(
22124 features::kPartitionConnectionsByNetworkIsolationKey);
22125
22126 enum class TestCase {
22127 kUseFirstPreconnect,
22128 kUseSecondPreconnect,
22129 kDontUsePreconnect,
22130 };
22131
Shivani Sharma8ae506c2019-07-21 21:08:2722132 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22133 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22134 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
22135 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
22136 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
22137 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2522138
22139 // Test that only preconnects with
22140 for (TestCase test_case :
22141 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
22142 TestCase::kDontUsePreconnect}) {
22143 SpdySessionDependencies session_deps;
22144 // Make DNS lookups completely synchronously, so preconnects complete
22145 // immediately.
22146 session_deps.host_resolver->set_synchronous_mode(true);
22147
22148 const MockWrite kMockWrites[] = {
22149 MockWrite(ASYNC, 0,
22150 "GET / HTTP/1.1\r\n"
22151 "Host: www.foo.com\r\n"
22152 "Connection: keep-alive\r\n\r\n"),
22153 };
22154
22155 const MockRead kMockReads[] = {
22156 MockRead(ASYNC, 1,
22157 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
22158 "hello"),
22159 };
22160
22161 // Used for the socket that will actually be used, which may or may not be
22162 // one of the preconnects
22163 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
22164 kMockReads, kMockWrites);
22165
22166 // Used for the preconnects that won't actually be used.
22167 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
22168 base::span<const MockRead>(),
22169 base::span<const MockWrite>());
22170 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
22171 base::span<const MockRead>(),
22172 base::span<const MockWrite>());
22173
22174 NetworkIsolationKey network_isolation_key_for_request;
22175
22176 switch (test_case) {
22177 case TestCase::kUseFirstPreconnect:
22178 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22179 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22180 network_isolation_key_for_request = preconnect1_isolation_key;
22181 break;
22182 case TestCase::kUseSecondPreconnect:
22183 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22184 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22185 network_isolation_key_for_request = preconnect2_isolation_key;
22186 break;
22187 case TestCase::kDontUsePreconnect:
22188 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22189 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22190 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22191 network_isolation_key_for_request = not_preconnected_isolation_key;
22192 break;
22193 }
22194
22195 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
22196
22197 // Preconnect sockets.
22198 HttpRequestInfo request;
22199 request.method = "GET";
22200 request.url = GURL("http://www.foo.com/");
22201 request.traffic_annotation =
22202 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22203
22204 request.network_isolation_key = preconnect1_isolation_key;
22205 session->http_stream_factory()->PreconnectStreams(1, request);
22206
22207 request.network_isolation_key = preconnect2_isolation_key;
22208 session->http_stream_factory()->PreconnectStreams(1, request);
22209
22210 request.network_isolation_key = network_isolation_key_for_request;
22211
22212 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22213
22214 // Make the request.
22215 TestCompletionCallback callback;
22216
22217 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22218
22219 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22220 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22221
22222 rv = callback.WaitForResult();
22223 EXPECT_THAT(rv, IsOk());
22224
22225 const HttpResponseInfo* response = trans.GetResponseInfo();
22226 ASSERT_TRUE(response);
22227 ASSERT_TRUE(response->headers);
22228 EXPECT_EQ(200, response->headers->response_code());
22229
22230 std::string response_data;
22231 rv = ReadTransaction(&trans, &response_data);
22232 EXPECT_THAT(rv, IsOk());
22233 EXPECT_EQ("hello", response_data);
22234
22235 if (test_case != TestCase::kDontUsePreconnect) {
22236 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22237 } else {
22238 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
22239 }
22240 }
22241}
22242
David Benjamin6f2da652019-06-26 23:36:3522243// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22244// cache is isolated.
22245TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
22246 base::test::ScopedFeatureList feature_list;
22247 feature_list.InitWithFeatures(
22248 {features::kPartitionConnectionsByNetworkIsolationKey,
22249 features::kPartitionSSLSessionsByNetworkIsolationKey},
22250 {});
22251
Shivani Sharma8ae506c2019-07-21 21:08:2722252 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22253 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22254 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22255 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522256 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22257
22258 // The server always sends Connection: close, so each request goes over a
22259 // distinct socket.
22260
22261 const MockWrite kWrites1[] = {
22262 MockWrite("GET /1 HTTP/1.1\r\n"
22263 "Host: foo.test\r\n"
22264 "Connection: keep-alive\r\n\r\n")};
22265
22266 const MockRead kReads1[] = {
22267 MockRead("HTTP/1.1 200 OK\r\n"
22268 "Connection: close\r\n"
22269 "Content-Length: 1\r\n\r\n"
22270 "1")};
22271
22272 const MockWrite kWrites2[] = {
22273 MockWrite("GET /2 HTTP/1.1\r\n"
22274 "Host: foo.test\r\n"
22275 "Connection: keep-alive\r\n\r\n")};
22276
22277 const MockRead kReads2[] = {
22278 MockRead("HTTP/1.1 200 OK\r\n"
22279 "Connection: close\r\n"
22280 "Content-Length: 1\r\n\r\n"
22281 "2")};
22282
22283 const MockWrite kWrites3[] = {
22284 MockWrite("GET /3 HTTP/1.1\r\n"
22285 "Host: foo.test\r\n"
22286 "Connection: keep-alive\r\n\r\n")};
22287
22288 const MockRead kReads3[] = {
22289 MockRead("HTTP/1.1 200 OK\r\n"
22290 "Connection: close\r\n"
22291 "Content-Length: 1\r\n\r\n"
22292 "3")};
22293
22294 StaticSocketDataProvider data1(kReads1, kWrites1);
22295 StaticSocketDataProvider data2(kReads2, kWrites2);
22296 StaticSocketDataProvider data3(kReads3, kWrites3);
22297 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22298 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22299 session_deps_.socket_factory->AddSocketDataProvider(&data3);
22300
22301 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22302 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
22303 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
22304 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22305 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
22306 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
22307 SSLSocketDataProvider ssl_data3(ASYNC, OK);
22308 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
22309 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
22310 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22311 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22312 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
22313
22314 TestCompletionCallback callback;
22315 HttpRequestInfo request1;
22316 request1.method = "GET";
22317 request1.url = GURL("https://foo.test/1");
22318 request1.traffic_annotation =
22319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22320 request1.network_isolation_key = kNetworkIsolationKey1;
22321 auto trans1 =
22322 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22323 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22324 EXPECT_THAT(callback.GetResult(rv), IsOk());
22325 std::string response_data1;
22326 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22327 EXPECT_EQ("1", response_data1);
22328 trans1.reset();
22329
22330 HttpRequestInfo request2;
22331 request2.method = "GET";
22332 request2.url = GURL("https://foo.test/2");
22333 request2.traffic_annotation =
22334 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22335 request2.network_isolation_key = kNetworkIsolationKey2;
22336 auto trans2 =
22337 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22338 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22339 EXPECT_THAT(callback.GetResult(rv), IsOk());
22340 std::string response_data2;
22341 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22342 EXPECT_EQ("2", response_data2);
22343 trans2.reset();
22344
22345 HttpRequestInfo request3;
22346 request3.method = "GET";
22347 request3.url = GURL("https://foo.test/3");
22348 request3.traffic_annotation =
22349 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22350 request3.network_isolation_key = kNetworkIsolationKey1;
22351 auto trans3 =
22352 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22353 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22354 EXPECT_THAT(callback.GetResult(rv), IsOk());
22355 std::string response_data3;
22356 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22357 EXPECT_EQ("3", response_data3);
22358 trans3.reset();
22359}
22360
22361// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22362// cache is isolated, for both origins and proxies.
22363TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
22364 base::test::ScopedFeatureList feature_list;
22365 feature_list.InitWithFeatures(
22366 {features::kPartitionConnectionsByNetworkIsolationKey,
22367 features::kPartitionSSLSessionsByNetworkIsolationKey},
22368 {});
22369
22370 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
22371 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
22372
Shivani Sharma8ae506c2019-07-21 21:08:2722373 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22374 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22375 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22376 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522377 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22378
22379 // Make both a tunneled and non-tunneled request.
22380 HttpRequestInfo request1;
22381 request1.method = "GET";
22382 request1.url = GURL("https://foo.test/1");
22383 request1.traffic_annotation =
22384 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22385 request1.network_isolation_key = kNetworkIsolationKey1;
22386
22387 HttpRequestInfo request2;
22388 request2.method = "GET";
22389 request2.url = GURL("http://foo.test/2");
22390 request2.traffic_annotation =
22391 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22392 request2.network_isolation_key = kNetworkIsolationKey2;
22393
22394 const MockWrite kWrites1[] = {
22395 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
22396 "Host: foo.test:443\r\n"
22397 "Proxy-Connection: keep-alive\r\n\r\n"),
22398 MockWrite("GET /1 HTTP/1.1\r\n"
22399 "Host: foo.test\r\n"
22400 "Connection: keep-alive\r\n\r\n")};
22401
22402 const MockRead kReads1[] = {
22403 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
22404 MockRead("HTTP/1.1 200 OK\r\n"
22405 "Connection: close\r\n"
22406 "Content-Length: 1\r\n\r\n"
22407 "1")};
22408
22409 const MockWrite kWrites2[] = {
22410 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
22411 "Host: foo.test\r\n"
22412 "Proxy-Connection: keep-alive\r\n\r\n")};
22413
22414 const MockRead kReads2[] = {
22415 MockRead("HTTP/1.1 200 OK\r\n"
22416 "Connection: close\r\n"
22417 "Content-Length: 1\r\n\r\n"
22418 "2")};
22419
22420 StaticSocketDataProvider data1(kReads1, kWrites1);
22421 StaticSocketDataProvider data2(kReads2, kWrites2);
22422 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22423 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22424 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22425
22426 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
22427 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
22428 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
22429 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
22430 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
22431 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
22432 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22433 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
22434 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
22435 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22436 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22437 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22438
22439 TestCompletionCallback callback;
22440 auto trans1 =
22441 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22442 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22443 EXPECT_THAT(callback.GetResult(rv), IsOk());
22444 std::string response_data1;
22445 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22446 EXPECT_EQ("1", response_data1);
22447 trans1.reset();
22448
22449 auto trans2 =
22450 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22451 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22452 EXPECT_THAT(callback.GetResult(rv), IsOk());
22453 std::string response_data2;
22454 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22455 EXPECT_EQ("2", response_data2);
22456 trans2.reset();
22457}
22458
David Benjaminef2f2a5a2019-07-16 19:21:3122459// Test that SSLConfig changes from SSLConfigService are picked up even when
22460// there are live sockets.
22461TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5222462 SSLContextConfig ssl_context_config;
22463 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22464 auto ssl_config_service =
22465 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122466 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22467
22468 session_deps_.ssl_config_service = std::move(ssl_config_service);
22469
22470 // Make three requests. Between the second and third, the SSL config will
22471 // change.
22472 HttpRequestInfo request1;
22473 request1.method = "GET";
22474 request1.url = GURL("https://foo.test/1");
22475 request1.traffic_annotation =
22476 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22477
22478 HttpRequestInfo request2;
22479 request2.method = "GET";
22480 request2.url = GURL("https://foo.test/2");
22481 request2.traffic_annotation =
22482 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22483
22484 HttpRequestInfo request3;
22485 request3.method = "GET";
22486 request3.url = GURL("https://foo.test/3");
22487 request3.traffic_annotation =
22488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22489
22490 const MockWrite kWrites1[] = {
22491 MockWrite("GET /1 HTTP/1.1\r\n"
22492 "Host: foo.test\r\n"
22493 "Connection: keep-alive\r\n\r\n"),
22494 MockWrite("GET /2 HTTP/1.1\r\n"
22495 "Host: foo.test\r\n"
22496 "Connection: keep-alive\r\n\r\n"),
22497 };
22498
22499 const MockRead kReads1[] = {
22500 MockRead("HTTP/1.1 200 OK\r\n"
22501 "Connection: keep-alive\r\n"
22502 "Content-Length: 1\r\n\r\n"
22503 "1"),
22504 MockRead("HTTP/1.1 200 OK\r\n"
22505 "Connection: keep-alive\r\n"
22506 "Content-Length: 1\r\n\r\n"
22507 "2"),
22508 };
22509
22510 // The third request goes on a different socket because the SSL config has
22511 // changed.
22512 const MockWrite kWrites2[] = {
22513 MockWrite("GET /3 HTTP/1.1\r\n"
22514 "Host: foo.test\r\n"
22515 "Connection: keep-alive\r\n\r\n")};
22516
22517 const MockRead kReads2[] = {
22518 MockRead("HTTP/1.1 200 OK\r\n"
22519 "Connection: keep-alive\r\n"
22520 "Content-Length: 1\r\n\r\n"
22521 "3")};
22522
22523 StaticSocketDataProvider data1(kReads1, kWrites1);
22524 StaticSocketDataProvider data2(kReads2, kWrites2);
22525 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22526 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22527
22528 SSLSocketDataProvider ssl1(ASYNC, OK);
22529 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22530 SSLSocketDataProvider ssl2(ASYNC, OK);
22531 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22532 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22533 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22534
22535 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22536
22537 TestCompletionCallback callback;
22538 auto trans1 =
22539 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22540 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22541 EXPECT_THAT(callback.GetResult(rv), IsOk());
22542 std::string response_data1;
22543 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22544 EXPECT_EQ("1", response_data1);
22545 trans1.reset();
22546
22547 auto trans2 =
22548 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22549 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22550 EXPECT_THAT(callback.GetResult(rv), IsOk());
22551 std::string response_data2;
22552 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22553 EXPECT_EQ("2", response_data2);
22554 trans2.reset();
22555
David Benjamin151ec6b2019-08-02 19:38:5222556 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22557 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122558
22559 auto trans3 =
22560 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22561 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22562 EXPECT_THAT(callback.GetResult(rv), IsOk());
22563 std::string response_data3;
22564 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22565 EXPECT_EQ("3", response_data3);
22566 trans3.reset();
22567}
22568
22569TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5222570 SSLContextConfig ssl_context_config;
22571 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22572 auto ssl_config_service =
22573 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122574 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22575
22576 session_deps_.ssl_config_service = std::move(ssl_config_service);
22577
22578 HttpRequestInfo request;
22579 request.method = "GET";
22580 request.url = GURL("https://foo.test/1");
22581 request.traffic_annotation =
22582 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22583
22584 // Make a socket which never connects.
22585 StaticSocketDataProvider data({}, {});
22586 session_deps_.socket_factory->AddSocketDataProvider(&data);
22587 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
22588 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22589 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
22590
22591 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22592
22593 TestCompletionCallback callback;
22594 auto trans =
22595 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22596 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
22597 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22598
David Benjamin151ec6b2019-08-02 19:38:5222599 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22600 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122601
22602 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
22603}
22604
David Benjaminbac8dff2019-08-07 01:30:4122605// Test that HttpNetworkTransaction correctly handles existing sockets when the
22606// server requests a client certificate post-handshake (via a TLS
22607// renegotiation). This is a regression test for https://crbug.com/829184.
22608TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
22609 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
22610 TRAFFIC_ANNOTATION_FOR_TESTS);
22611
22612 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
22613 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
22614
22615 std::unique_ptr<FakeClientCertIdentity> identity =
22616 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22617 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
22618 ASSERT_TRUE(identity);
22619
22620 // This test will make several requests so that, when the client certificate
22621 // request comes in, we have a socket in use, an idle socket, and a socket for
22622 // an unrelated host.
22623 //
22624 // First, two long-lived requests which do not complete until after the client
22625 // certificate request. This arranges for sockets to be in use during the
22626 // request. They should not be interrupted.
22627 HttpRequestInfo request_long_lived;
22628 request_long_lived.method = "GET";
22629 request_long_lived.url = GURL("https://foo.test/long-lived");
22630 request_long_lived.traffic_annotation = kTrafficAnnotation;
22631
22632 HttpRequestInfo request_long_lived_bar;
22633 request_long_lived_bar.method = "GET";
22634 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
22635 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
22636
22637 // Next, make a request that needs client certificates.
22638 HttpRequestInfo request_auth;
22639 request_auth.method = "GET";
22640 request_auth.url = GURL("https://foo.test/auth");
22641 request_auth.traffic_annotation = kTrafficAnnotation;
22642
22643 // Before responding to the challenge, make a request to an unauthenticated
22644 // endpoint. This will result in an idle socket when the client certificate
22645 // challenge is resolved.
22646 HttpRequestInfo request_unauth;
22647 request_unauth.method = "GET";
22648 request_unauth.url = GURL("https://foo.test/unauth");
22649 request_unauth.traffic_annotation = kTrafficAnnotation;
22650
22651 // After all the preceding requests complete, end with two additional requests
22652 // to ensure pre-authentication foo.test sockets are not used and bar.test
22653 // sockets are unaffected.
22654 HttpRequestInfo request_post_auth;
22655 request_post_auth.method = "GET";
22656 request_post_auth.url = GURL("https://foo.test/post-auth");
22657 request_post_auth.traffic_annotation = kTrafficAnnotation;
22658
22659 HttpRequestInfo request_post_auth_bar;
22660 request_post_auth_bar.method = "GET";
22661 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
22662 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
22663
22664 // The sockets for /long-lived and /unauth complete their request but are
22665 // not allocated for /post-auth or /retry because SSL state has since changed.
22666 const MockWrite kLongLivedWrites[] = {
22667 MockWrite(ASYNC, 0,
22668 "GET /long-lived HTTP/1.1\r\n"
22669 "Host: foo.test\r\n"
22670 "Connection: keep-alive\r\n\r\n"),
22671 };
22672 const MockRead kLongLivedReads[] = {
22673 // Pause so /long-lived completes after the client presents client
22674 // certificates.
22675 MockRead(ASYNC, ERR_IO_PENDING, 1),
22676 MockRead(ASYNC, 2,
22677 "HTTP/1.1 200 OK\r\n"
22678 "Connection: keep-alive\r\n"
22679 "Content-Length: 10\r\n\r\n"
22680 "long-lived"),
22681 };
22682 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
22683 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
22684 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
22685 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
22686
22687 // Requests for bar.test should be unaffected by foo.test and get allocated
22688 // a single socket.
22689 const MockWrite kBarWrites[] = {
22690 MockWrite(ASYNC, 0,
22691 "GET /long-lived HTTP/1.1\r\n"
22692 "Host: bar.test\r\n"
22693 "Connection: keep-alive\r\n\r\n"),
22694 MockWrite(ASYNC, 3,
22695 "GET /post-auth HTTP/1.1\r\n"
22696 "Host: bar.test\r\n"
22697 "Connection: keep-alive\r\n\r\n"),
22698 };
22699 const MockRead kBarReads[] = {
22700 // Pause on /long-lived so it completes after foo.test's authentication.
22701 MockRead(ASYNC, ERR_IO_PENDING, 1),
22702 MockRead(ASYNC, 2,
22703 "HTTP/1.1 200 OK\r\n"
22704 "Connection: keep-alive\r\n"
22705 "Content-Length: 10\r\n\r\n"
22706 "long-lived"),
22707 MockRead(ASYNC, 4,
22708 "HTTP/1.1 200 OK\r\n"
22709 "Connection: keep-alive\r\n"
22710 "Content-Length: 9\r\n\r\n"
22711 "post-auth"),
22712 };
22713 SequencedSocketData data_bar(kBarReads, kBarWrites);
22714 SSLSocketDataProvider ssl_bar(ASYNC, OK);
22715 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
22716 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
22717
22718 // Requesting /auth results in a post-handshake client certificate challenge.
22719 const MockWrite kAuthWrites[] = {
22720 MockWrite(ASYNC, 0,
22721 "GET /auth HTTP/1.1\r\n"
22722 "Host: foo.test\r\n"
22723 "Connection: keep-alive\r\n\r\n"),
22724 };
22725 const MockRead kAuthReads[] = {
22726 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
22727 };
22728 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
22729 SSLSocketDataProvider ssl_auth(ASYNC, OK);
22730 ssl_auth.cert_request_info = cert_request_info.get();
22731 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
22732 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
22733
22734 // Requesting /unauth completes.
22735 const MockWrite kUnauthWrites[] = {
22736 MockWrite(ASYNC, 0,
22737 "GET /unauth HTTP/1.1\r\n"
22738 "Host: foo.test\r\n"
22739 "Connection: keep-alive\r\n\r\n"),
22740 };
22741 const MockRead kUnauthReads[] = {
22742 MockRead(ASYNC, 1,
22743 "HTTP/1.1 200 OK\r\n"
22744 "Connection: keep-alive\r\n"
22745 "Content-Length: 6\r\n\r\n"
22746 "unauth"),
22747 };
22748 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
22749 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
22750 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
22751 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
22752
22753 // When the client certificate is selected, /auth is retried on a new
22754 // connection. In particular, it should not be retried on |data_unauth|,
22755 // which would not honor the new client certificate configuration.
22756 const MockWrite kRetryWrites[] = {
22757 MockWrite(ASYNC, 0,
22758 "GET /auth HTTP/1.1\r\n"
22759 "Host: foo.test\r\n"
22760 "Connection: keep-alive\r\n\r\n"),
22761 };
22762 const MockRead kRetryReads[] = {
22763 MockRead(ASYNC, 1,
22764 "HTTP/1.1 200 OK\r\n"
22765 // Close the connection so we test that /post-auth is not
22766 // allocated to |data_unauth| or |data_long_lived|.
22767 "Connection: close\r\n"
22768 "Content-Length: 4\r\n\r\n"
22769 "auth"),
22770 };
22771 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
22772 SSLSocketDataProvider ssl_retry(ASYNC, OK);
22773 ssl_retry.expected_send_client_cert = true;
22774 ssl_retry.expected_client_cert = identity->certificate();
22775 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
22776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
22777
22778 // /post-auth gets its own socket.
22779 const MockWrite kPostAuthWrites[] = {
22780 MockWrite(ASYNC, 0,
22781 "GET /post-auth HTTP/1.1\r\n"
22782 "Host: foo.test\r\n"
22783 "Connection: keep-alive\r\n\r\n"),
22784 };
22785 const MockRead kPostAuthReads[] = {
22786 MockRead(ASYNC, 1,
22787 "HTTP/1.1 200 OK\r\n"
22788 "Connection: keep-alive\r\n"
22789 "Content-Length: 9\r\n\r\n"
22790 "post-auth"),
22791 };
22792 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
22793 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
22794 ssl_post_auth.expected_send_client_cert = true;
22795 ssl_post_auth.expected_client_cert = identity->certificate();
22796 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
22797 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
22798
22799 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22800
22801 // Start the two long-lived requests.
22802 TestCompletionCallback callback_long_lived;
22803 auto trans_long_lived =
22804 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22805 int rv = trans_long_lived->Start(
22806 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
22807 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22808 data_long_lived.RunUntilPaused();
22809
22810 TestCompletionCallback callback_long_lived_bar;
22811 auto trans_long_lived_bar =
22812 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22813 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
22814 callback_long_lived_bar.callback(),
22815 NetLogWithSource());
22816 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22817 data_bar.RunUntilPaused();
22818
22819 // Request /auth. This gives a client certificate challenge.
22820 TestCompletionCallback callback_auth;
22821 auto trans_auth =
22822 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22823 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
22824 NetLogWithSource());
22825 EXPECT_THAT(callback_auth.GetResult(rv),
22826 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22827
22828 // Make an unauthenticated request. This completes.
22829 TestCompletionCallback callback_unauth;
22830 auto trans_unauth =
22831 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22832 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
22833 NetLogWithSource());
22834 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
22835 std::string response_unauth;
22836 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
22837 EXPECT_EQ("unauth", response_unauth);
22838 trans_unauth.reset();
22839
22840 // Complete the authenticated request.
22841 rv = trans_auth->RestartWithCertificate(identity->certificate(),
22842 identity->ssl_private_key(),
22843 callback_auth.callback());
22844 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
22845 std::string response_auth;
22846 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
22847 EXPECT_EQ("auth", response_auth);
22848 trans_auth.reset();
22849
22850 // Complete the long-lived requests.
22851 data_long_lived.Resume();
22852 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
22853 std::string response_long_lived;
22854 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
22855 IsOk());
22856 EXPECT_EQ("long-lived", response_long_lived);
22857 trans_long_lived.reset();
22858
22859 data_bar.Resume();
22860 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
22861 std::string response_long_lived_bar;
22862 EXPECT_THAT(
22863 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
22864 IsOk());
22865 EXPECT_EQ("long-lived", response_long_lived_bar);
22866 trans_long_lived_bar.reset();
22867
22868 // Run the post-authentication requests.
22869 TestCompletionCallback callback_post_auth;
22870 auto trans_post_auth =
22871 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22872 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
22873 NetLogWithSource());
22874 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
22875 std::string response_post_auth;
22876 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
22877 IsOk());
22878 EXPECT_EQ("post-auth", response_post_auth);
22879 trans_post_auth.reset();
22880
22881 TestCompletionCallback callback_post_auth_bar;
22882 auto trans_post_auth_bar =
22883 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22884 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
22885 callback_post_auth_bar.callback(),
22886 NetLogWithSource());
22887 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
22888 std::string response_post_auth_bar;
22889 EXPECT_THAT(
22890 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
22891 IsOk());
22892 EXPECT_EQ("post-auth", response_post_auth_bar);
22893 trans_post_auth_bar.reset();
22894}
22895
[email protected]89ceba9a2009-03-21 03:46:0622896} // namespace net