blob: 4db22adf47b7030ff32934311271e8e1389f9f29 [file] [log] [blame]
[email protected]23e482282013-06-14 16:08:021// Copyright 2013 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]5285d972011-10-18 18:56:348#include <stdarg.h>
sclittlebe1ccf62015-09-02 19:40:369#include <stdint.h>
danakj1fd259a02016-04-16 03:17:0910
avibf0746c2015-12-09 19:53:1411#include <limits>
rdsmith1d343be52016-10-21 20:37:5012#include <set>
[email protected]5285d972011-10-18 18:56:3413#include <string>
dchengc7eeda422015-12-26 03:56:4814#include <utility>
[email protected]95d88ffe2010-02-04 21:25:3315#include <vector>
[email protected]77848d12008-11-14 00:00:2216
Sebastien Marchand6d0558fd2019-01-25 16:49:3717#include "base/bind.h"
[email protected]68bf9152008-09-25 19:47:3018#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5219#include "base/files/file_path.h"
thestigd8df0332014-09-04 06:33:2920#include "base/files/file_util.h"
[email protected]f3da152d2012-06-02 01:00:5721#include "base/json/json_writer.h"
Adam Rice425cf122015-01-19 06:18:2422#include "base/logging.h"
danakj1fd259a02016-04-16 03:17:0923#include "base/memory/ptr_util.h"
[email protected]bf828982013-08-14 18:01:4724#include "base/memory/weak_ptr.h"
Eric Orthf4db66a2019-02-19 21:35:3325#include "base/optional.h"
[email protected]a34f61ee2014-03-18 20:59:4926#include "base/run_loop.h"
Avi Drissman4365a4782018-12-28 19:26:2427#include "base/stl_util.h"
Bence Békyd74f4382018-02-20 18:26:1928#include "base/strings/string_piece.h"
[email protected]125ef482013-06-11 18:32:4729#include "base/strings/string_util.h"
Matt Menked732ea42019-03-08 12:05:0030#include "base/strings/stringprintf.h"
[email protected]750b2f3c2013-06-07 18:41:0531#include "base/strings/utf_string_conversions.h"
Douglas Creager3cb042052018-11-06 23:08:5232#include "base/test/metrics/histogram_tester.h"
Matt Menke166443c2019-05-24 18:45:5933#include "base/test/scoped_feature_list.h"
Douglas Creager134b52e2018-11-09 18:00:1434#include "base/test/simple_test_clock.h"
35#include "base/test/simple_test_tick_clock.h"
Gabriel Charettec7108742019-08-23 03:31:4036#include "base/test/task_environment.h"
[email protected]f36a8132011-09-02 18:36:3337#include "base/test/test_file_util.h"
gabf767595f2016-05-11 18:50:3538#include "base/threading/thread_task_runner_handle.h"
Matt Menke5062be22019-05-01 17:50:2439#include "build/build_config.h"
[email protected]277d5942010-08-11 21:02:3540#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0741#include "net/base/chunked_upload_data_stream.h"
Bence Békya25e3f72018-02-13 21:13:3942#include "net/base/completion_once_callback.h"
mmenkecbc2b712014-10-09 20:29:0743#include "net/base/elements_upload_data_stream.h"
Matt Menke166443c2019-05-24 18:45:5944#include "net/base/features.h"
Eric Orthf4db66a2019-02-19 21:35:3345#include "net/base/host_port_pair.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3746#include "net/base/ip_endpoint.h"
[email protected]58e32bb2013-01-21 18:23:2547#include "net/base/load_timing_info.h"
48#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2449#include "net/base/net_errors.h"
Matt Menkebdf777802019-04-22 19:38:5950#include "net/base/privacy_mode.h"
tbansal28e68f82016-02-04 02:56:1551#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4052#include "net/base/proxy_server.h"
[email protected]ac790b42009-12-02 04:31:3153#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5254#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1555#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0656#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2157#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0858#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1159#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5360#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2461#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1262#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0063#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2964#include "net/http/http_auth_handler_ntlm.h"
aberentbba302d2015-12-03 10:20:1965#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5766#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5267#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5668#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0469#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2470#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1371#include "net/http/http_response_info.h"
Matt Menke609160742019-08-02 18:47:2672#include "net/http/http_server_properties.h"
[email protected]0877e3d2009-10-17 22:29:5773#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3874#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1975#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0776#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0077#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1978#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5179#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4680#include "net/log/test_net_log_util.h"
Lily Houghton582d4622018-01-22 22:43:4081#include "net/proxy_resolution/mock_proxy_resolver.h"
82#include "net/proxy_resolution/proxy_config_service_fixed.h"
83#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0384#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4085#include "net/proxy_resolution/proxy_resolver.h"
86#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4487#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1588#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0389#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3690#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4791#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0292#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0793#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0494#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4495#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1296#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:4497#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:5898#include "net/spdy/spdy_session.h"
99#include "net/spdy/spdy_session_pool.h"
100#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:04101#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57102#include "net/ssl/ssl_cert_request_info.h"
David Benjaminef2f2a5a2019-07-16 19:21:31103#include "net/ssl/ssl_config.h"
[email protected]e86839fd2013-08-14 18:29:03104#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57105#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54106#include "net/ssl/ssl_private_key.h"
David Benjamin151ec6b2019-08-02 19:38:52107#include "net/ssl/test_ssl_config_service.h"
[email protected]6e7845ae2013-03-29 21:48:11108#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01109#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43110#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:40111#include "net/test/test_with_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14112#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23113#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00114#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44115#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06116#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18117#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52118#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15119#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27120#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52121
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37122#if defined(NTLM_PORTABLE)
123#include "base/base64.h"
124#include "net/ntlm/ntlm_test_data.h"
125#endif
126
Douglas Creager3cb042052018-11-06 23:08:52127#if BUILDFLAG(ENABLE_REPORTING)
128#include "net/network_error_logging/network_error_logging_service.h"
129#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14130#include "net/reporting/reporting_cache.h"
Lily Chenfc92ff42019-05-06 22:59:10131#include "net/reporting/reporting_endpoint.h"
Douglas Creager134b52e2018-11-09 18:00:14132#include "net/reporting/reporting_header_parser.h"
133#include "net/reporting/reporting_service.h"
134#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52135#endif // BUILDFLAG(ENABLE_REPORTING)
136
robpercival214763f2016-07-01 23:27:01137using net::test::IsError;
138using net::test::IsOk;
139
[email protected]ad65a3e2013-12-25 18:18:01140using base::ASCIIToUTF16;
141
David Benjamin3b94b0f2019-04-25 23:07:52142using testing::AnyOf;
143
initial.commit586acc5fe2008-07-26 22:42:52144//-----------------------------------------------------------------------------
145
ttuttle859dc7a2015-04-23 19:42:29146namespace net {
147
[email protected]13c8a092010-07-29 06:15:44148namespace {
149
[email protected]42cba2fb2013-03-29 19:58:57150const base::string16 kBar(ASCIIToUTF16("bar"));
151const base::string16 kBar2(ASCIIToUTF16("bar2"));
152const base::string16 kBar3(ASCIIToUTF16("bar3"));
153const base::string16 kBaz(ASCIIToUTF16("baz"));
154const base::string16 kFirst(ASCIIToUTF16("first"));
155const base::string16 kFoo(ASCIIToUTF16("foo"));
156const base::string16 kFoo2(ASCIIToUTF16("foo2"));
157const base::string16 kFoo3(ASCIIToUTF16("foo3"));
158const base::string16 kFou(ASCIIToUTF16("fou"));
159const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57160const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44161
bnc2df4b522016-07-08 18:17:43162const char kAlternativeServiceHttpHeader[] =
163 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
164
ttuttle859dc7a2015-04-23 19:42:29165int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40166 return session
167 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
168 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29169 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02170}
171
ttuttle859dc7a2015-04-23 19:42:29172bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40173 return session
174 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
175 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29176 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52177}
178
[email protected]f3da152d2012-06-02 01:00:57179// Takes in a Value created from a NetLogHttpResponseParameter, and returns
180// a JSONified list of headers as a single string. Uses single quotes instead
Eric Roman79cc7552019-07-19 02:17:54181// of double quotes for easier comparison.
182std::string GetHeaders(const base::Value& params) {
183 if (!params.is_dict())
184 return "";
185 const base::Value* header_list = params.FindListKey("headers");
186 if (!header_list)
187 return "";
188 std::string headers;
189 base::JSONWriter::Write(*header_list, &headers);
190 base::ReplaceChars(headers, "\"", "'", &headers);
191 return headers;
[email protected]f3da152d2012-06-02 01:00:57192}
193
[email protected]029c83b62013-01-24 05:28:20194// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
195// used.
ttuttle859dc7a2015-04-23 19:42:29196void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20197 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19198 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25199
[email protected]029c83b62013-01-24 05:28:20200 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
201 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
202
ttuttle859dc7a2015-04-23 19:42:29203 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20204 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25205
206 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25207
[email protected]3b23a222013-05-15 21:33:25208 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25209 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
210 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25211 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25212}
213
[email protected]029c83b62013-01-24 05:28:20214// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
215// used.
ttuttle859dc7a2015-04-23 19:42:29216void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25217 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20218 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19219 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20220
221 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
222 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
223
ttuttle859dc7a2015-04-23 19:42:29224 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
225 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20226 EXPECT_LE(load_timing_info.connect_timing.connect_end,
227 load_timing_info.send_start);
228
229 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20230
[email protected]3b23a222013-05-15 21:33:25231 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20232 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
233 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25234 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20235}
236
237// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
238// used.
ttuttle859dc7a2015-04-23 19:42:29239void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20240 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19241 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20242
ttuttle859dc7a2015-04-23 19:42:29243 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20244
245 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
246 EXPECT_LE(load_timing_info.proxy_resolve_start,
247 load_timing_info.proxy_resolve_end);
248 EXPECT_LE(load_timing_info.proxy_resolve_end,
249 load_timing_info.send_start);
250 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20251
[email protected]3b23a222013-05-15 21:33:25252 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20253 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
254 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25255 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20256}
257
258// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
259// used.
ttuttle859dc7a2015-04-23 19:42:29260void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20261 int connect_timing_flags) {
262 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19263 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20264
265 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
266 EXPECT_LE(load_timing_info.proxy_resolve_start,
267 load_timing_info.proxy_resolve_end);
268 EXPECT_LE(load_timing_info.proxy_resolve_end,
269 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29270 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
271 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20272 EXPECT_LE(load_timing_info.connect_timing.connect_end,
273 load_timing_info.send_start);
274
275 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20276
[email protected]3b23a222013-05-15 21:33:25277 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20278 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
279 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25280 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25281}
282
Matt Menke2436b2f2018-12-11 18:07:11283// ProxyResolver that records URLs passed to it, and that can be told what
284// result to return.
285class CapturingProxyResolver : public ProxyResolver {
286 public:
287 CapturingProxyResolver()
288 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
289 ~CapturingProxyResolver() override = default;
290
291 int GetProxyForURL(const GURL& url,
292 ProxyInfo* results,
293 CompletionOnceCallback callback,
294 std::unique_ptr<Request>* request,
295 const NetLogWithSource& net_log) override {
296 results->UseProxyServer(proxy_server_);
297 resolved_.push_back(url);
298 return OK;
299 }
300
301 // Sets whether the resolver should use direct connections, instead of a
302 // proxy.
303 void set_proxy_server(ProxyServer proxy_server) {
304 proxy_server_ = proxy_server;
305 }
306
307 const std::vector<GURL>& resolved() const { return resolved_; }
308
309 private:
310 std::vector<GURL> resolved_;
311
312 ProxyServer proxy_server_;
313
314 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
315};
316
317class CapturingProxyResolverFactory : public ProxyResolverFactory {
318 public:
319 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
320 : ProxyResolverFactory(false), resolver_(resolver) {}
321
322 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
323 std::unique_ptr<ProxyResolver>* resolver,
324 CompletionOnceCallback callback,
325 std::unique_ptr<Request>* request) override {
326 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
327 return OK;
328 }
329
330 private:
331 ProxyResolver* resolver_;
332};
333
danakj1fd259a02016-04-16 03:17:09334std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42335 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34336 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14337}
338
xunjieli96f2a402017-06-05 17:24:27339class FailingProxyResolverFactory : public ProxyResolverFactory {
340 public:
341 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
342
343 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42344 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
345 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17346 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42347 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27348 return ERR_PAC_SCRIPT_FAILED;
349 }
350};
351
[email protected]448d4ca52012-03-04 04:12:23352} // namespace
353
Bence Béky98447b12018-05-08 03:14:01354class HttpNetworkTransactionTest : public PlatformTest,
Gabriel Charette694c3c332019-08-19 14:53:05355 public WithTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03356 public:
bncd16676a2016-07-20 16:23:01357 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03358 // Important to restore the per-pool limit first, since the pool limit must
359 // always be greater than group limit, and the tests reduce both limits.
360 ClientSocketPoolManager::set_max_sockets_per_pool(
361 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
362 ClientSocketPoolManager::set_max_sockets_per_group(
363 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
364 }
365
[email protected]e3ceb682011-06-28 23:55:46366 protected:
[email protected]23e482282013-06-14 16:08:02367 HttpNetworkTransactionTest()
Gabriel Charette694c3c332019-08-19 14:53:05368 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
Matt Menked6fd2a52019-03-20 06:14:36369 dummy_connect_job_params_(
370 nullptr /* client_socket_factory */,
371 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40372 nullptr /* http_auth_cache */,
373 nullptr /* http_auth_handler_factory */,
374 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13375 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40376 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36377 nullptr /* proxy_delegate */,
378 nullptr /* http_user_agent_settings */,
David Benjamin24725be2019-07-24 20:57:18379 nullptr /* ssl_client_context */,
Matt Menked6fd2a52019-03-20 06:14:36380 nullptr /* socket_performance_watcher_factory */,
381 nullptr /* network_quality_estimator */,
382 nullptr /* net_log */,
383 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56384 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15385 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03386 HttpNetworkSession::NORMAL_SOCKET_POOL)),
387 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
388 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28389 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03390 }
[email protected]bb88e1d32013-05-03 23:11:07391
[email protected]e3ceb682011-06-28 23:55:46392 struct SimpleGetHelperResult {
393 int rv;
394 std::string status_line;
395 std::string response_data;
sclittlefb249892015-09-10 21:33:22396 int64_t total_received_bytes;
397 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25398 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47399 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59400 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46401 };
402
dcheng67be2b1f2014-10-27 21:47:29403 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50404 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55405 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56406 // Set an initial delay to ensure that the first call to TimeTicks::Now()
407 // before incrementing the counter does not return a null value.
Matt Menke6dc08232019-10-03 18:00:28408 FastForwardBy(base::TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54409 }
410
dcheng67be2b1f2014-10-27 21:47:29411 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50412 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55413 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09414 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55415 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09416 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50417 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55418 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09419 }
420
Andrew Comminos1f2ff1cc2018-12-14 05:22:38421 void Check100ResponseTiming(bool use_spdy);
422
[email protected]202965992011-12-07 23:04:51423 // Either |write_failure| specifies a write failure or |read_failure|
424 // specifies a read failure when using a reused socket. In either case, the
425 // failure should cause the network transaction to resend the request, and the
426 // other argument should be NULL.
427 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
428 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52429
[email protected]a34f61ee2014-03-18 20:59:49430 // Either |write_failure| specifies a write failure or |read_failure|
431 // specifies a read failure when using a reused socket. In either case, the
432 // failure should cause the network transaction to resend the request, and the
433 // other argument should be NULL.
434 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10435 const MockRead* read_failure,
436 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49437
Ryan Sleevib8d7ea02018-05-07 20:01:01438 SimpleGetHelperResult SimpleGetHelperForData(
439 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15440 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52441
[email protected]ff007e162009-05-23 09:13:15442 HttpRequestInfo request;
443 request.method = "GET";
bncce36dca22015-04-21 22:11:23444 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10445 request.traffic_annotation =
446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52447
vishal.b62985ca92015-04-17 08:45:51448 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07449 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09450 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16451 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27452
Ryan Sleevib8d7ea02018-05-07 20:01:01453 for (auto* provider : providers) {
454 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29455 }
initial.commit586acc5fe2008-07-26 22:42:52456
[email protected]49639fa2011-12-20 23:22:41457 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52458
eroman24bc6a12015-05-06 19:55:48459 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16460 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01461 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52462
[email protected]ff007e162009-05-23 09:13:15463 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16464 out.total_received_bytes = trans.GetTotalReceivedBytes();
465 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25466
467 // Even in the failure cases that use this function, connections are always
468 // successfully established before the error.
bnc691fda62016-08-12 00:43:16469 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25470 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
471
[email protected]ff007e162009-05-23 09:13:15472 if (out.rv != OK)
473 return out;
474
bnc691fda62016-08-12 00:43:16475 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50476 // Can't use ASSERT_* inside helper functions like this, so
477 // return an error.
wezca1070932016-05-26 20:30:52478 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50479 out.rv = ERR_UNEXPECTED;
480 return out;
481 }
[email protected]ff007e162009-05-23 09:13:15482 out.status_line = response->headers->GetStatusLine();
483
Tsuyoshi Horo01faed62019-02-20 22:11:37484 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
485 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19486
ttuttled9dbc652015-09-29 20:00:59487 bool got_endpoint =
bnc691fda62016-08-12 00:43:16488 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59489 EXPECT_EQ(got_endpoint,
490 out.remote_endpoint_after_start.address().size() > 0);
491
bnc691fda62016-08-12 00:43:16492 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01493 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40494
Eric Roman79cc7552019-07-19 02:17:54495 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:39496 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00497 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
498 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39499 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00500 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
501 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15502
Eric Roman79cc7552019-07-19 02:17:54503 EXPECT_EQ("GET / HTTP/1.1\r\n",
504 GetStringValueFromParams(entries[pos], "line"));
[email protected]f3da152d2012-06-02 01:00:57505
bncce36dca22015-04-21 22:11:23506 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
Eric Roman79cc7552019-07-19 02:17:54507 GetHeaders(entries[pos].params));
[email protected]3deb9a52010-11-11 00:24:40508
bnc691fda62016-08-12 00:43:16509 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22510 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16511 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22512
bnc691fda62016-08-12 00:43:16513 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47514 return out;
[email protected]ff007e162009-05-23 09:13:15515 }
initial.commit586acc5fe2008-07-26 22:42:52516
Ryan Sleevib8d7ea02018-05-07 20:01:01517 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22518 MockWrite data_writes[] = {
519 MockWrite("GET / HTTP/1.1\r\n"
520 "Host: www.example.org\r\n"
521 "Connection: keep-alive\r\n\r\n"),
522 };
[email protected]5a60c8b2011-10-19 20:14:29523
Ryan Sleevib8d7ea02018-05-07 20:01:01524 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22525 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01526 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22527
Ryan Sleevib8d7ea02018-05-07 20:01:01528 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22529 return out;
[email protected]b8015c42013-12-24 15:18:19530 }
531
bnc032658ba2016-09-26 18:17:15532 void AddSSLSocketData() {
533 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49534 ssl_.ssl_info.cert =
535 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
536 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15537 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
538 }
539
[email protected]ff007e162009-05-23 09:13:15540 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
541 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52542
[email protected]ff007e162009-05-23 09:13:15543 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07544
[email protected]bb88e1d32013-05-03 23:11:07545 void CheckErrorIsPassedBack(int error, IoMode mode);
546
Matt Menked6fd2a52019-03-20 06:14:36547 const CommonConnectJobParams dummy_connect_job_params_;
548
Douglas Creager134b52e2018-11-09 18:00:14549 // These clocks are defined here, even though they're only used in the
550 // Reporting tests below, since they need to be destroyed after
551 // |session_deps_|.
552 base::SimpleTestClock clock_;
553 base::SimpleTestTickClock tick_clock_;
554
[email protected]4bd46222013-05-14 19:32:23555 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07556 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15557 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03558
559 // Original socket limits. Some tests set these. Safest to always restore
560 // them once each test has been run.
561 int old_max_group_sockets_;
562 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15563};
[email protected]231d5a32008-09-13 00:45:27564
[email protected]448d4ca52012-03-04 04:12:23565namespace {
566
ryansturm49a8cb12016-06-15 16:51:09567class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27568 public:
ryansturm49a8cb12016-06-15 16:51:09569 BeforeHeadersSentHandler()
570 : observed_before_headers_sent_with_proxy_(false),
571 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27572
ryansturm49a8cb12016-06-15 16:51:09573 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
574 HttpRequestHeaders* request_headers) {
575 observed_before_headers_sent_ = true;
576 if (!proxy_info.is_http() && !proxy_info.is_https() &&
577 !proxy_info.is_quic()) {
578 return;
579 }
580 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27581 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
582 }
583
ryansturm49a8cb12016-06-15 16:51:09584 bool observed_before_headers_sent_with_proxy() const {
585 return observed_before_headers_sent_with_proxy_;
586 }
587
588 bool observed_before_headers_sent() const {
589 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27590 }
591
592 std::string observed_proxy_server_uri() const {
593 return observed_proxy_server_uri_;
594 }
595
596 private:
ryansturm49a8cb12016-06-15 16:51:09597 bool observed_before_headers_sent_with_proxy_;
598 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27599 std::string observed_proxy_server_uri_;
600
ryansturm49a8cb12016-06-15 16:51:09601 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27602};
603
[email protected]15a5ccf82008-10-23 19:57:43604// Fill |str| with a long header list that consumes >= |size| bytes.
605void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51606 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19607 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
608 const int sizeof_row = strlen(row);
609 const int num_rows = static_cast<int>(
610 ceil(static_cast<float>(size) / sizeof_row));
611 const int sizeof_data = num_rows * sizeof_row;
612 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43613 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51614
[email protected]4ddaf2502008-10-23 18:26:19615 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43616 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19617}
618
thakis84dff942015-07-28 20:47:38619#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09620uint64_t MockGetMSTime() {
621 // Tue, 23 May 2017 20:13:07 +0000
622 return 131400439870000000;
623}
624
[email protected]385a4672009-03-11 22:21:29625// Alternative functions that eliminate randomness and dependency on the local
626// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37627void MockGenerateRandom(uint8_t* output, size_t n) {
628 // This is set to 0xaa because the client challenge for testing in
629 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
630 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29631}
632
[email protected]fe2bc6a2009-03-23 16:52:20633std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37634 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29635}
thakis84dff942015-07-28 20:47:38636#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29637
Matt Menked6fd2a52019-03-20 06:14:36638class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31639 public:
Matt Menked6fd2a52019-03-20 06:14:36640 explicit CaptureGroupIdTransportSocketPool(
641 const CommonConnectJobParams* common_connect_job_params)
642 : TransportClientSocketPool(0,
643 0,
644 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36645 ProxyServer::Direct(),
646 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52647 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18648
Matt Menkef6edce752019-03-19 17:21:56649 const ClientSocketPool::GroupId& last_group_id_received() const {
650 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49651 }
652
Tarun Bansal162eabe52018-01-20 01:16:39653 bool socket_requested() const { return socket_requested_; }
654
Matt Menke28ac03e2019-02-25 22:25:50655 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56656 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03657 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28658 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50659 RequestPriority priority,
660 const SocketTag& socket_tag,
661 ClientSocketPool::RespectLimits respect_limits,
662 ClientSocketHandle* handle,
663 CompletionOnceCallback callback,
664 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
665 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56666 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39667 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31668 return ERR_IO_PENDING;
669 }
Matt Menkef6edce752019-03-19 17:21:56670 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21671 ClientSocketHandle* handle,
672 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56673 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09674 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24675 int64_t generation) override {}
dmichaeld6e570d2014-12-18 22:30:57676 void CloseIdleSockets() override {}
Matt Menkef6edce752019-03-19 17:21:56677 void CloseIdleSocketsInGroup(
678 const ClientSocketPool::GroupId& group_id) override {}
dmichaeld6e570d2014-12-18 22:30:57679 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56680 size_t IdleSocketCountInGroup(
681 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31682 return 0;
683 }
Matt Menkef6edce752019-03-19 17:21:56684 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57685 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31686 return LOAD_STATE_IDLE;
687 }
[email protected]d80a4322009-08-14 07:07:49688
689 private:
Matt Menkef6edce752019-03-19 17:21:56690 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39691 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31692};
693
[email protected]231d5a32008-09-13 00:45:27694//-----------------------------------------------------------------------------
695
[email protected]79cb5c12011-09-12 13:12:04696// Helper functions for validating that AuthChallengeInfo's are correctly
697// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58698bool CheckBasicServerAuth(
699 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04700 if (!auth_challenge)
701 return false;
702 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43703 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04704 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19705 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04706 return true;
707}
708
David Benjamin2eb827f2019-04-29 18:31:04709bool CheckBasicSecureServerAuth(
710 const base::Optional<AuthChallengeInfo>& auth_challenge) {
711 if (!auth_challenge)
712 return false;
713 EXPECT_FALSE(auth_challenge->is_proxy);
714 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
715 EXPECT_EQ("MyRealm1", auth_challenge->realm);
716 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
717 return true;
718}
719
Emily Starkf2c9bbd2019-04-09 17:08:58720bool CheckBasicProxyAuth(
721 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04722 if (!auth_challenge)
723 return false;
724 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43725 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
726 EXPECT_EQ("MyRealm1", auth_challenge->realm);
727 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
728 return true;
729}
730
Emily Starkf2c9bbd2019-04-09 17:08:58731bool CheckBasicSecureProxyAuth(
732 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43733 if (!auth_challenge)
734 return false;
735 EXPECT_TRUE(auth_challenge->is_proxy);
736 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04737 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19738 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04739 return true;
740}
741
Emily Starkf2c9bbd2019-04-09 17:08:58742bool CheckDigestServerAuth(
743 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04744 if (!auth_challenge)
745 return false;
746 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43747 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04748 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19749 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04750 return true;
751}
752
thakis84dff942015-07-28 20:47:38753#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58754bool CheckNTLMServerAuth(
755 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04756 if (!auth_challenge)
757 return false;
758 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55759 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04760 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19761 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04762 return true;
763}
David Benjamin5cb91132018-04-06 05:54:49764
Emily Starkf2c9bbd2019-04-09 17:08:58765bool CheckNTLMProxyAuth(
766 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49767 if (!auth_challenge)
768 return false;
769 EXPECT_TRUE(auth_challenge->is_proxy);
770 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
771 EXPECT_EQ(std::string(), auth_challenge->realm);
772 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
773 return true;
774}
thakis84dff942015-07-28 20:47:38775#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04776
[email protected]448d4ca52012-03-04 04:12:23777} // namespace
778
Shivani Sharma8ae506c2019-07-21 21:08:27779// TODO(950069): Add testing for frame_origin in NetworkIsolationKey
780// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
781
bncd16676a2016-07-20 16:23:01782TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09783 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16784 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27785}
786
bncd16676a2016-07-20 16:23:01787TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27788 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35789 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
790 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06791 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27792 };
Ryan Sleevib8d7ea02018-05-07 20:01:01793 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01794 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27795 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
796 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01797 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22798 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47799 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59800
801 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27802}
803
804// Response with no status line.
bncd16676a2016-07-20 16:23:01805TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27806 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35807 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06808 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27809 };
Ryan Sleevib8d7ea02018-05-07 20:01:01810 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41811 EXPECT_THAT(out.rv, IsOk());
812 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
813 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01814 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41815 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27816}
817
mmenkea7da6da2016-09-01 21:56:52818// Response with no status line, and a weird port. Should fail by default.
819TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
820 MockRead data_reads[] = {
821 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
822 };
823
Ryan Sleevib8d7ea02018-05-07 20:01:01824 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52825 session_deps_.socket_factory->AddSocketDataProvider(&data);
826
827 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
828
krasinc06a72a2016-12-21 03:42:46829 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58830 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19831 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52832
mmenkea7da6da2016-09-01 21:56:52833 request.method = "GET";
834 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10835 request.traffic_annotation =
836 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
837
mmenkea7da6da2016-09-01 21:56:52838 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20839 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52840 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
841}
842
Shivani Sharmafdcaefd2017-11-02 00:12:26843// Tests that request info can be destroyed after the headers phase is complete.
844TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
845 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
846 auto trans =
847 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
848
849 MockRead data_reads[] = {
850 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
851 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
852 };
Ryan Sleevib8d7ea02018-05-07 20:01:01853 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26854 session_deps_.socket_factory->AddSocketDataProvider(&data);
855
856 TestCompletionCallback callback;
857
858 {
859 auto request = std::make_unique<HttpRequestInfo>();
860 request->method = "GET";
861 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10862 request->traffic_annotation =
863 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26864
865 int rv =
866 trans->Start(request.get(), callback.callback(), NetLogWithSource());
867
868 EXPECT_THAT(callback.GetResult(rv), IsOk());
869 } // Let request info be destroyed.
870
871 trans.reset();
872}
873
[email protected]231d5a32008-09-13 00:45:27874// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01875TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27876 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35877 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06878 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27879 };
Ryan Sleevib8d7ea02018-05-07 20:01:01880 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01881 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27882 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
883 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01884 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22885 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27886}
887
888// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01889TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27890 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35891 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06892 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27893 };
Ryan Sleevib8d7ea02018-05-07 20:01:01894 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01895 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27896 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
897 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01898 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22899 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27900}
901
902// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01903TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27904 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35905 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06906 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27907 };
Ryan Sleevib8d7ea02018-05-07 20:01:01908 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41909 EXPECT_THAT(out.rv, IsOk());
910 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
911 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01912 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41913 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27914}
915
916// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01917TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27918 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35919 MockRead("\n"),
920 MockRead("\n"),
921 MockRead("Q"),
922 MockRead("J"),
923 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06924 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27925 };
Ryan Sleevib8d7ea02018-05-07 20:01:01926 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01927 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27928 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
929 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01930 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22931 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27932}
933
934// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01935TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27936 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35937 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06938 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27939 };
Ryan Sleevib8d7ea02018-05-07 20:01:01940 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41941 EXPECT_THAT(out.rv, IsOk());
942 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
943 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01944 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41945 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52946}
947
[email protected]f9d44aa2008-09-23 23:57:17948// Simulate a 204 response, lacking a Content-Length header, sent over a
949// persistent connection. The response should still terminate since a 204
950// cannot have a response body.
bncd16676a2016-07-20 16:23:01951TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19952 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17953 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35954 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19955 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06956 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17957 };
Ryan Sleevib8d7ea02018-05-07 20:01:01958 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01959 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:17960 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
961 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01962 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22963 int64_t response_size = reads_size - strlen(junk);
964 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17965}
966
[email protected]0877e3d2009-10-17 22:29:57967// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:01968TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19969 std::string final_chunk = "0\r\n\r\n";
970 std::string extra_data = "HTTP/1.1 200 OK\r\n";
971 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57972 MockRead data_reads[] = {
973 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
974 MockRead("5\r\nHello\r\n"),
975 MockRead("1\r\n"),
976 MockRead(" \r\n"),
977 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19978 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06979 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57980 };
Ryan Sleevib8d7ea02018-05-07 20:01:01981 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01982 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:57983 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
984 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01985 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22986 int64_t response_size = reads_size - extra_data.size();
987 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57988}
989
[email protected]9fe44f52010-09-23 18:36:00990// Next tests deal with http://crbug.com/56344.
991
bncd16676a2016-07-20 16:23:01992TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00993 MultipleContentLengthHeadersNoTransferEncoding) {
994 MockRead data_reads[] = {
995 MockRead("HTTP/1.1 200 OK\r\n"),
996 MockRead("Content-Length: 10\r\n"),
997 MockRead("Content-Length: 5\r\n\r\n"),
998 };
Ryan Sleevib8d7ea02018-05-07 20:01:01999 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011000 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001001}
1002
bncd16676a2016-07-20 16:23:011003TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041004 DuplicateContentLengthHeadersNoTransferEncoding) {
1005 MockRead data_reads[] = {
1006 MockRead("HTTP/1.1 200 OK\r\n"),
1007 MockRead("Content-Length: 5\r\n"),
1008 MockRead("Content-Length: 5\r\n\r\n"),
1009 MockRead("Hello"),
1010 };
Ryan Sleevib8d7ea02018-05-07 20:01:011011 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011012 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041013 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1014 EXPECT_EQ("Hello", out.response_data);
1015}
1016
bncd16676a2016-07-20 16:23:011017TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041018 ComplexContentLengthHeadersNoTransferEncoding) {
1019 // More than 2 dupes.
1020 {
1021 MockRead data_reads[] = {
1022 MockRead("HTTP/1.1 200 OK\r\n"),
1023 MockRead("Content-Length: 5\r\n"),
1024 MockRead("Content-Length: 5\r\n"),
1025 MockRead("Content-Length: 5\r\n\r\n"),
1026 MockRead("Hello"),
1027 };
Ryan Sleevib8d7ea02018-05-07 20:01:011028 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011029 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041030 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1031 EXPECT_EQ("Hello", out.response_data);
1032 }
1033 // HTTP/1.0
1034 {
1035 MockRead data_reads[] = {
1036 MockRead("HTTP/1.0 200 OK\r\n"),
1037 MockRead("Content-Length: 5\r\n"),
1038 MockRead("Content-Length: 5\r\n"),
1039 MockRead("Content-Length: 5\r\n\r\n"),
1040 MockRead("Hello"),
1041 };
Ryan Sleevib8d7ea02018-05-07 20:01:011042 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011043 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041044 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1045 EXPECT_EQ("Hello", out.response_data);
1046 }
1047 // 2 dupes and one mismatched.
1048 {
1049 MockRead data_reads[] = {
1050 MockRead("HTTP/1.1 200 OK\r\n"),
1051 MockRead("Content-Length: 10\r\n"),
1052 MockRead("Content-Length: 10\r\n"),
1053 MockRead("Content-Length: 5\r\n\r\n"),
1054 };
Ryan Sleevib8d7ea02018-05-07 20:01:011055 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011056 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041057 }
1058}
1059
bncd16676a2016-07-20 16:23:011060TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001061 MultipleContentLengthHeadersTransferEncoding) {
1062 MockRead data_reads[] = {
1063 MockRead("HTTP/1.1 200 OK\r\n"),
1064 MockRead("Content-Length: 666\r\n"),
1065 MockRead("Content-Length: 1337\r\n"),
1066 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1067 MockRead("5\r\nHello\r\n"),
1068 MockRead("1\r\n"),
1069 MockRead(" \r\n"),
1070 MockRead("5\r\nworld\r\n"),
1071 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061072 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001073 };
Ryan Sleevib8d7ea02018-05-07 20:01:011074 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011075 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001076 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1077 EXPECT_EQ("Hello world", out.response_data);
1078}
1079
[email protected]1628fe92011-10-04 23:04:551080// Next tests deal with http://crbug.com/98895.
1081
1082// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011083TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551084 MockRead data_reads[] = {
1085 MockRead("HTTP/1.1 200 OK\r\n"),
1086 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1087 MockRead("Content-Length: 5\r\n\r\n"),
1088 MockRead("Hello"),
1089 };
Ryan Sleevib8d7ea02018-05-07 20:01:011090 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011091 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551092 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1093 EXPECT_EQ("Hello", out.response_data);
1094}
1095
[email protected]54a9c6e52012-03-21 20:10:591096// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011097TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551098 MockRead data_reads[] = {
1099 MockRead("HTTP/1.1 200 OK\r\n"),
1100 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1101 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1102 MockRead("Content-Length: 5\r\n\r\n"),
1103 MockRead("Hello"),
1104 };
Ryan Sleevib8d7ea02018-05-07 20:01:011105 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011106 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591107 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1108 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551109}
1110
1111// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011112TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551113 MockRead data_reads[] = {
1114 MockRead("HTTP/1.1 200 OK\r\n"),
1115 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1116 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1117 MockRead("Content-Length: 5\r\n\r\n"),
1118 MockRead("Hello"),
1119 };
Ryan Sleevib8d7ea02018-05-07 20:01:011120 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011121 EXPECT_THAT(out.rv,
1122 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551123}
1124
[email protected]54a9c6e52012-03-21 20:10:591125// Checks that two identical Location headers result in no error.
1126// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011127TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551128 MockRead data_reads[] = {
1129 MockRead("HTTP/1.1 302 Redirect\r\n"),
1130 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591131 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551132 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061133 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551134 };
1135
1136 HttpRequestInfo request;
1137 request.method = "GET";
1138 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101139 request.traffic_annotation =
1140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551141
danakj1fd259a02016-04-16 03:17:091142 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161143 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551144
Ryan Sleevib8d7ea02018-05-07 20:01:011145 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071146 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551147
[email protected]49639fa2011-12-20 23:22:411148 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551149
tfarina42834112016-09-22 13:38:201150 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011151 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551152
robpercival214763f2016-07-01 23:27:011153 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551154
bnc691fda62016-08-12 00:43:161155 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521156 ASSERT_TRUE(response);
1157 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551158 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1159 std::string url;
1160 EXPECT_TRUE(response->headers->IsRedirect(&url));
1161 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471162 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551163}
1164
[email protected]1628fe92011-10-04 23:04:551165// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011166TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551167 MockRead data_reads[] = {
1168 MockRead("HTTP/1.1 302 Redirect\r\n"),
1169 MockRead("Location: http://good.com/\r\n"),
1170 MockRead("Location: http://evil.com/\r\n"),
1171 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061172 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551173 };
Ryan Sleevib8d7ea02018-05-07 20:01:011174 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011175 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551176}
1177
[email protected]ef0faf2e72009-03-05 23:27:231178// Do a request using the HEAD method. Verify that we don't try to read the
1179// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011180TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421181 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231182 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231183 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101184 request.traffic_annotation =
1185 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231186
danakj1fd259a02016-04-16 03:17:091187 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161188 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091189 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161190 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091191 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1192 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271193
[email protected]ef0faf2e72009-03-05 23:27:231194 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131195 MockWrite("HEAD / HTTP/1.1\r\n"
1196 "Host: www.example.org\r\n"
1197 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231198 };
1199 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231200 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1201 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231202
mmenked39192ee2015-12-09 00:57:231203 // No response body because the test stops reading here.
1204 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231205 };
1206
Ryan Sleevib8d7ea02018-05-07 20:01:011207 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071208 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231209
[email protected]49639fa2011-12-20 23:22:411210 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231211
tfarina42834112016-09-22 13:38:201212 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011213 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231214
1215 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011216 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231217
bnc691fda62016-08-12 00:43:161218 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521219 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231220
1221 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521222 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231223 EXPECT_EQ(1234, response->headers->GetContentLength());
1224 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471225 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091226 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1227 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231228
1229 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101230 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231231 bool has_server_header = response->headers->EnumerateHeader(
1232 &iter, "Server", &server_header);
1233 EXPECT_TRUE(has_server_header);
1234 EXPECT_EQ("Blah", server_header);
1235
1236 // Reading should give EOF right away, since there is no message body
1237 // (despite non-zero content-length).
1238 std::string response_data;
bnc691fda62016-08-12 00:43:161239 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011240 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231241 EXPECT_EQ("", response_data);
1242}
1243
bncd16676a2016-07-20 16:23:011244TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091245 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521246
1247 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351248 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1249 MockRead("hello"),
1250 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1251 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061252 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521253 };
Ryan Sleevib8d7ea02018-05-07 20:01:011254 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071255 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521256
[email protected]0b0bf032010-09-21 18:08:501257 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521258 "hello", "world"
1259 };
1260
1261 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421262 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521263 request.method = "GET";
bncce36dca22015-04-21 22:11:231264 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101265 request.traffic_annotation =
1266 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521267
bnc691fda62016-08-12 00:43:161268 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271269
[email protected]49639fa2011-12-20 23:22:411270 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521271
tfarina42834112016-09-22 13:38:201272 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011273 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521274
1275 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011276 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521277
bnc691fda62016-08-12 00:43:161278 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521279 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521280
wezca1070932016-05-26 20:30:521281 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251282 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471283 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521284
1285 std::string response_data;
bnc691fda62016-08-12 00:43:161286 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011287 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251288 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521289 }
1290}
1291
bncd16676a2016-07-20 16:23:011292TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091293 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221294 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191295 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221296 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271297
[email protected]1c773ea12009-04-28 19:58:421298 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521299 request.method = "POST";
1300 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271301 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:101302 request.traffic_annotation =
1303 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521304
shivanishab9a143952016-09-19 17:23:411305 // Check the upload progress returned before initialization is correct.
1306 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1307 EXPECT_EQ(0u, progress.size());
1308 EXPECT_EQ(0u, progress.position());
1309
danakj1fd259a02016-04-16 03:17:091310 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161311 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271312
initial.commit586acc5fe2008-07-26 22:42:521313 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351314 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1315 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1316 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061317 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521318 };
Ryan Sleevib8d7ea02018-05-07 20:01:011319 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071320 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521321
[email protected]49639fa2011-12-20 23:22:411322 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521323
tfarina42834112016-09-22 13:38:201324 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011325 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521326
1327 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011328 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521329
bnc691fda62016-08-12 00:43:161330 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521331 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521332
wezca1070932016-05-26 20:30:521333 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251334 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521335
1336 std::string response_data;
bnc691fda62016-08-12 00:43:161337 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011338 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251339 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521340}
1341
[email protected]3a2d3662009-03-27 03:49:141342// This test is almost the same as Ignores100 above, but the response contains
1343// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571344// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011345TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421346 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141347 request.method = "GET";
1348 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101349 request.traffic_annotation =
1350 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141351
danakj1fd259a02016-04-16 03:17:091352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161353 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271354
[email protected]3a2d3662009-03-27 03:49:141355 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571356 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1357 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141358 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061359 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141360 };
Ryan Sleevib8d7ea02018-05-07 20:01:011361 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071362 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141363
[email protected]49639fa2011-12-20 23:22:411364 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141365
tfarina42834112016-09-22 13:38:201366 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011367 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141368
1369 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011370 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141371
bnc691fda62016-08-12 00:43:161372 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521373 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141374
wezca1070932016-05-26 20:30:521375 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141376 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1377
1378 std::string response_data;
bnc691fda62016-08-12 00:43:161379 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011380 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141381 EXPECT_EQ("hello world", response_data);
1382}
1383
Andrew Comminos517a92c2019-01-14 17:49:561384TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1385 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381386 base::TimeDelta::FromMilliseconds(10);
1387
1388 HttpRequestInfo request;
1389 request.method = "GET";
1390 request.url = GURL("http://www.foo.com/");
1391 request.traffic_annotation =
1392 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1393
1394 std::vector<MockWrite> data_writes = {
1395 MockWrite(ASYNC, 0,
1396 "GET / HTTP/1.1\r\n"
1397 "Host: www.foo.com\r\n"
1398 "Connection: keep-alive\r\n\r\n"),
1399 };
1400
1401 std::vector<MockRead> data_reads = {
1402 // Write one byte of the status line, followed by a pause.
1403 MockRead(ASYNC, 1, "H"),
1404 MockRead(ASYNC, ERR_IO_PENDING, 2),
1405 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1406 MockRead(ASYNC, 4, "hello world"),
1407 MockRead(SYNCHRONOUS, OK, 5),
1408 };
1409
1410 SequencedSocketData data(data_reads, data_writes);
1411 session_deps_.socket_factory->AddSocketDataProvider(&data);
1412
1413 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1414
1415 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1416
1417 TestCompletionCallback callback;
1418
1419 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1420 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1421
1422 data.RunUntilPaused();
1423 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561424 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381425 data.Resume();
1426
1427 rv = callback.WaitForResult();
1428 EXPECT_THAT(rv, IsOk());
1429
1430 const HttpResponseInfo* response = trans.GetResponseInfo();
1431 ASSERT_TRUE(response);
1432
1433 EXPECT_TRUE(response->headers);
1434 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1435
1436 LoadTimingInfo load_timing_info;
1437 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1438 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1439 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561440 // Ensure we didn't include the delay in the TTFB time.
1441 EXPECT_EQ(load_timing_info.receive_headers_start,
1442 load_timing_info.connect_timing.connect_end);
1443 // Ensure that the mock clock advanced at all.
1444 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1445 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381446
1447 std::string response_data;
1448 rv = ReadTransaction(&trans, &response_data);
1449 EXPECT_THAT(rv, IsOk());
1450 EXPECT_EQ("hello world", response_data);
1451}
1452
1453// Tests that the time-to-first-byte reported in a transaction's load timing
1454// info uses the first response, even if 1XX/informational.
1455void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561456 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381457 base::TimeDelta::FromMilliseconds(10);
1458
1459 HttpRequestInfo request;
1460 request.method = "GET";
1461 request.url = GURL("https://www.foo.com/");
1462 request.traffic_annotation =
1463 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1464
1465 SSLSocketDataProvider ssl(ASYNC, OK);
1466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1467
1468 std::vector<MockWrite> data_writes;
1469 std::vector<MockRead> data_reads;
1470
1471 spdy::SpdySerializedFrame spdy_req(
1472 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1473
1474 spdy::SpdyHeaderBlock spdy_resp1_headers;
1475 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1476 spdy::SpdySerializedFrame spdy_resp1(
1477 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1478 spdy::SpdySerializedFrame spdy_resp2(
1479 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1480 spdy::SpdySerializedFrame spdy_data(
1481 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1482
1483 if (use_spdy) {
1484 ssl.next_proto = kProtoHTTP2;
1485
1486 data_writes = {CreateMockWrite(spdy_req, 0)};
1487
1488 data_reads = {
1489 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1490 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1491 MockRead(SYNCHRONOUS, OK, 5),
1492 };
1493 } else {
1494 data_writes = {
1495 MockWrite(ASYNC, 0,
1496 "GET / HTTP/1.1\r\n"
1497 "Host: www.foo.com\r\n"
1498 "Connection: keep-alive\r\n\r\n"),
1499 };
1500
1501 data_reads = {
1502 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1503 MockRead(ASYNC, ERR_IO_PENDING, 2),
1504
1505 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1506 MockRead(ASYNC, 4, "hello world"),
1507 MockRead(SYNCHRONOUS, OK, 5),
1508 };
1509 }
1510
1511 SequencedSocketData data(data_reads, data_writes);
1512 session_deps_.socket_factory->AddSocketDataProvider(&data);
1513
1514 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1515
1516 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1517
1518 TestCompletionCallback callback;
1519
1520 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1521 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1522
1523 data.RunUntilPaused();
1524 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1525 // the delay before parsing the 200 response.
1526 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561527 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381528 data.Resume();
1529
1530 rv = callback.WaitForResult();
1531 EXPECT_THAT(rv, IsOk());
1532
1533 const HttpResponseInfo* response = trans.GetResponseInfo();
1534 ASSERT_TRUE(response);
1535
1536 LoadTimingInfo load_timing_info;
1537 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1538 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1539 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561540 // Ensure we didn't include the delay in the TTFB time.
1541 EXPECT_EQ(load_timing_info.receive_headers_start,
1542 load_timing_info.connect_timing.connect_end);
1543 // Ensure that the mock clock advanced at all.
1544 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1545 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381546
1547 std::string response_data;
1548 rv = ReadTransaction(&trans, &response_data);
1549 EXPECT_THAT(rv, IsOk());
1550 EXPECT_EQ("hello world", response_data);
1551}
1552
Andrew Comminos517a92c2019-01-14 17:49:561553TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381554 Check100ResponseTiming(false /* use_spdy */);
1555}
1556
Andrew Comminos517a92c2019-01-14 17:49:561557TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381558 Check100ResponseTiming(true /* use_spdy */);
1559}
1560
bncd16676a2016-07-20 16:23:011561TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081562 HttpRequestInfo request;
1563 request.method = "POST";
1564 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101565 request.traffic_annotation =
1566 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081567
danakj1fd259a02016-04-16 03:17:091568 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081570
1571 MockRead data_reads[] = {
1572 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1573 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381574 };
Ryan Sleevib8d7ea02018-05-07 20:01:011575 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081576 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381577
zmo9528c9f42015-08-04 22:12:081578 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381579
tfarina42834112016-09-22 13:38:201580 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011581 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381582
zmo9528c9f42015-08-04 22:12:081583 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011584 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381585
zmo9528c9f42015-08-04 22:12:081586 std::string response_data;
bnc691fda62016-08-12 00:43:161587 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011588 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081589 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381590}
1591
bncd16676a2016-07-20 16:23:011592TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381593 HttpRequestInfo request;
1594 request.method = "POST";
1595 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101596 request.traffic_annotation =
1597 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381598
danakj1fd259a02016-04-16 03:17:091599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161600 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271601
[email protected]ee9410e72010-01-07 01:42:381602 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061603 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381604 };
Ryan Sleevib8d7ea02018-05-07 20:01:011605 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071606 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381607
[email protected]49639fa2011-12-20 23:22:411608 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381609
tfarina42834112016-09-22 13:38:201610 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011611 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381612
1613 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011614 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381615}
1616
[email protected]23e482282013-06-14 16:08:021617void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511618 const MockWrite* write_failure,
1619 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421620 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521621 request.method = "GET";
1622 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101623 request.traffic_annotation =
1624 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521625
vishal.b62985ca92015-04-17 08:45:511626 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071627 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091628 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271629
[email protected]202965992011-12-07 23:04:511630 // Written data for successfully sending both requests.
1631 MockWrite data1_writes[] = {
1632 MockWrite("GET / HTTP/1.1\r\n"
1633 "Host: www.foo.com\r\n"
1634 "Connection: keep-alive\r\n\r\n"),
1635 MockWrite("GET / HTTP/1.1\r\n"
1636 "Host: www.foo.com\r\n"
1637 "Connection: keep-alive\r\n\r\n")
1638 };
1639
1640 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521641 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351642 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1643 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061644 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521645 };
[email protected]202965992011-12-07 23:04:511646
1647 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491648 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511649 data1_writes[1] = *write_failure;
1650 } else {
1651 ASSERT_TRUE(read_failure);
1652 data1_reads[2] = *read_failure;
1653 }
1654
Ryan Sleevib8d7ea02018-05-07 20:01:011655 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071656 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521657
1658 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351659 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1660 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061661 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521662 };
Ryan Sleevib8d7ea02018-05-07 20:01:011663 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071664 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521665
thestig9d3bb0c2015-01-24 00:49:511666 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521667 "hello", "world"
1668 };
1669
mikecironef22f9812016-10-04 03:40:191670 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521671 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411672 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521673
bnc691fda62016-08-12 00:43:161674 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521675
tfarina42834112016-09-22 13:38:201676 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011677 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521678
1679 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011680 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521681
[email protected]58e32bb2013-01-21 18:23:251682 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161683 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251684 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1685 if (i == 0) {
1686 first_socket_log_id = load_timing_info.socket_log_id;
1687 } else {
1688 // The second request should be using a new socket.
1689 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1690 }
1691
bnc691fda62016-08-12 00:43:161692 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521693 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521694
wezca1070932016-05-26 20:30:521695 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471696 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251697 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521698
1699 std::string response_data;
bnc691fda62016-08-12 00:43:161700 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011701 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251702 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521703 }
1704}
[email protected]3d2a59b2008-09-26 19:44:251705
[email protected]a34f61ee2014-03-18 20:59:491706void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1707 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101708 const MockRead* read_failure,
1709 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491710 HttpRequestInfo request;
1711 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101712 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101713 request.traffic_annotation =
1714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491715
vishal.b62985ca92015-04-17 08:45:511716 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491717 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091718 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491719
[email protected]09356c652014-03-25 15:36:101720 SSLSocketDataProvider ssl1(ASYNC, OK);
1721 SSLSocketDataProvider ssl2(ASYNC, OK);
1722 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361723 ssl1.next_proto = kProtoHTTP2;
1724 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101725 }
1726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491728
[email protected]09356c652014-03-25 15:36:101729 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131730 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491731 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131732 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351733 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131734 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191735 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491736
[email protected]09356c652014-03-25 15:36:101737 // HTTP/1.1 versions of the request and response.
1738 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1739 "Host: www.foo.com\r\n"
1740 "Connection: keep-alive\r\n\r\n";
1741 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1742 const char kHttpData[] = "hello";
1743
1744 std::vector<MockRead> data1_reads;
1745 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491746 if (write_failure) {
1747 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101748 data1_writes.push_back(*write_failure);
1749 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491750 } else {
1751 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101752 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411753 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101754 } else {
1755 data1_writes.push_back(MockWrite(kHttpRequest));
1756 }
1757 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491758 }
1759
Ryan Sleevib8d7ea02018-05-07 20:01:011760 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491761 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1762
[email protected]09356c652014-03-25 15:36:101763 std::vector<MockRead> data2_reads;
1764 std::vector<MockWrite> data2_writes;
1765
1766 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411767 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101768
bncdf80d44fd2016-07-15 20:27:411769 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1770 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101771 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1772 } else {
1773 data2_writes.push_back(
1774 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1775
1776 data2_reads.push_back(
1777 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1778 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1779 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1780 }
Ryan Sleevib8d7ea02018-05-07 20:01:011781 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491782 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1783
1784 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591785 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491786 // Wait for the preconnect to complete.
1787 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1788 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231789 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491790
1791 // Make the request.
1792 TestCompletionCallback callback;
1793
bnc691fda62016-08-12 00:43:161794 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491795
tfarina42834112016-09-22 13:38:201796 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011797 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491798
1799 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011800 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491801
1802 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161803 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101804 TestLoadTimingNotReused(
1805 load_timing_info,
1806 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491807
bnc691fda62016-08-12 00:43:161808 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521809 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491810
wezca1070932016-05-26 20:30:521811 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021812 if (response->was_fetched_via_spdy) {
1813 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1814 } else {
1815 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1816 }
[email protected]a34f61ee2014-03-18 20:59:491817
1818 std::string response_data;
bnc691fda62016-08-12 00:43:161819 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011820 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101821 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491822}
1823
Biljith Jayan45a41722017-08-16 18:43:141824// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:181825// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:141826// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1827TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1828 HttpRequestInfo request;
1829 request.method = "GET";
1830 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101831 request.traffic_annotation =
1832 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141833
1834 // Check whether we give up after the third try.
1835
1836 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131837 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141838 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131839 spdy::SpdySerializedFrame spdy_response_go_away(
1840 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011841 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1842 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141843
1844 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011845 StaticSocketDataProvider data1(data_read1, data_write);
1846 StaticSocketDataProvider data2(data_read1, data_write);
1847 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141848
1849 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1850 AddSSLSocketData();
1851 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1852 AddSSLSocketData();
1853 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1854 AddSSLSocketData();
1855
1856 TestCompletionCallback callback;
1857 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1858 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1859
1860 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1861 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1862
1863 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:181864 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:141865}
1866
1867TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1868 HttpRequestInfo request;
1869 request.method = "GET";
1870 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101871 request.traffic_annotation =
1872 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141873
1874 // Check whether we try atleast thrice before giving up.
1875
1876 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131877 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141878 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131879 spdy::SpdySerializedFrame spdy_response_go_away(
1880 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011881 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1882 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141883
1884 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131885 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141886 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131887 spdy::SpdySerializedFrame spdy_data(
1888 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141889 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1890 CreateMockRead(spdy_data, 2)};
1891
1892 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011893 StaticSocketDataProvider data1(data_read1, data_write);
1894 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141895 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011896 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141897
1898 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1899 AddSSLSocketData();
1900 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1901 AddSSLSocketData();
1902 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1903 AddSSLSocketData();
1904
1905 TestCompletionCallback callback;
1906 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1907 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1908
1909 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1910 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1911
1912 rv = callback.WaitForResult();
1913 EXPECT_THAT(rv, IsOk());
1914}
1915
bncd16676a2016-07-20 16:23:011916TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061917 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351918 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511919}
1920
bncd16676a2016-07-20 16:23:011921TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061922 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351923 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251924}
1925
bncd16676a2016-07-20 16:23:011926TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061927 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351928 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251929}
1930
[email protected]d58ceea82014-06-04 10:55:541931// Make sure that on a 408 response (Request Timeout), the request is retried,
1932// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011933TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541934 MockRead read_failure(SYNCHRONOUS,
1935 "HTTP/1.1 408 Request Timeout\r\n"
1936 "Connection: Keep-Alive\r\n"
1937 "Content-Length: 6\r\n\r\n"
1938 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351939 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:541940}
1941
bncd16676a2016-07-20 16:23:011942TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:491943 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351944 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:491945}
1946
bncd16676a2016-07-20 16:23:011947TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:491948 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351949 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491950}
1951
bncd16676a2016-07-20 16:23:011952TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:491953 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351954 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101955}
1956
bncd16676a2016-07-20 16:23:011957TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101958 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351959 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101960}
1961
[email protected]d58ceea82014-06-04 10:55:541962// Make sure that on a 408 response (Request Timeout), the request is retried,
1963// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:011964TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:541965 MockRead read_failure(SYNCHRONOUS,
1966 "HTTP/1.1 408 Request Timeout\r\n"
1967 "Connection: Keep-Alive\r\n"
1968 "Content-Length: 6\r\n\r\n"
1969 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351970 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
1971 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:541972}
1973
bncd16676a2016-07-20 16:23:011974TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:101975 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351976 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:101977}
1978
bncd16676a2016-07-20 16:23:011979TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:101980 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351981 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101982}
1983
bncd16676a2016-07-20 16:23:011984TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:101985 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351986 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101987}
1988
bncd16676a2016-07-20 16:23:011989TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101990 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351991 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491992}
1993
bncd16676a2016-07-20 16:23:011994TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421995 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251996 request.method = "GET";
bncce36dca22015-04-21 22:11:231997 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101998 request.traffic_annotation =
1999 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252000
danakj1fd259a02016-04-16 03:17:092001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162002 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272003
[email protected]3d2a59b2008-09-26 19:44:252004 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062005 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352006 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2007 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062008 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252009 };
Ryan Sleevib8d7ea02018-05-07 20:01:012010 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072011 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252012
[email protected]49639fa2011-12-20 23:22:412013 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252014
tfarina42834112016-09-22 13:38:202015 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012016 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252017
2018 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012019 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592020
2021 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162022 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592023 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252024}
2025
2026// What do various browsers do when the server closes a non-keepalive
2027// connection without sending any response header or body?
2028//
2029// IE7: error page
2030// Safari 3.1.2 (Windows): error page
2031// Firefox 3.0.1: blank page
2032// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422033// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2034// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012035TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252036 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062037 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352038 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2039 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062040 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252041 };
Ryan Sleevib8d7ea02018-05-07 20:01:012042 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012043 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252044}
[email protected]1826a402014-01-08 15:40:482045
[email protected]7a5378b2012-11-04 03:25:172046// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2047// tests. There was a bug causing HttpNetworkTransaction to hang in the
2048// destructor in such situations.
2049// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012050TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172051 HttpRequestInfo request;
2052 request.method = "GET";
bncce36dca22015-04-21 22:11:232053 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102054 request.traffic_annotation =
2055 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172056
danakj1fd259a02016-04-16 03:17:092057 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582058 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192059 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172060
2061 MockRead data_reads[] = {
2062 MockRead("HTTP/1.0 200 OK\r\n"),
2063 MockRead("Connection: keep-alive\r\n"),
2064 MockRead("Content-Length: 100\r\n\r\n"),
2065 MockRead("hello"),
2066 MockRead(SYNCHRONOUS, 0),
2067 };
Ryan Sleevib8d7ea02018-05-07 20:01:012068 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072069 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172070
2071 TestCompletionCallback callback;
2072
tfarina42834112016-09-22 13:38:202073 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012074 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172075
2076 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012077 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172078
Victor Costan9c7302b2018-08-27 16:39:442079 scoped_refptr<IOBufferWithSize> io_buf =
2080 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502081 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172082 if (rv == ERR_IO_PENDING)
2083 rv = callback.WaitForResult();
2084 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502085 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012086 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172087
2088 trans.reset();
fdoray92e35a72016-06-10 15:54:552089 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172090 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2091}
2092
bncd16676a2016-07-20 16:23:012093TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172094 HttpRequestInfo request;
2095 request.method = "GET";
bncce36dca22015-04-21 22:11:232096 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102097 request.traffic_annotation =
2098 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172099
danakj1fd259a02016-04-16 03:17:092100 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582101 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192102 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172103
2104 MockRead data_reads[] = {
2105 MockRead("HTTP/1.0 200 OK\r\n"),
2106 MockRead("Connection: keep-alive\r\n"),
2107 MockRead("Content-Length: 100\r\n\r\n"),
2108 MockRead(SYNCHRONOUS, 0),
2109 };
Ryan Sleevib8d7ea02018-05-07 20:01:012110 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072111 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172112
2113 TestCompletionCallback callback;
2114
tfarina42834112016-09-22 13:38:202115 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012116 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172117
2118 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012119 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172120
Victor Costan9c7302b2018-08-27 16:39:442121 scoped_refptr<IOBufferWithSize> io_buf(
2122 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502123 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172124 if (rv == ERR_IO_PENDING)
2125 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012126 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172127
2128 trans.reset();
fdoray92e35a72016-06-10 15:54:552129 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172130 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2131}
2132
[email protected]0b0bf032010-09-21 18:08:502133// Test that we correctly reuse a keep-alive connection after not explicitly
2134// reading the body.
bncd16676a2016-07-20 16:23:012135TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132136 HttpRequestInfo request;
2137 request.method = "GET";
2138 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102139 request.traffic_annotation =
2140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132141
vishal.b62985ca92015-04-17 08:45:512142 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072143 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092144 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272145
mmenkecc2298e2015-12-07 18:20:182146 const char* request_data =
2147 "GET / HTTP/1.1\r\n"
2148 "Host: www.foo.com\r\n"
2149 "Connection: keep-alive\r\n\r\n";
2150 MockWrite data_writes[] = {
2151 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2152 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2153 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2154 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2155 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2156 };
2157
[email protected]0b0bf032010-09-21 18:08:502158 // Note that because all these reads happen in the same
2159 // StaticSocketDataProvider, it shows that the same socket is being reused for
2160 // all transactions.
mmenkecc2298e2015-12-07 18:20:182161 MockRead data_reads[] = {
2162 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2163 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2164 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2165 MockRead(ASYNC, 7,
2166 "HTTP/1.1 302 Found\r\n"
2167 "Content-Length: 0\r\n\r\n"),
2168 MockRead(ASYNC, 9,
2169 "HTTP/1.1 302 Found\r\n"
2170 "Content-Length: 5\r\n\r\n"
2171 "hello"),
2172 MockRead(ASYNC, 11,
2173 "HTTP/1.1 301 Moved Permanently\r\n"
2174 "Content-Length: 0\r\n\r\n"),
2175 MockRead(ASYNC, 13,
2176 "HTTP/1.1 301 Moved Permanently\r\n"
2177 "Content-Length: 5\r\n\r\n"
2178 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132179
mmenkecc2298e2015-12-07 18:20:182180 // In the next two rounds, IsConnectedAndIdle returns false, due to
2181 // the set_busy_before_sync_reads(true) call, while the
2182 // HttpNetworkTransaction is being shut down, but the socket is still
2183 // reuseable. See http://crbug.com/544255.
2184 MockRead(ASYNC, 15,
2185 "HTTP/1.1 200 Hunky-Dory\r\n"
2186 "Content-Length: 5\r\n\r\n"),
2187 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132188
mmenkecc2298e2015-12-07 18:20:182189 MockRead(ASYNC, 18,
2190 "HTTP/1.1 200 Hunky-Dory\r\n"
2191 "Content-Length: 5\r\n\r\n"
2192 "he"),
2193 MockRead(SYNCHRONOUS, 19, "llo"),
2194
2195 // The body of the final request is actually read.
2196 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2197 MockRead(ASYNC, 22, "hello"),
2198 };
Ryan Sleevib8d7ea02018-05-07 20:01:012199 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182200 data.set_busy_before_sync_reads(true);
2201 session_deps_.socket_factory->AddSocketDataProvider(&data);
2202
Avi Drissman4365a4782018-12-28 19:26:242203 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502204 std::string response_lines[kNumUnreadBodies];
2205
mikecironef22f9812016-10-04 03:40:192206 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182207 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412208 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132209
Jeremy Roman0579ed62017-08-29 15:56:192210 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582211 session.get());
[email protected]fc31d6a42010-06-24 18:05:132212
tfarina42834112016-09-22 13:38:202213 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012214 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132215
[email protected]58e32bb2013-01-21 18:23:252216 LoadTimingInfo load_timing_info;
2217 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2218 if (i == 0) {
2219 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2220 first_socket_log_id = load_timing_info.socket_log_id;
2221 } else {
2222 TestLoadTimingReused(load_timing_info);
2223 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2224 }
2225
[email protected]fc31d6a42010-06-24 18:05:132226 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182227 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132228
mmenkecc2298e2015-12-07 18:20:182229 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502230 response_lines[i] = response->headers->GetStatusLine();
2231
mmenkecc2298e2015-12-07 18:20:182232 // Delete the transaction without reading the response bodies. Then spin
2233 // the message loop, so the response bodies are drained.
2234 trans.reset();
2235 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132236 }
[email protected]0b0bf032010-09-21 18:08:502237
2238 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182239 "HTTP/1.1 204 No Content",
2240 "HTTP/1.1 205 Reset Content",
2241 "HTTP/1.1 304 Not Modified",
2242 "HTTP/1.1 302 Found",
2243 "HTTP/1.1 302 Found",
2244 "HTTP/1.1 301 Moved Permanently",
2245 "HTTP/1.1 301 Moved Permanently",
2246 "HTTP/1.1 200 Hunky-Dory",
2247 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502248 };
2249
Avi Drissman4365a4782018-12-28 19:26:242250 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272251 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502252
2253 for (int i = 0; i < kNumUnreadBodies; ++i)
2254 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2255
[email protected]49639fa2011-12-20 23:22:412256 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162257 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202258 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012259 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162260 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182261 ASSERT_TRUE(response);
2262 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2264 std::string response_data;
bnc691fda62016-08-12 00:43:162265 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012266 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502267 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132268}
2269
mmenke5f94fda2016-06-02 20:54:132270// Sockets that receive extra data after a response is complete should not be
2271// reused.
bncd16676a2016-07-20 16:23:012272TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132273 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2274 MockWrite data_writes1[] = {
2275 MockWrite("HEAD / HTTP/1.1\r\n"
2276 "Host: www.borked.com\r\n"
2277 "Connection: keep-alive\r\n\r\n"),
2278 };
2279
2280 MockRead data_reads1[] = {
2281 MockRead("HTTP/1.1 200 OK\r\n"
2282 "Connection: keep-alive\r\n"
2283 "Content-Length: 22\r\n\r\n"
2284 "This server is borked."),
2285 };
2286
2287 MockWrite data_writes2[] = {
2288 MockWrite("GET /foo HTTP/1.1\r\n"
2289 "Host: www.borked.com\r\n"
2290 "Connection: keep-alive\r\n\r\n"),
2291 };
2292
2293 MockRead data_reads2[] = {
2294 MockRead("HTTP/1.1 200 OK\r\n"
2295 "Content-Length: 3\r\n\r\n"
2296 "foo"),
2297 };
Ryan Sleevib8d7ea02018-05-07 20:01:012298 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132299 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012300 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132301 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2302
2303 TestCompletionCallback callback;
2304 HttpRequestInfo request1;
2305 request1.method = "HEAD";
2306 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102307 request1.traffic_annotation =
2308 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132309
bnc87dcefc2017-05-25 12:47:582310 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192311 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202312 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012313 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132314
2315 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2316 ASSERT_TRUE(response1);
2317 ASSERT_TRUE(response1->headers);
2318 EXPECT_EQ(200, response1->headers->response_code());
2319 EXPECT_TRUE(response1->headers->IsKeepAlive());
2320
2321 std::string response_data1;
robpercival214763f2016-07-01 23:27:012322 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132323 EXPECT_EQ("", response_data1);
2324 // Deleting the transaction attempts to release the socket back into the
2325 // socket pool.
2326 trans1.reset();
2327
2328 HttpRequestInfo request2;
2329 request2.method = "GET";
2330 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102331 request2.traffic_annotation =
2332 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132333
bnc87dcefc2017-05-25 12:47:582334 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192335 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202336 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012337 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132338
2339 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2340 ASSERT_TRUE(response2);
2341 ASSERT_TRUE(response2->headers);
2342 EXPECT_EQ(200, response2->headers->response_code());
2343
2344 std::string response_data2;
robpercival214763f2016-07-01 23:27:012345 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132346 EXPECT_EQ("foo", response_data2);
2347}
2348
bncd16676a2016-07-20 16:23:012349TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132350 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2351 MockWrite data_writes1[] = {
2352 MockWrite("GET / HTTP/1.1\r\n"
2353 "Host: www.borked.com\r\n"
2354 "Connection: keep-alive\r\n\r\n"),
2355 };
2356
2357 MockRead data_reads1[] = {
2358 MockRead("HTTP/1.1 200 OK\r\n"
2359 "Connection: keep-alive\r\n"
2360 "Content-Length: 22\r\n\r\n"
2361 "This server is borked."
2362 "Bonus data!"),
2363 };
2364
2365 MockWrite data_writes2[] = {
2366 MockWrite("GET /foo HTTP/1.1\r\n"
2367 "Host: www.borked.com\r\n"
2368 "Connection: keep-alive\r\n\r\n"),
2369 };
2370
2371 MockRead data_reads2[] = {
2372 MockRead("HTTP/1.1 200 OK\r\n"
2373 "Content-Length: 3\r\n\r\n"
2374 "foo"),
2375 };
Ryan Sleevib8d7ea02018-05-07 20:01:012376 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132377 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012378 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132379 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2380
2381 TestCompletionCallback callback;
2382 HttpRequestInfo request1;
2383 request1.method = "GET";
2384 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102385 request1.traffic_annotation =
2386 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132387
bnc87dcefc2017-05-25 12:47:582388 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192389 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202390 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012391 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132392
2393 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2394 ASSERT_TRUE(response1);
2395 ASSERT_TRUE(response1->headers);
2396 EXPECT_EQ(200, response1->headers->response_code());
2397 EXPECT_TRUE(response1->headers->IsKeepAlive());
2398
2399 std::string response_data1;
robpercival214763f2016-07-01 23:27:012400 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132401 EXPECT_EQ("This server is borked.", response_data1);
2402 // Deleting the transaction attempts to release the socket back into the
2403 // socket pool.
2404 trans1.reset();
2405
2406 HttpRequestInfo request2;
2407 request2.method = "GET";
2408 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102409 request2.traffic_annotation =
2410 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132411
bnc87dcefc2017-05-25 12:47:582412 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192413 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202414 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012415 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132416
2417 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2418 ASSERT_TRUE(response2);
2419 ASSERT_TRUE(response2->headers);
2420 EXPECT_EQ(200, response2->headers->response_code());
2421
2422 std::string response_data2;
robpercival214763f2016-07-01 23:27:012423 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132424 EXPECT_EQ("foo", response_data2);
2425}
2426
bncd16676a2016-07-20 16:23:012427TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132428 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2429 MockWrite data_writes1[] = {
2430 MockWrite("GET / HTTP/1.1\r\n"
2431 "Host: www.borked.com\r\n"
2432 "Connection: keep-alive\r\n\r\n"),
2433 };
2434
2435 MockRead data_reads1[] = {
2436 MockRead("HTTP/1.1 200 OK\r\n"
2437 "Connection: keep-alive\r\n"
2438 "Transfer-Encoding: chunked\r\n\r\n"),
2439 MockRead("16\r\nThis server is borked.\r\n"),
2440 MockRead("0\r\n\r\nBonus data!"),
2441 };
2442
2443 MockWrite data_writes2[] = {
2444 MockWrite("GET /foo HTTP/1.1\r\n"
2445 "Host: www.borked.com\r\n"
2446 "Connection: keep-alive\r\n\r\n"),
2447 };
2448
2449 MockRead data_reads2[] = {
2450 MockRead("HTTP/1.1 200 OK\r\n"
2451 "Content-Length: 3\r\n\r\n"
2452 "foo"),
2453 };
Ryan Sleevib8d7ea02018-05-07 20:01:012454 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132455 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012456 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132457 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2458
2459 TestCompletionCallback callback;
2460 HttpRequestInfo request1;
2461 request1.method = "GET";
2462 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102463 request1.traffic_annotation =
2464 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132465
bnc87dcefc2017-05-25 12:47:582466 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192467 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202468 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012469 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132470
2471 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2472 ASSERT_TRUE(response1);
2473 ASSERT_TRUE(response1->headers);
2474 EXPECT_EQ(200, response1->headers->response_code());
2475 EXPECT_TRUE(response1->headers->IsKeepAlive());
2476
2477 std::string response_data1;
robpercival214763f2016-07-01 23:27:012478 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132479 EXPECT_EQ("This server is borked.", response_data1);
2480 // Deleting the transaction attempts to release the socket back into the
2481 // socket pool.
2482 trans1.reset();
2483
2484 HttpRequestInfo request2;
2485 request2.method = "GET";
2486 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102487 request2.traffic_annotation =
2488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132489
bnc87dcefc2017-05-25 12:47:582490 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192491 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202492 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012493 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132494
2495 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2496 ASSERT_TRUE(response2);
2497 ASSERT_TRUE(response2->headers);
2498 EXPECT_EQ(200, response2->headers->response_code());
2499
2500 std::string response_data2;
robpercival214763f2016-07-01 23:27:012501 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132502 EXPECT_EQ("foo", response_data2);
2503}
2504
2505// This is a little different from the others - it tests the case that the
2506// HttpStreamParser doesn't know if there's extra data on a socket or not when
2507// the HttpNetworkTransaction is torn down, because the response body hasn't
2508// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012509TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132510 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2511 MockWrite data_writes1[] = {
2512 MockWrite("GET / HTTP/1.1\r\n"
2513 "Host: www.borked.com\r\n"
2514 "Connection: keep-alive\r\n\r\n"),
2515 };
2516
2517 MockRead data_reads1[] = {
2518 MockRead("HTTP/1.1 200 OK\r\n"
2519 "Connection: keep-alive\r\n"
2520 "Transfer-Encoding: chunked\r\n\r\n"),
2521 MockRead("16\r\nThis server is borked.\r\n"),
2522 MockRead("0\r\n\r\nBonus data!"),
2523 };
Ryan Sleevib8d7ea02018-05-07 20:01:012524 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132525 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2526
2527 TestCompletionCallback callback;
2528 HttpRequestInfo request1;
2529 request1.method = "GET";
2530 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102531 request1.traffic_annotation =
2532 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132533
bnc87dcefc2017-05-25 12:47:582534 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192535 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582536 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012537 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132538
bnc87dcefc2017-05-25 12:47:582539 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132540 ASSERT_TRUE(response1);
2541 ASSERT_TRUE(response1->headers);
2542 EXPECT_EQ(200, response1->headers->response_code());
2543 EXPECT_TRUE(response1->headers->IsKeepAlive());
2544
2545 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2546 // response body.
bnc87dcefc2017-05-25 12:47:582547 trans.reset();
mmenke5f94fda2016-06-02 20:54:132548
2549 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2550 // socket can't be reused, rather than returning it to the socket pool.
2551 base::RunLoop().RunUntilIdle();
2552
2553 // There should be no idle sockets in the pool.
2554 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2555}
2556
[email protected]038e9a32008-10-08 22:40:162557// Test the request-challenge-retry sequence for basic auth.
2558// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012559TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422560 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162561 request.method = "GET";
bncce36dca22015-04-21 22:11:232562 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102563 request.traffic_annotation =
2564 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162565
vishal.b62985ca92015-04-17 08:45:512566 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072567 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092568 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272570
[email protected]f9ee6b52008-11-08 06:46:232571 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232572 MockWrite(
2573 "GET / HTTP/1.1\r\n"
2574 "Host: www.example.org\r\n"
2575 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232576 };
2577
[email protected]038e9a32008-10-08 22:40:162578 MockRead data_reads1[] = {
2579 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2580 // Give a couple authenticate options (only the middle one is actually
2581 // supported).
[email protected]22927ad2009-09-21 19:56:192582 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162583 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2584 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2585 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2586 // Large content-length -- won't matter, as connection will be reset.
2587 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062588 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162589 };
2590
2591 // After calling trans->RestartWithAuth(), this is the request we should
2592 // be issuing -- the final header line contains the credentials.
2593 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232594 MockWrite(
2595 "GET / HTTP/1.1\r\n"
2596 "Host: www.example.org\r\n"
2597 "Connection: keep-alive\r\n"
2598 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162599 };
2600
2601 // Lastly, the server responds with the actual content.
2602 MockRead data_reads2[] = {
2603 MockRead("HTTP/1.0 200 OK\r\n"),
2604 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2605 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062606 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162607 };
2608
Ryan Sleevib8d7ea02018-05-07 20:01:012609 StaticSocketDataProvider data1(data_reads1, data_writes1);
2610 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072611 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2612 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162613
[email protected]49639fa2011-12-20 23:22:412614 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162615
tfarina42834112016-09-22 13:38:202616 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012617 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162618
2619 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012620 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162621
[email protected]58e32bb2013-01-21 18:23:252622 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162623 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252624 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2625
Ryan Sleevib8d7ea02018-05-07 20:01:012626 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162627 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012628 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162629 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192630
bnc691fda62016-08-12 00:43:162631 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522632 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582633 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162634
[email protected]49639fa2011-12-20 23:22:412635 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162636
bnc691fda62016-08-12 00:43:162637 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012638 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162639
2640 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012641 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162642
[email protected]58e32bb2013-01-21 18:23:252643 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162644 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252645 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2646 // The load timing after restart should have a new socket ID, and times after
2647 // those of the first load timing.
2648 EXPECT_LE(load_timing_info1.receive_headers_end,
2649 load_timing_info2.connect_timing.connect_start);
2650 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2651
Ryan Sleevib8d7ea02018-05-07 20:01:012652 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162653 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012654 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162655 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192656
bnc691fda62016-08-12 00:43:162657 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522658 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582659 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162660 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162661}
2662
ttuttled9dbc652015-09-29 20:00:592663// Test the request-challenge-retry sequence for basic auth.
2664// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012665TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592666 HttpRequestInfo request;
2667 request.method = "GET";
2668 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102669 request.traffic_annotation =
2670 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592671
2672 TestNetLog log;
2673 MockHostResolver* resolver = new MockHostResolver();
2674 session_deps_.net_log = &log;
2675 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092676 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162677 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592678
2679 resolver->rules()->ClearRules();
2680 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2681
2682 MockWrite data_writes1[] = {
2683 MockWrite("GET / HTTP/1.1\r\n"
2684 "Host: www.example.org\r\n"
2685 "Connection: keep-alive\r\n\r\n"),
2686 };
2687
2688 MockRead data_reads1[] = {
2689 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2690 // Give a couple authenticate options (only the middle one is actually
2691 // supported).
2692 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2693 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2694 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2695 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2696 // Large content-length -- won't matter, as connection will be reset.
2697 MockRead("Content-Length: 10000\r\n\r\n"),
2698 MockRead(SYNCHRONOUS, ERR_FAILED),
2699 };
2700
2701 // After calling trans->RestartWithAuth(), this is the request we should
2702 // be issuing -- the final header line contains the credentials.
2703 MockWrite data_writes2[] = {
2704 MockWrite("GET / HTTP/1.1\r\n"
2705 "Host: www.example.org\r\n"
2706 "Connection: keep-alive\r\n"
2707 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2708 };
2709
2710 // Lastly, the server responds with the actual content.
2711 MockRead data_reads2[] = {
2712 MockRead("HTTP/1.0 200 OK\r\n"),
2713 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2714 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2715 };
2716
Ryan Sleevib8d7ea02018-05-07 20:01:012717 StaticSocketDataProvider data1(data_reads1, data_writes1);
2718 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592719 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2720 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2721
2722 TestCompletionCallback callback1;
2723
bnc691fda62016-08-12 00:43:162724 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202725 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592726
2727 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162728 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592729 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2730
Ryan Sleevib8d7ea02018-05-07 20:01:012731 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162732 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012733 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162734 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592735
bnc691fda62016-08-12 00:43:162736 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592737 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582738 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592739
2740 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162741 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592742 ASSERT_FALSE(endpoint.address().empty());
2743 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2744
2745 resolver->rules()->ClearRules();
2746 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2747
2748 TestCompletionCallback callback2;
2749
bnc691fda62016-08-12 00:43:162750 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592751 AuthCredentials(kFoo, kBar), callback2.callback())));
2752
2753 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162754 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592755 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2756 // The load timing after restart should have a new socket ID, and times after
2757 // those of the first load timing.
2758 EXPECT_LE(load_timing_info1.receive_headers_end,
2759 load_timing_info2.connect_timing.connect_start);
2760 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2761
Ryan Sleevib8d7ea02018-05-07 20:01:012762 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162763 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012764 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162765 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592766
bnc691fda62016-08-12 00:43:162767 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592768 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582769 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592770 EXPECT_EQ(100, response->headers->GetContentLength());
2771
bnc691fda62016-08-12 00:43:162772 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592773 ASSERT_FALSE(endpoint.address().empty());
2774 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2775}
2776
David Benjamin83ddfb32018-03-30 01:07:522777// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2778// will eventually give up.
2779TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2780 HttpRequestInfo request;
2781 request.method = "GET";
2782 request.url = GURL("http://www.example.org/");
2783 request.traffic_annotation =
2784 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2785
2786 TestNetLog log;
2787 session_deps_.net_log = &log;
2788 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2789 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2790
2791 MockWrite data_writes[] = {
2792 MockWrite("GET / HTTP/1.1\r\n"
2793 "Host: www.example.org\r\n"
2794 "Connection: keep-alive\r\n\r\n"),
2795 };
2796
2797 MockRead data_reads[] = {
2798 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2799 // Give a couple authenticate options (only the middle one is actually
2800 // supported).
2801 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2802 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2803 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2804 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2805 // Large content-length -- won't matter, as connection will be reset.
2806 MockRead("Content-Length: 10000\r\n\r\n"),
2807 MockRead(SYNCHRONOUS, ERR_FAILED),
2808 };
2809
2810 // After calling trans->RestartWithAuth(), this is the request we should
2811 // be issuing -- the final header line contains the credentials.
2812 MockWrite data_writes_restart[] = {
2813 MockWrite("GET / HTTP/1.1\r\n"
2814 "Host: www.example.org\r\n"
2815 "Connection: keep-alive\r\n"
2816 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2817 };
2818
Ryan Sleevib8d7ea02018-05-07 20:01:012819 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522820 session_deps_.socket_factory->AddSocketDataProvider(&data);
2821
2822 TestCompletionCallback callback;
2823 int rv = callback.GetResult(
2824 trans.Start(&request, callback.callback(), NetLogWithSource()));
2825
2826 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2827 for (int i = 0; i < 32; i++) {
2828 // Check the previous response was a 401.
2829 EXPECT_THAT(rv, IsOk());
2830 const HttpResponseInfo* response = trans.GetResponseInfo();
2831 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582832 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522833
2834 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012835 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522836 session_deps_.socket_factory->AddSocketDataProvider(
2837 data_restarts.back().get());
2838 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2839 callback.callback()));
2840 }
2841
2842 // After too many tries, the transaction should have given up.
2843 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2844}
2845
bncd16676a2016-07-20 16:23:012846TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462847 HttpRequestInfo request;
2848 request.method = "GET";
bncce36dca22015-04-21 22:11:232849 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292850 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:102851 request.traffic_annotation =
2852 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462853
danakj1fd259a02016-04-16 03:17:092854 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162855 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272856
[email protected]861fcd52009-08-26 02:33:462857 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232858 MockWrite(
2859 "GET / HTTP/1.1\r\n"
2860 "Host: www.example.org\r\n"
2861 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462862 };
2863
2864 MockRead data_reads[] = {
2865 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2866 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2868 // Large content-length -- won't matter, as connection will be reset.
2869 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062870 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462871 };
2872
Ryan Sleevib8d7ea02018-05-07 20:01:012873 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072874 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412875 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462876
tfarina42834112016-09-22 13:38:202877 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012878 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462879
2880 rv = callback.WaitForResult();
2881 EXPECT_EQ(0, rv);
2882
Ryan Sleevib8d7ea02018-05-07 20:01:012883 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162884 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012885 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162886 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192887
bnc691fda62016-08-12 00:43:162888 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522889 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582890 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462891}
2892
[email protected]2d2697f92009-02-18 21:00:322893// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2894// connection.
bncd16676a2016-07-20 16:23:012895TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182896 // On the second pass, the body read of the auth challenge is synchronous, so
2897 // IsConnectedAndIdle returns false. The socket should still be drained and
2898 // reused. See http://crbug.com/544255.
2899 for (int i = 0; i < 2; ++i) {
2900 HttpRequestInfo request;
2901 request.method = "GET";
2902 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102903 request.traffic_annotation =
2904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322905
mmenkecc2298e2015-12-07 18:20:182906 TestNetLog log;
2907 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092908 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272909
mmenkecc2298e2015-12-07 18:20:182910 MockWrite data_writes[] = {
2911 MockWrite(ASYNC, 0,
2912 "GET / HTTP/1.1\r\n"
2913 "Host: www.example.org\r\n"
2914 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322915
bnc691fda62016-08-12 00:43:162916 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182917 // be issuing -- the final header line contains the credentials.
2918 MockWrite(ASYNC, 6,
2919 "GET / HTTP/1.1\r\n"
2920 "Host: www.example.org\r\n"
2921 "Connection: keep-alive\r\n"
2922 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2923 };
[email protected]2d2697f92009-02-18 21:00:322924
mmenkecc2298e2015-12-07 18:20:182925 MockRead data_reads[] = {
2926 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2927 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2928 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2929 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2930 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322931
mmenkecc2298e2015-12-07 18:20:182932 // Lastly, the server responds with the actual content.
2933 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2934 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2935 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2936 MockRead(ASYNC, 10, "Hello"),
2937 };
[email protected]2d2697f92009-02-18 21:00:322938
Ryan Sleevib8d7ea02018-05-07 20:01:012939 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182940 data.set_busy_before_sync_reads(true);
2941 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462942
mmenkecc2298e2015-12-07 18:20:182943 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322944
bnc691fda62016-08-12 00:43:162945 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202946 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012947 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322948
mmenkecc2298e2015-12-07 18:20:182949 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162950 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:182951 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322952
bnc691fda62016-08-12 00:43:162953 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182954 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582955 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:322956
mmenkecc2298e2015-12-07 18:20:182957 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252958
bnc691fda62016-08-12 00:43:162959 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2960 callback2.callback());
robpercival214763f2016-07-01 23:27:012961 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322962
mmenkecc2298e2015-12-07 18:20:182963 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162964 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:182965 TestLoadTimingReused(load_timing_info2);
2966 // The load timing after restart should have the same socket ID, and times
2967 // those of the first load timing.
2968 EXPECT_LE(load_timing_info1.receive_headers_end,
2969 load_timing_info2.send_start);
2970 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322971
bnc691fda62016-08-12 00:43:162972 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182973 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582974 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:182975 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322976
mmenkecc2298e2015-12-07 18:20:182977 std::string response_data;
bnc691fda62016-08-12 00:43:162978 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:322979
Ryan Sleevib8d7ea02018-05-07 20:01:012980 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162981 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012982 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162983 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:182984 }
[email protected]2d2697f92009-02-18 21:00:322985}
2986
2987// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2988// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:012989TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422990 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322991 request.method = "GET";
bncce36dca22015-04-21 22:11:232992 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102993 request.traffic_annotation =
2994 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322995
danakj1fd259a02016-04-16 03:17:092996 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272997
[email protected]2d2697f92009-02-18 21:00:322998 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:162999 MockWrite("GET / HTTP/1.1\r\n"
3000 "Host: www.example.org\r\n"
3001 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323002
bnc691fda62016-08-12 00:43:163003 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233004 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163005 MockWrite("GET / HTTP/1.1\r\n"
3006 "Host: www.example.org\r\n"
3007 "Connection: keep-alive\r\n"
3008 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323009 };
3010
[email protected]2d2697f92009-02-18 21:00:323011 MockRead data_reads1[] = {
3012 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3013 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313014 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323015
3016 // Lastly, the server responds with the actual content.
3017 MockRead("HTTP/1.1 200 OK\r\n"),
3018 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503019 MockRead("Content-Length: 5\r\n\r\n"),
3020 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323021 };
3022
[email protected]2d0a4f92011-05-05 16:38:463023 // An incorrect reconnect would cause this to be read.
3024 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063025 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463026 };
3027
Ryan Sleevib8d7ea02018-05-07 20:01:013028 StaticSocketDataProvider data1(data_reads1, data_writes1);
3029 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073030 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3031 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323032
[email protected]49639fa2011-12-20 23:22:413033 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323034
bnc691fda62016-08-12 00:43:163035 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203036 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013037 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323038
3039 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013040 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323041
bnc691fda62016-08-12 00:43:163042 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523043 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583044 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323045
[email protected]49639fa2011-12-20 23:22:413046 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323047
bnc691fda62016-08-12 00:43:163048 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013049 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323050
3051 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013052 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323053
bnc691fda62016-08-12 00:43:163054 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523055 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583056 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503057 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323058}
3059
3060// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3061// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013062TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423063 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323064 request.method = "GET";
bncce36dca22015-04-21 22:11:233065 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103066 request.traffic_annotation =
3067 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323068
danakj1fd259a02016-04-16 03:17:093069 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273070
[email protected]2d2697f92009-02-18 21:00:323071 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163072 MockWrite("GET / HTTP/1.1\r\n"
3073 "Host: www.example.org\r\n"
3074 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323075
bnc691fda62016-08-12 00:43:163076 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233077 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163078 MockWrite("GET / HTTP/1.1\r\n"
3079 "Host: www.example.org\r\n"
3080 "Connection: keep-alive\r\n"
3081 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323082 };
3083
3084 // Respond with 5 kb of response body.
3085 std::string large_body_string("Unauthorized");
3086 large_body_string.append(5 * 1024, ' ');
3087 large_body_string.append("\r\n");
3088
3089 MockRead data_reads1[] = {
3090 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3091 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3092 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3093 // 5134 = 12 + 5 * 1024 + 2
3094 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063095 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323096
3097 // Lastly, the server responds with the actual content.
3098 MockRead("HTTP/1.1 200 OK\r\n"),
3099 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503100 MockRead("Content-Length: 5\r\n\r\n"),
3101 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323102 };
3103
[email protected]2d0a4f92011-05-05 16:38:463104 // An incorrect reconnect would cause this to be read.
3105 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063106 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463107 };
3108
Ryan Sleevib8d7ea02018-05-07 20:01:013109 StaticSocketDataProvider data1(data_reads1, data_writes1);
3110 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073111 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3112 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323113
[email protected]49639fa2011-12-20 23:22:413114 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323115
bnc691fda62016-08-12 00:43:163116 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203117 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323119
3120 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013121 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323122
bnc691fda62016-08-12 00:43:163123 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523124 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583125 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323126
[email protected]49639fa2011-12-20 23:22:413127 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323128
bnc691fda62016-08-12 00:43:163129 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013130 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323131
3132 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013133 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323134
bnc691fda62016-08-12 00:43:163135 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523136 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583137 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503138 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323139}
3140
3141// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313142// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013143TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313144 HttpRequestInfo request;
3145 request.method = "GET";
bncce36dca22015-04-21 22:11:233146 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103147 request.traffic_annotation =
3148 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313149
danakj1fd259a02016-04-16 03:17:093150 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273151
[email protected]11203f012009-11-12 23:02:313152 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233153 MockWrite(
3154 "GET / HTTP/1.1\r\n"
3155 "Host: www.example.org\r\n"
3156 "Connection: keep-alive\r\n\r\n"),
3157 // This simulates the seemingly successful write to a closed connection
3158 // if the bug is not fixed.
3159 MockWrite(
3160 "GET / HTTP/1.1\r\n"
3161 "Host: www.example.org\r\n"
3162 "Connection: keep-alive\r\n"
3163 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313164 };
3165
3166 MockRead data_reads1[] = {
3167 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3168 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3169 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3170 MockRead("Content-Length: 14\r\n\r\n"),
3171 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063172 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313173 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063174 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313175 };
3176
bnc691fda62016-08-12 00:43:163177 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313178 // be issuing -- the final header line contains the credentials.
3179 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233180 MockWrite(
3181 "GET / HTTP/1.1\r\n"
3182 "Host: www.example.org\r\n"
3183 "Connection: keep-alive\r\n"
3184 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313185 };
3186
3187 // Lastly, the server responds with the actual content.
3188 MockRead data_reads2[] = {
3189 MockRead("HTTP/1.1 200 OK\r\n"),
3190 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503191 MockRead("Content-Length: 5\r\n\r\n"),
3192 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313193 };
3194
Ryan Sleevib8d7ea02018-05-07 20:01:013195 StaticSocketDataProvider data1(data_reads1, data_writes1);
3196 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073197 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3198 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313199
[email protected]49639fa2011-12-20 23:22:413200 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313201
bnc691fda62016-08-12 00:43:163202 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203203 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013204 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313205
3206 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013207 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313208
bnc691fda62016-08-12 00:43:163209 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523210 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583211 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313212
[email protected]49639fa2011-12-20 23:22:413213 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313214
bnc691fda62016-08-12 00:43:163215 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013216 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313217
3218 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013219 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313220
bnc691fda62016-08-12 00:43:163221 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523222 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583223 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503224 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313225}
3226
[email protected]394816e92010-08-03 07:38:593227// Test the request-challenge-retry sequence for basic auth, over a connection
3228// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013229TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013230 HttpRequestInfo request;
3231 request.method = "GET";
bncce36dca22015-04-21 22:11:233232 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013233 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293234 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103235 request.traffic_annotation =
3236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013237
3238 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593239 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493240 ProxyResolutionService::CreateFixedFromPacResult(
3241 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513242 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013243 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093244 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013245
3246 // Since we have proxy, should try to establish tunnel.
3247 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543248 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173249 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543250 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013251 };
3252
mmenkee71e15332015-10-07 16:39:543253 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013254 // connection.
3255 MockRead data_reads1[] = {
3256 // No credentials.
3257 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3258 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543259 };
ttuttle34f63b52015-03-05 04:33:013260
mmenkee71e15332015-10-07 16:39:543261 // Since the first connection couldn't be reused, need to establish another
3262 // once given credentials.
3263 MockWrite data_writes2[] = {
3264 // After calling trans->RestartWithAuth(), this is the request we should
3265 // be issuing -- the final header line contains the credentials.
3266 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173267 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543268 "Proxy-Connection: keep-alive\r\n"
3269 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3270
3271 MockWrite("GET / HTTP/1.1\r\n"
3272 "Host: www.example.org\r\n"
3273 "Connection: keep-alive\r\n\r\n"),
3274 };
3275
3276 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013277 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3278
3279 MockRead("HTTP/1.1 200 OK\r\n"),
3280 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3281 MockRead("Content-Length: 5\r\n\r\n"),
3282 MockRead(SYNCHRONOUS, "hello"),
3283 };
3284
Ryan Sleevib8d7ea02018-05-07 20:01:013285 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013286 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013287 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543288 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013289 SSLSocketDataProvider ssl(ASYNC, OK);
3290 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3291
3292 TestCompletionCallback callback1;
3293
bnc87dcefc2017-05-25 12:47:583294 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193295 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013296
3297 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013299
3300 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013301 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543302 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013303 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003304 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3305 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013306 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003307 entries, pos,
3308 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3309 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013310
3311 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523312 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013313 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523314 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013315 EXPECT_EQ(407, response->headers->response_code());
3316 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583317 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013318
3319 LoadTimingInfo load_timing_info;
3320 // CONNECT requests and responses are handled at the connect job level, so
3321 // the transaction does not yet have a connection.
3322 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3323
3324 TestCompletionCallback callback2;
3325
3326 rv =
3327 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013328 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013329
3330 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013331 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013332
3333 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523334 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013335
3336 EXPECT_TRUE(response->headers->IsKeepAlive());
3337 EXPECT_EQ(200, response->headers->response_code());
3338 EXPECT_EQ(5, response->headers->GetContentLength());
3339 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3340
Matt Menke96092e62019-10-18 04:09:333341 // Check that credentials were successfully cached, with the right target.
3342 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
3343 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:263344 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:333345 ASSERT_TRUE(entry);
3346 ASSERT_EQ(kFoo, entry->credentials().username());
3347 ASSERT_EQ(kBar, entry->credentials().password());
3348
ttuttle34f63b52015-03-05 04:33:013349 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583350 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013351
3352 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3353 TestLoadTimingNotReusedWithPac(load_timing_info,
3354 CONNECT_TIMING_HAS_SSL_TIMES);
3355
3356 trans.reset();
3357 session->CloseAllConnections();
3358}
3359
3360// Test the request-challenge-retry sequence for basic auth, over a connection
3361// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013362TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593363 HttpRequestInfo request;
3364 request.method = "GET";
bncce36dca22015-04-21 22:11:233365 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593366 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293367 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103368 request.traffic_annotation =
3369 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593370
[email protected]cb9bf6ca2011-01-28 13:15:273371 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593372 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493373 ProxyResolutionService::CreateFixedFromPacResult(
3374 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513375 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073376 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093377 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273378
[email protected]394816e92010-08-03 07:38:593379 // Since we have proxy, should try to establish tunnel.
3380 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543381 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173382 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543383 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113384 };
3385
mmenkee71e15332015-10-07 16:39:543386 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083387 // connection.
3388 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543389 // No credentials.
3390 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3391 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3392 MockRead("Proxy-Connection: close\r\n\r\n"),
3393 };
mmenkee0b5c882015-08-26 20:29:113394
mmenkee71e15332015-10-07 16:39:543395 MockWrite data_writes2[] = {
3396 // After calling trans->RestartWithAuth(), this is the request we should
3397 // be issuing -- the final header line contains the credentials.
3398 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173399 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543400 "Proxy-Connection: keep-alive\r\n"
3401 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083402
mmenkee71e15332015-10-07 16:39:543403 MockWrite("GET / HTTP/1.1\r\n"
3404 "Host: www.example.org\r\n"
3405 "Connection: keep-alive\r\n\r\n"),
3406 };
3407
3408 MockRead data_reads2[] = {
3409 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3410
3411 MockRead("HTTP/1.1 200 OK\r\n"),
3412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3413 MockRead("Content-Length: 5\r\n\r\n"),
3414 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593415 };
3416
Ryan Sleevib8d7ea02018-05-07 20:01:013417 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073418 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013419 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543420 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063421 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593423
[email protected]49639fa2011-12-20 23:22:413424 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593425
bnc87dcefc2017-05-25 12:47:583426 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193427 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503428
[email protected]49639fa2011-12-20 23:22:413429 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013430 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593431
3432 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013433 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543434 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593435 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003436 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3437 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593438 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403439 entries, pos,
mikecirone8b85c432016-09-08 19:11:003440 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3441 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593442
3443 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523444 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013445 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523446 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593447 EXPECT_EQ(407, response->headers->response_code());
3448 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583449 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593450
[email protected]029c83b62013-01-24 05:28:203451 LoadTimingInfo load_timing_info;
3452 // CONNECT requests and responses are handled at the connect job level, so
3453 // the transaction does not yet have a connection.
3454 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3455
[email protected]49639fa2011-12-20 23:22:413456 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593457
[email protected]49639fa2011-12-20 23:22:413458 rv = trans->RestartWithAuth(
3459 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013460 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593461
3462 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013463 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593464
3465 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523466 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593467
3468 EXPECT_TRUE(response->headers->IsKeepAlive());
3469 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503470 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593471 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3472
3473 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583474 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503475
[email protected]029c83b62013-01-24 05:28:203476 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3477 TestLoadTimingNotReusedWithPac(load_timing_info,
3478 CONNECT_TIMING_HAS_SSL_TIMES);
3479
[email protected]0b0bf032010-09-21 18:08:503480 trans.reset();
[email protected]102e27c2011-02-23 01:01:313481 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:593482}
3483
[email protected]11203f012009-11-12 23:02:313484// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013485// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013486TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233487 // On the second pass, the body read of the auth challenge is synchronous, so
3488 // IsConnectedAndIdle returns false. The socket should still be drained and
3489 // reused. See http://crbug.com/544255.
3490 for (int i = 0; i < 2; ++i) {
3491 HttpRequestInfo request;
3492 request.method = "GET";
3493 request.url = GURL("https://www.example.org/");
3494 // Ensure that proxy authentication is attempted even
3495 // when the no authentication data flag is set.
3496 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103497 request.traffic_annotation =
3498 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013499
mmenked39192ee2015-12-09 00:57:233500 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593501 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493502 ProxyResolutionService::CreateFixed("myproxy:70",
3503 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233504 BoundTestNetLog log;
3505 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093506 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013507
bnc691fda62016-08-12 00:43:163508 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013509
mmenked39192ee2015-12-09 00:57:233510 // Since we have proxy, should try to establish tunnel.
3511 MockWrite data_writes1[] = {
3512 MockWrite(ASYNC, 0,
3513 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3514 "Host: www.example.org:443\r\n"
3515 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013516
bnc691fda62016-08-12 00:43:163517 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233518 // be issuing -- the final header line contains the credentials.
3519 MockWrite(ASYNC, 3,
3520 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3521 "Host: www.example.org:443\r\n"
3522 "Proxy-Connection: keep-alive\r\n"
3523 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3524 };
ttuttle34f63b52015-03-05 04:33:013525
mmenked39192ee2015-12-09 00:57:233526 // The proxy responds to the connect with a 407, using a persistent
3527 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3528 MockRead data_reads1[] = {
3529 // No credentials.
3530 MockRead(ASYNC, 1,
3531 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3532 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3533 "Proxy-Connection: keep-alive\r\n"
3534 "Content-Length: 10\r\n\r\n"),
3535 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013536
mmenked39192ee2015-12-09 00:57:233537 // Wrong credentials (wrong password).
3538 MockRead(ASYNC, 4,
3539 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3540 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3541 "Proxy-Connection: keep-alive\r\n"
3542 "Content-Length: 10\r\n\r\n"),
3543 // No response body because the test stops reading here.
3544 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3545 };
ttuttle34f63b52015-03-05 04:33:013546
Ryan Sleevib8d7ea02018-05-07 20:01:013547 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233548 data1.set_busy_before_sync_reads(true);
3549 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013550
mmenked39192ee2015-12-09 00:57:233551 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013552
bnc691fda62016-08-12 00:43:163553 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013554 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013555
Eric Roman79cc7552019-07-19 02:17:543556 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233557 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003558 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3559 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233560 ExpectLogContainsSomewhere(
3561 entries, pos,
mikecirone8b85c432016-09-08 19:11:003562 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3563 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013564
bnc691fda62016-08-12 00:43:163565 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233566 ASSERT_TRUE(response);
3567 ASSERT_TRUE(response->headers);
3568 EXPECT_TRUE(response->headers->IsKeepAlive());
3569 EXPECT_EQ(407, response->headers->response_code());
3570 EXPECT_EQ(10, response->headers->GetContentLength());
3571 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583572 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013573
mmenked39192ee2015-12-09 00:57:233574 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013575
mmenked39192ee2015-12-09 00:57:233576 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163577 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3578 callback2.callback());
robpercival214763f2016-07-01 23:27:013579 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013580
bnc691fda62016-08-12 00:43:163581 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233582 ASSERT_TRUE(response);
3583 ASSERT_TRUE(response->headers);
3584 EXPECT_TRUE(response->headers->IsKeepAlive());
3585 EXPECT_EQ(407, response->headers->response_code());
3586 EXPECT_EQ(10, response->headers->GetContentLength());
3587 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583588 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013589
mmenked39192ee2015-12-09 00:57:233590 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3591 // out of scope.
3592 session->CloseAllConnections();
3593 }
ttuttle34f63b52015-03-05 04:33:013594}
3595
3596// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3597// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013598TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233599 // On the second pass, the body read of the auth challenge is synchronous, so
3600 // IsConnectedAndIdle returns false. The socket should still be drained and
3601 // reused. See http://crbug.com/544255.
3602 for (int i = 0; i < 2; ++i) {
3603 HttpRequestInfo request;
3604 request.method = "GET";
3605 request.url = GURL("https://www.example.org/");
3606 // Ensure that proxy authentication is attempted even
3607 // when the no authentication data flag is set.
3608 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103609 request.traffic_annotation =
3610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233611
3612 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593613 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493614 ProxyResolutionService::CreateFixed("myproxy:70",
3615 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233616 BoundTestNetLog log;
3617 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093618 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233619
bnc691fda62016-08-12 00:43:163620 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233621
3622 // Since we have proxy, should try to establish tunnel.
3623 MockWrite data_writes1[] = {
3624 MockWrite(ASYNC, 0,
3625 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3626 "Host: www.example.org:443\r\n"
3627 "Proxy-Connection: keep-alive\r\n\r\n"),
3628
bnc691fda62016-08-12 00:43:163629 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233630 // be issuing -- the final header line contains the credentials.
3631 MockWrite(ASYNC, 3,
3632 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3633 "Host: www.example.org:443\r\n"
3634 "Proxy-Connection: keep-alive\r\n"
3635 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3636 };
3637
3638 // The proxy responds to the connect with a 407, using a persistent
3639 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3640 MockRead data_reads1[] = {
3641 // No credentials.
3642 MockRead(ASYNC, 1,
3643 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3644 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3645 "Content-Length: 10\r\n\r\n"),
3646 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3647
3648 // Wrong credentials (wrong password).
3649 MockRead(ASYNC, 4,
3650 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3651 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3652 "Content-Length: 10\r\n\r\n"),
3653 // No response body because the test stops reading here.
3654 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3655 };
3656
Ryan Sleevib8d7ea02018-05-07 20:01:013657 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233658 data1.set_busy_before_sync_reads(true);
3659 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3660
3661 TestCompletionCallback callback1;
3662
bnc691fda62016-08-12 00:43:163663 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013664 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233665
Eric Roman79cc7552019-07-19 02:17:543666 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233667 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003668 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3669 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233670 ExpectLogContainsSomewhere(
3671 entries, pos,
mikecirone8b85c432016-09-08 19:11:003672 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3673 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233674
bnc691fda62016-08-12 00:43:163675 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233676 ASSERT_TRUE(response);
3677 ASSERT_TRUE(response->headers);
3678 EXPECT_TRUE(response->headers->IsKeepAlive());
3679 EXPECT_EQ(407, response->headers->response_code());
3680 EXPECT_EQ(10, response->headers->GetContentLength());
3681 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583682 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503683 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233684
3685 TestCompletionCallback callback2;
3686
3687 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163688 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3689 callback2.callback());
robpercival214763f2016-07-01 23:27:013690 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233691
bnc691fda62016-08-12 00:43:163692 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233693 ASSERT_TRUE(response);
3694 ASSERT_TRUE(response->headers);
3695 EXPECT_TRUE(response->headers->IsKeepAlive());
3696 EXPECT_EQ(407, response->headers->response_code());
3697 EXPECT_EQ(10, response->headers->GetContentLength());
3698 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583699 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503700 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233701
3702 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3703 // out of scope.
3704 session->CloseAllConnections();
3705 }
3706}
3707
3708// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3709// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3710// the case the server sends extra data on the original socket, so it can't be
3711// reused.
bncd16676a2016-07-20 16:23:013712TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273713 HttpRequestInfo request;
3714 request.method = "GET";
bncce36dca22015-04-21 22:11:233715 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273716 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293717 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103718 request.traffic_annotation =
3719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273720
[email protected]2d2697f92009-02-18 21:00:323721 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593722 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493723 ProxyResolutionService::CreateFixedFromPacResult(
3724 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513725 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073726 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093727 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323728
[email protected]2d2697f92009-02-18 21:00:323729 // Since we have proxy, should try to establish tunnel.
3730 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233731 MockWrite(ASYNC, 0,
3732 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173733 "Host: www.example.org:443\r\n"
3734 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233735 };
[email protected]2d2697f92009-02-18 21:00:323736
mmenked39192ee2015-12-09 00:57:233737 // The proxy responds to the connect with a 407, using a persistent, but sends
3738 // extra data, so the socket cannot be reused.
3739 MockRead data_reads1[] = {
3740 // No credentials.
3741 MockRead(ASYNC, 1,
3742 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3743 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3744 "Content-Length: 10\r\n\r\n"),
3745 MockRead(SYNCHRONOUS, 2, "0123456789"),
3746 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3747 };
3748
3749 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233750 // After calling trans->RestartWithAuth(), this is the request we should
3751 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233752 MockWrite(ASYNC, 0,
3753 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173754 "Host: www.example.org:443\r\n"
3755 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233756 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3757
3758 MockWrite(ASYNC, 2,
3759 "GET / HTTP/1.1\r\n"
3760 "Host: www.example.org\r\n"
3761 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323762 };
3763
mmenked39192ee2015-12-09 00:57:233764 MockRead data_reads2[] = {
3765 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323766
mmenked39192ee2015-12-09 00:57:233767 MockRead(ASYNC, 3,
3768 "HTTP/1.1 200 OK\r\n"
3769 "Content-Type: text/html; charset=iso-8859-1\r\n"
3770 "Content-Length: 5\r\n\r\n"),
3771 // No response body because the test stops reading here.
3772 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323773 };
3774
Ryan Sleevib8d7ea02018-05-07 20:01:013775 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233776 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073777 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013778 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233779 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3780 SSLSocketDataProvider ssl(ASYNC, OK);
3781 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323782
[email protected]49639fa2011-12-20 23:22:413783 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323784
bnc87dcefc2017-05-25 12:47:583785 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193786 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323787
mmenked39192ee2015-12-09 00:57:233788 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013789 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233790
Eric Roman79cc7552019-07-19 02:17:543791 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393792 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003793 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3794 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393795 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403796 entries, pos,
mikecirone8b85c432016-09-08 19:11:003797 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3798 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323799
[email protected]1c773ea12009-04-28 19:58:423800 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243801 ASSERT_TRUE(response);
3802 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323803 EXPECT_TRUE(response->headers->IsKeepAlive());
3804 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423805 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583806 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323807
mmenked39192ee2015-12-09 00:57:233808 LoadTimingInfo load_timing_info;
3809 // CONNECT requests and responses are handled at the connect job level, so
3810 // the transaction does not yet have a connection.
3811 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3812
[email protected]49639fa2011-12-20 23:22:413813 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323814
mmenked39192ee2015-12-09 00:57:233815 rv =
3816 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013817 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323818
[email protected]2d2697f92009-02-18 21:00:323819 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233820 EXPECT_EQ(200, response->headers->response_code());
3821 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423822 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133823
mmenked39192ee2015-12-09 00:57:233824 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583825 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233826
3827 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3828 TestLoadTimingNotReusedWithPac(load_timing_info,
3829 CONNECT_TIMING_HAS_SSL_TIMES);
3830
3831 trans.reset();
[email protected]102e27c2011-02-23 01:01:313832 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323833}
3834
mmenkee71e15332015-10-07 16:39:543835// Test the case a proxy closes a socket while the challenge body is being
3836// drained.
bncd16676a2016-07-20 16:23:013837TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543838 HttpRequestInfo request;
3839 request.method = "GET";
3840 request.url = GURL("https://www.example.org/");
3841 // Ensure that proxy authentication is attempted even
3842 // when the no authentication data flag is set.
3843 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103844 request.traffic_annotation =
3845 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543846
3847 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493848 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3849 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093850 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543851
bnc691fda62016-08-12 00:43:163852 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543853
3854 // Since we have proxy, should try to establish tunnel.
3855 MockWrite data_writes1[] = {
3856 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173857 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543858 "Proxy-Connection: keep-alive\r\n\r\n"),
3859 };
3860
3861 // The proxy responds to the connect with a 407, using a persistent
3862 // connection.
3863 MockRead data_reads1[] = {
3864 // No credentials.
3865 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3866 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3867 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3868 // Server hands up in the middle of the body.
3869 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3870 };
3871
3872 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163873 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543874 // be issuing -- the final header line contains the credentials.
3875 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173876 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543877 "Proxy-Connection: keep-alive\r\n"
3878 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3879
3880 MockWrite("GET / HTTP/1.1\r\n"
3881 "Host: www.example.org\r\n"
3882 "Connection: keep-alive\r\n\r\n"),
3883 };
3884
3885 MockRead data_reads2[] = {
3886 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3887
3888 MockRead("HTTP/1.1 200 OK\r\n"),
3889 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3890 MockRead("Content-Length: 5\r\n\r\n"),
3891 MockRead(SYNCHRONOUS, "hello"),
3892 };
3893
Ryan Sleevib8d7ea02018-05-07 20:01:013894 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543895 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013896 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543897 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3898 SSLSocketDataProvider ssl(ASYNC, OK);
3899 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3900
3901 TestCompletionCallback callback;
3902
tfarina42834112016-09-22 13:38:203903 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013904 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543905
bnc691fda62016-08-12 00:43:163906 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543907 ASSERT_TRUE(response);
3908 ASSERT_TRUE(response->headers);
3909 EXPECT_TRUE(response->headers->IsKeepAlive());
3910 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583911 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543912
bnc691fda62016-08-12 00:43:163913 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013914 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543915
bnc691fda62016-08-12 00:43:163916 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543917 ASSERT_TRUE(response);
3918 ASSERT_TRUE(response->headers);
3919 EXPECT_TRUE(response->headers->IsKeepAlive());
3920 EXPECT_EQ(200, response->headers->response_code());
3921 std::string body;
bnc691fda62016-08-12 00:43:163922 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543923 EXPECT_EQ("hello", body);
3924}
3925
[email protected]a8e9b162009-03-12 00:06:443926// Test that we don't read the response body when we fail to establish a tunnel,
3927// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013928TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273929 HttpRequestInfo request;
3930 request.method = "GET";
bncce36dca22015-04-21 22:11:233931 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103932 request.traffic_annotation =
3933 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273934
[email protected]a8e9b162009-03-12 00:06:443935 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493936 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3937 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443938
danakj1fd259a02016-04-16 03:17:093939 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443940
bnc691fda62016-08-12 00:43:163941 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443942
[email protected]a8e9b162009-03-12 00:06:443943 // Since we have proxy, should try to establish tunnel.
3944 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173945 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3946 "Host: www.example.org:443\r\n"
3947 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443948 };
3949
3950 // The proxy responds to the connect with a 407.
3951 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243952 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3953 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3954 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233955 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243956 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443957 };
3958
Ryan Sleevib8d7ea02018-05-07 20:01:013959 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073960 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443961
[email protected]49639fa2011-12-20 23:22:413962 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443963
tfarina42834112016-09-22 13:38:203964 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013965 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:443966
3967 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013968 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:443969
bnc691fda62016-08-12 00:43:163970 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243971 ASSERT_TRUE(response);
3972 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443973 EXPECT_TRUE(response->headers->IsKeepAlive());
3974 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423975 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443976
3977 std::string response_data;
bnc691fda62016-08-12 00:43:163978 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:013979 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:183980
3981 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313982 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443983}
3984
Matt Menke96092e62019-10-18 04:09:333985// Test the no-tunnel HTTP auth case where proxy and server origins and realms
3986// are the same, but the user/passwords are different. Serves to verify
3987// credentials are correctly separated based on HttpAuth::Target.
3988TEST_F(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
3989 HttpRequestInfo request;
3990 request.method = "GET";
3991 request.url = GURL("http://myproxy:70/");
3992 request.traffic_annotation =
3993 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3994
3995 // Proxy matches request URL.
3996 session_deps_.proxy_resolution_service =
3997 ProxyResolutionService::CreateFixedFromPacResult(
3998 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
3999 BoundTestNetLog log;
4000 session_deps_.net_log = log.bound().net_log();
4001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4002
4003 MockWrite data_writes[] = {
4004 // Initial request gets a proxy auth challenge.
4005 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4006 "Host: myproxy:70\r\n"
4007 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264008 // Retry with proxy auth credentials, which will result in a server auth
Matt Menke96092e62019-10-18 04:09:334009 // challenge.
4010 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4011 "Host: myproxy:70\r\n"
4012 "Proxy-Connection: keep-alive\r\n"
4013 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264014 // Retry with proxy and server auth credentials, which gets a response.
Matt Menke96092e62019-10-18 04:09:334015 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4016 "Host: myproxy:70\r\n"
4017 "Proxy-Connection: keep-alive\r\n"
4018 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4019 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4020 // A second request should preemptively send the correct proxy and server
4021 // auth headers.
4022 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4023 "Host: myproxy:70\r\n"
4024 "Proxy-Connection: keep-alive\r\n"
4025 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4026 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4027 };
4028
4029 MockRead data_reads[] = {
4030 // Proxy auth challenge.
4031 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4032 "Proxy-Connection: keep-alive\r\n"
4033 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4034 "Content-Length: 0\r\n\r\n"),
4035 // Server auth challenge.
4036 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4037 "Proxy-Connection: keep-alive\r\n"
4038 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4039 "Content-Length: 0\r\n\r\n"),
4040 // Response.
4041 MockRead("HTTP/1.1 200 OK\r\n"
4042 "Proxy-Connection: keep-alive\r\n"
4043 "Content-Length: 5\r\n\r\n"
4044 "hello"),
4045 // Response to second request.
4046 MockRead("HTTP/1.1 200 OK\r\n"
4047 "Proxy-Connection: keep-alive\r\n"
4048 "Content-Length: 2\r\n\r\n"
4049 "hi"),
4050 };
4051
4052 StaticSocketDataProvider data(data_reads, data_writes);
4053 session_deps_.socket_factory->AddSocketDataProvider(&data);
4054
4055 TestCompletionCallback callback;
4056
4057 auto trans =
4058 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4059 int rv = trans->Start(&request, callback.callback(), log.bound());
4060 EXPECT_THAT(callback.GetResult(rv), IsOk());
4061 const HttpResponseInfo* response = trans->GetResponseInfo();
4062 ASSERT_TRUE(response);
4063 ASSERT_TRUE(response->headers);
4064 EXPECT_EQ(407, response->headers->response_code());
4065 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4066
4067 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4068 EXPECT_THAT(callback.GetResult(rv), IsOk());
4069 response = trans->GetResponseInfo();
4070 ASSERT_TRUE(response);
4071 EXPECT_EQ(401, response->headers->response_code());
4072 EXPECT_FALSE(response->auth_challenge->is_proxy);
4073 EXPECT_EQ("http://myproxy:70",
4074 response->auth_challenge->challenger.Serialize());
4075 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4076 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4077
4078 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4079 callback.callback());
4080 EXPECT_THAT(callback.GetResult(rv), IsOk());
4081 response = trans->GetResponseInfo();
4082 ASSERT_TRUE(response);
4083 EXPECT_EQ(200, response->headers->response_code());
4084 // The password prompt info should not be set.
4085 EXPECT_FALSE(response->auth_challenge.has_value());
4086
4087 std::string response_data;
4088 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4089 EXPECT_EQ("hello", response_data);
4090
4091 // Check that the credentials were cached correctly.
4092 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4093 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:264094 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334095 ASSERT_TRUE(entry);
4096 ASSERT_EQ(kFoo, entry->credentials().username());
4097 ASSERT_EQ(kBar, entry->credentials().password());
Matt Menkebe090422019-10-18 20:25:264098 entry = session->http_auth_cache()->Lookup(
4099 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4100 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334101 ASSERT_TRUE(entry);
4102 ASSERT_EQ(kFoo2, entry->credentials().username());
4103 ASSERT_EQ(kBar2, entry->credentials().password());
4104
4105 // Make another request, which should automatically send the correct proxy and
4106 // server auth credentials and get another response.
4107 trans =
4108 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4109 rv = trans->Start(&request, callback.callback(), log.bound());
4110 EXPECT_THAT(callback.GetResult(rv), IsOk());
4111 response = trans->GetResponseInfo();
4112 ASSERT_TRUE(response);
4113 EXPECT_EQ(200, response->headers->response_code());
4114 // The password prompt info should not be set.
4115 EXPECT_FALSE(response->auth_challenge.has_value());
4116
4117 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4118 EXPECT_EQ("hi", response_data);
4119
4120 trans.reset();
4121 session->CloseAllConnections();
4122}
4123
Matt Menkebe090422019-10-18 20:25:264124// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4125// are the same, but the user/passwords are different, and with different
4126// NetworkIsolationKeys. Sends one request with a NIK, response to both proxy
4127// and auth challenges, sends another request with another NIK, expecting only
4128// the proxy credentials to be cached, and thus sees only a server auth
4129// challenge. Then sends a request with the original NIK, expecting cached proxy
4130// and auth credentials that match the ones used in the first request.
4131//
4132// Serves to verify credentials are correctly separated based on
4133// HttpAuth::Target and NetworkIsolationKeys, but NetworkIsolationKey only
4134// affects server credentials, not proxy credentials.
4135TEST_F(HttpNetworkTransactionTest,
4136 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyNoTunnel) {
4137 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4138 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4139 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4140 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4141
4142 // This test would need to use a single socket without this option enabled.
4143 // Best to use this option when it would affect a test, as it will eventually
4144 // become the default behavior.
4145 base::test::ScopedFeatureList feature_list;
4146 feature_list.InitAndEnableFeature(
4147 features::kPartitionConnectionsByNetworkIsolationKey);
4148
4149 // Proxy matches request URL.
4150 session_deps_.proxy_resolution_service =
4151 ProxyResolutionService::CreateFixedFromPacResult(
4152 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4153 BoundTestNetLog log;
4154 session_deps_.net_log = log.bound().net_log();
4155 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4156 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4157
4158 MockWrite data_writes[] = {
4159 // Initial request gets a proxy auth challenge.
4160 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4161 "Host: myproxy:70\r\n"
4162 "Proxy-Connection: keep-alive\r\n\r\n"),
4163 // Retry with proxy auth credentials, which will result in a server auth
4164 // 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"
4168 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4169 // Retry with proxy and server auth credentials, which gets a response.
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"
4174 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4175 // Another request to the same server and using the same NIK should
4176 // preemptively send the correct cached proxy and server
4177 // auth headers.
4178 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4179 "Host: myproxy:70\r\n"
4180 "Proxy-Connection: keep-alive\r\n"
4181 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4182 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4183 };
4184
4185 MockRead data_reads[] = {
4186 // Proxy auth challenge.
4187 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4188 "Proxy-Connection: keep-alive\r\n"
4189 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4190 "Content-Length: 0\r\n\r\n"),
4191 // Server auth challenge.
4192 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4193 "Proxy-Connection: keep-alive\r\n"
4194 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4195 "Content-Length: 0\r\n\r\n"),
4196 // Response.
4197 MockRead("HTTP/1.1 200 OK\r\n"
4198 "Proxy-Connection: keep-alive\r\n"
4199 "Content-Length: 5\r\n\r\n"
4200 "hello"),
4201 // Response to second request.
4202 MockRead("HTTP/1.1 200 OK\r\n"
4203 "Proxy-Connection: keep-alive\r\n"
4204 "Content-Length: 2\r\n\r\n"
4205 "hi"),
4206 };
4207
4208 StaticSocketDataProvider data(data_reads, data_writes);
4209 session_deps_.socket_factory->AddSocketDataProvider(&data);
4210
4211 MockWrite data_writes2[] = {
4212 // Initial request using a different NetworkIsolationKey includes the
4213 // cached proxy credentials, but not server credentials.
4214 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4215 "Host: myproxy:70\r\n"
4216 "Proxy-Connection: keep-alive\r\n"
4217 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4218 // Retry with proxy and new server auth credentials, which gets a
4219 // response.
4220 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4221 "Host: myproxy:70\r\n"
4222 "Proxy-Connection: keep-alive\r\n"
4223 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4224 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4225 };
4226
4227 MockRead data_reads2[] = {
4228 // Server auth challenge.
4229 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4230 "Proxy-Connection: keep-alive\r\n"
4231 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4232 "Content-Length: 0\r\n\r\n"),
4233 // Response.
4234 MockRead("HTTP/1.1 200 OK\r\n"
4235 "Proxy-Connection: keep-alive\r\n"
4236 "Content-Length: 9\r\n\r\n"
4237 "greetings"),
4238 };
4239
4240 StaticSocketDataProvider data2(data_reads2, data_writes2);
4241 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4242
4243 TestCompletionCallback callback;
4244
4245 HttpRequestInfo request;
4246 request.method = "GET";
4247 request.url = GURL("http://myproxy:70/");
4248 request.traffic_annotation =
4249 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4250 request.network_isolation_key = kNetworkIsolationKey1;
4251
4252 auto trans =
4253 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4254 int rv = trans->Start(&request, callback.callback(), log.bound());
4255 EXPECT_THAT(callback.GetResult(rv), IsOk());
4256 const HttpResponseInfo* response = trans->GetResponseInfo();
4257 ASSERT_TRUE(response);
4258 ASSERT_TRUE(response->headers);
4259 EXPECT_EQ(407, response->headers->response_code());
4260 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4261
4262 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4263 EXPECT_THAT(callback.GetResult(rv), IsOk());
4264 response = trans->GetResponseInfo();
4265 ASSERT_TRUE(response);
4266 EXPECT_EQ(401, response->headers->response_code());
4267 EXPECT_FALSE(response->auth_challenge->is_proxy);
4268 EXPECT_EQ("http://myproxy:70",
4269 response->auth_challenge->challenger.Serialize());
4270 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4271 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4272
4273 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4274 callback.callback());
4275 EXPECT_THAT(callback.GetResult(rv), IsOk());
4276 response = trans->GetResponseInfo();
4277 ASSERT_TRUE(response);
4278 EXPECT_EQ(200, response->headers->response_code());
4279 // The password prompt info should not be set.
4280 EXPECT_FALSE(response->auth_challenge.has_value());
4281 std::string response_data;
4282 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4283 EXPECT_EQ("hello", response_data);
4284
4285 // Check that the proxy credentials were cached correctly. The should be
4286 // accessible with any NetworkIsolationKey.
4287 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4288 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4289 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4290 ASSERT_TRUE(entry);
4291 ASSERT_EQ(kFoo, entry->credentials().username());
4292 ASSERT_EQ(kBar, entry->credentials().password());
4293 EXPECT_EQ(entry,
4294 session->http_auth_cache()->Lookup(
4295 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4296 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4297
4298 // Check that the server credentials were cached correctly. The should be
4299 // accessible with only kNetworkIsolationKey1.
4300 entry = session->http_auth_cache()->Lookup(
4301 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4302 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4303 ASSERT_TRUE(entry);
4304 ASSERT_EQ(kFoo2, entry->credentials().username());
4305 ASSERT_EQ(kBar2, entry->credentials().password());
4306 // Looking up the server entry with another NetworkIsolationKey should fail.
4307 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4308 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4309 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4310
4311 // Make another request with a different NetworkIsolationKey. It should use
4312 // another socket, reuse the cached proxy credentials, but result in a server
4313 // auth challenge.
4314 request.network_isolation_key = kNetworkIsolationKey2;
4315 trans =
4316 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4317 rv = trans->Start(&request, callback.callback(), log.bound());
4318 EXPECT_THAT(callback.GetResult(rv), IsOk());
4319 response = trans->GetResponseInfo();
4320 ASSERT_TRUE(response);
4321 EXPECT_EQ(401, response->headers->response_code());
4322 EXPECT_FALSE(response->auth_challenge->is_proxy);
4323 EXPECT_EQ("http://myproxy:70",
4324 response->auth_challenge->challenger.Serialize());
4325 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4326 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4327
4328 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4329 callback.callback());
4330 EXPECT_THAT(callback.GetResult(rv), IsOk());
4331 response = trans->GetResponseInfo();
4332 ASSERT_TRUE(response);
4333 EXPECT_EQ(200, response->headers->response_code());
4334 // The password prompt info should not be set.
4335 EXPECT_FALSE(response->auth_challenge.has_value());
4336 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4337 EXPECT_EQ("greetings", response_data);
4338
4339 // Check that the proxy credentials are still cached.
4340 entry = session->http_auth_cache()->Lookup(
4341 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4342 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4343 ASSERT_TRUE(entry);
4344 ASSERT_EQ(kFoo, entry->credentials().username());
4345 ASSERT_EQ(kBar, entry->credentials().password());
4346 EXPECT_EQ(entry,
4347 session->http_auth_cache()->Lookup(
4348 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4349 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4350
4351 // Check that the correct server credentials are cached for each
4352 // NetworkIsolationKey.
4353 entry = session->http_auth_cache()->Lookup(
4354 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4355 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4356 ASSERT_TRUE(entry);
4357 ASSERT_EQ(kFoo2, entry->credentials().username());
4358 ASSERT_EQ(kBar2, entry->credentials().password());
4359 entry = session->http_auth_cache()->Lookup(
4360 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4361 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4362 ASSERT_TRUE(entry);
4363 ASSERT_EQ(kFoo3, entry->credentials().username());
4364 ASSERT_EQ(kBar3, entry->credentials().password());
4365
4366 // Make a request with the original NetworkIsolationKey. It should reuse the
4367 // first socket, and the proxy credentials sent on the first socket.
4368 request.network_isolation_key = kNetworkIsolationKey1;
4369 trans =
4370 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4371 rv = trans->Start(&request, callback.callback(), log.bound());
4372 EXPECT_THAT(callback.GetResult(rv), IsOk());
4373 response = trans->GetResponseInfo();
4374 ASSERT_TRUE(response);
4375 EXPECT_EQ(200, response->headers->response_code());
4376 // The password prompt info should not be set.
4377 EXPECT_FALSE(response->auth_challenge.has_value());
4378 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4379 EXPECT_EQ("hi", response_data);
4380
4381 trans.reset();
4382 session->CloseAllConnections();
4383}
4384
4385// Much like the test above, but uses tunnelled connections.
4386TEST_F(HttpNetworkTransactionTest,
4387 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyWithTunnel) {
4388 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4389 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4390 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4391 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4392
4393 // This test would need to use a single socket without this option enabled.
4394 // Best to use this option when it would affect a test, as it will eventually
4395 // become the default behavior.
4396 base::test::ScopedFeatureList feature_list;
4397 feature_list.InitAndEnableFeature(
4398 features::kPartitionConnectionsByNetworkIsolationKey);
4399
4400 // Proxy matches request URL.
4401 session_deps_.proxy_resolution_service =
4402 ProxyResolutionService::CreateFixedFromPacResult(
4403 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4404 BoundTestNetLog log;
4405 session_deps_.net_log = log.bound().net_log();
4406 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4407 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4408
4409 MockWrite data_writes[] = {
4410 // Initial tunnel request gets a proxy auth challenge.
4411 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4412 "Host: myproxy:70\r\n"
4413 "Proxy-Connection: keep-alive\r\n\r\n"),
4414 // Retry with proxy auth credentials, which will result in establishing a
4415 // tunnel.
4416 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4417 "Host: myproxy:70\r\n"
4418 "Proxy-Connection: keep-alive\r\n"
4419 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4420 // Request over the tunnel, which gets a server auth challenge.
4421 MockWrite("GET / HTTP/1.1\r\n"
4422 "Host: myproxy:70\r\n"
4423 "Connection: keep-alive\r\n\r\n"),
4424 // Retry with server auth credentials, which gets a response.
4425 MockWrite("GET / HTTP/1.1\r\n"
4426 "Host: myproxy:70\r\n"
4427 "Connection: keep-alive\r\n"
4428 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4429 // Another request to the same server and using the same NIK should
4430 // preemptively send the correct cached server
4431 // auth header. Since a tunnel was already established, the proxy headers
4432 // won't be sent again except when establishing another tunnel.
4433 MockWrite("GET / HTTP/1.1\r\n"
4434 "Host: myproxy:70\r\n"
4435 "Connection: keep-alive\r\n"
4436 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4437 };
4438
4439 MockRead data_reads[] = {
4440 // Proxy auth challenge.
4441 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4442 "Proxy-Connection: keep-alive\r\n"
4443 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4444 "Content-Length: 0\r\n\r\n"),
4445 // Tunnel success
4446 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4447 // Server auth challenge.
4448 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4449 "Connection: keep-alive\r\n"
4450 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4451 "Content-Length: 0\r\n\r\n"),
4452 // Response.
4453 MockRead("HTTP/1.1 200 OK\r\n"
4454 "Connection: keep-alive\r\n"
4455 "Content-Length: 5\r\n\r\n"
4456 "hello"),
4457 // Response to second request.
4458 MockRead("HTTP/1.1 200 OK\r\n"
4459 "Connection: keep-alive\r\n"
4460 "Content-Length: 2\r\n\r\n"
4461 "hi"),
4462 };
4463
4464 StaticSocketDataProvider data(data_reads, data_writes);
4465 session_deps_.socket_factory->AddSocketDataProvider(&data);
4466 // One for the proxy connection, one of the server connection.
4467 SSLSocketDataProvider ssl(ASYNC, OK);
4468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4469 SSLSocketDataProvider ssl2(ASYNC, OK);
4470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4471
4472 MockWrite data_writes2[] = {
4473 // Initial request using a different NetworkIsolationKey includes the
4474 // cached proxy credentials when establishing a tunnel.
4475 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4476 "Host: myproxy:70\r\n"
4477 "Proxy-Connection: keep-alive\r\n"
4478 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4479 // Request over the tunnel, which gets a server auth challenge. Cached
4480 // credentials cannot be used, since the NIK is different.
4481 MockWrite("GET / HTTP/1.1\r\n"
4482 "Host: myproxy:70\r\n"
4483 "Connection: keep-alive\r\n\r\n"),
4484 // Retry with server auth credentials, which gets a response.
4485 MockWrite("GET / HTTP/1.1\r\n"
4486 "Host: myproxy:70\r\n"
4487 "Connection: keep-alive\r\n"
4488 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4489 };
4490
4491 MockRead data_reads2[] = {
4492 // Tunnel success
4493 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4494 // Server auth challenge.
4495 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4496 "Connection: keep-alive\r\n"
4497 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4498 "Content-Length: 0\r\n\r\n"),
4499 // Response.
4500 MockRead("HTTP/1.1 200 OK\r\n"
4501 "Connection: keep-alive\r\n"
4502 "Content-Length: 9\r\n\r\n"
4503 "greetings"),
4504 };
4505
4506 StaticSocketDataProvider data2(data_reads2, data_writes2);
4507 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4508 // One for the proxy connection, one of the server connection.
4509 SSLSocketDataProvider ssl3(ASYNC, OK);
4510 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
4511 SSLSocketDataProvider ssl4(ASYNC, OK);
4512 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
4513
4514 TestCompletionCallback callback;
4515
4516 HttpRequestInfo request;
4517 request.method = "GET";
4518 request.url = GURL("https://myproxy:70/");
4519 request.traffic_annotation =
4520 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4521 request.network_isolation_key = kNetworkIsolationKey1;
4522
4523 auto trans =
4524 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4525 int rv = trans->Start(&request, callback.callback(), log.bound());
4526 EXPECT_THAT(callback.GetResult(rv), IsOk());
4527 const HttpResponseInfo* response = trans->GetResponseInfo();
4528 ASSERT_TRUE(response);
4529 ASSERT_TRUE(response->headers);
4530 EXPECT_EQ(407, response->headers->response_code());
4531 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
4532
4533 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4534 EXPECT_THAT(callback.GetResult(rv), IsOk());
4535 response = trans->GetResponseInfo();
4536 ASSERT_TRUE(response);
4537 EXPECT_EQ(401, response->headers->response_code());
4538 EXPECT_FALSE(response->auth_challenge->is_proxy);
4539 EXPECT_EQ("https://myproxy:70",
4540 response->auth_challenge->challenger.Serialize());
4541 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4542 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4543
4544 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4545 callback.callback());
4546 EXPECT_THAT(callback.GetResult(rv), IsOk());
4547 response = trans->GetResponseInfo();
4548 ASSERT_TRUE(response);
4549 EXPECT_EQ(200, response->headers->response_code());
4550 // The password prompt info should not be set.
4551 EXPECT_FALSE(response->auth_challenge.has_value());
4552 std::string response_data;
4553 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4554 EXPECT_EQ("hello", response_data);
4555
4556 // Check that the proxy credentials were cached correctly. The should be
4557 // accessible with any NetworkIsolationKey.
4558 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4559 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4560 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4561 ASSERT_TRUE(entry);
4562 ASSERT_EQ(kFoo, entry->credentials().username());
4563 ASSERT_EQ(kBar, entry->credentials().password());
4564 EXPECT_EQ(entry,
4565 session->http_auth_cache()->Lookup(
4566 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4567 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4568
4569 // Check that the server credentials were cached correctly. The should be
4570 // accessible with only kNetworkIsolationKey1.
4571 entry = session->http_auth_cache()->Lookup(
4572 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4573 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4574 ASSERT_TRUE(entry);
4575 ASSERT_EQ(kFoo2, entry->credentials().username());
4576 ASSERT_EQ(kBar2, entry->credentials().password());
4577 // Looking up the server entry with another NetworkIsolationKey should fail.
4578 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4579 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4580 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4581
4582 // Make another request with a different NetworkIsolationKey. It should use
4583 // another socket, reuse the cached proxy credentials, but result in a server
4584 // auth challenge.
4585 request.network_isolation_key = kNetworkIsolationKey2;
4586 trans =
4587 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4588 rv = trans->Start(&request, callback.callback(), log.bound());
4589 EXPECT_THAT(callback.GetResult(rv), IsOk());
4590 response = trans->GetResponseInfo();
4591 ASSERT_TRUE(response);
4592 EXPECT_EQ(401, response->headers->response_code());
4593 EXPECT_FALSE(response->auth_challenge->is_proxy);
4594 EXPECT_EQ("https://myproxy:70",
4595 response->auth_challenge->challenger.Serialize());
4596 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4597 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4598
4599 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4600 callback.callback());
4601 EXPECT_THAT(callback.GetResult(rv), IsOk());
4602 response = trans->GetResponseInfo();
4603 ASSERT_TRUE(response);
4604 EXPECT_EQ(200, response->headers->response_code());
4605 // The password prompt info should not be set.
4606 EXPECT_FALSE(response->auth_challenge.has_value());
4607 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4608 EXPECT_EQ("greetings", response_data);
4609
4610 // Check that the proxy credentials are still cached.
4611 entry = session->http_auth_cache()->Lookup(
4612 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4613 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4614 ASSERT_TRUE(entry);
4615 ASSERT_EQ(kFoo, entry->credentials().username());
4616 ASSERT_EQ(kBar, entry->credentials().password());
4617 EXPECT_EQ(entry,
4618 session->http_auth_cache()->Lookup(
4619 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4620 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4621
4622 // Check that the correct server credentials are cached for each
4623 // NetworkIsolationKey.
4624 entry = session->http_auth_cache()->Lookup(
4625 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4626 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4627 ASSERT_TRUE(entry);
4628 ASSERT_EQ(kFoo2, entry->credentials().username());
4629 ASSERT_EQ(kBar2, entry->credentials().password());
4630 entry = session->http_auth_cache()->Lookup(
4631 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4632 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4633 ASSERT_TRUE(entry);
4634 ASSERT_EQ(kFoo3, entry->credentials().username());
4635 ASSERT_EQ(kBar3, entry->credentials().password());
4636
4637 // Make a request with the original NetworkIsolationKey. It should reuse the
4638 // first socket, and the proxy credentials sent on the first socket.
4639 request.network_isolation_key = kNetworkIsolationKey1;
4640 trans =
4641 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4642 rv = trans->Start(&request, callback.callback(), log.bound());
4643 EXPECT_THAT(callback.GetResult(rv), IsOk());
4644 response = trans->GetResponseInfo();
4645 ASSERT_TRUE(response);
4646 EXPECT_EQ(200, response->headers->response_code());
4647 // The password prompt info should not be set.
4648 EXPECT_FALSE(response->auth_challenge.has_value());
4649 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4650 EXPECT_EQ("hi", response_data);
4651
4652 trans.reset();
4653 session->CloseAllConnections();
4654}
4655
ttuttle7933c112015-01-06 00:55:244656// Test that we don't pass extraneous headers from the proxy's response to the
4657// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014658TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244659 HttpRequestInfo request;
4660 request.method = "GET";
bncce36dca22015-04-21 22:11:234661 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104662 request.traffic_annotation =
4663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244664
4665 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:494666 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4667 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244668
danakj1fd259a02016-04-16 03:17:094669 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244670
bnc691fda62016-08-12 00:43:164671 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244672
4673 // Since we have proxy, should try to establish tunnel.
4674 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174675 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4676 "Host: www.example.org:443\r\n"
4677 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244678 };
4679
4680 // The proxy responds to the connect with a 407.
4681 MockRead data_reads[] = {
4682 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4683 MockRead("X-Foo: bar\r\n"),
4684 MockRead("Set-Cookie: foo=bar\r\n"),
4685 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4686 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234687 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244688 };
4689
Ryan Sleevib8d7ea02018-05-07 20:01:014690 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244691 session_deps_.socket_factory->AddSocketDataProvider(&data);
4692
4693 TestCompletionCallback callback;
4694
tfarina42834112016-09-22 13:38:204695 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014696 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244697
4698 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014699 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244700
bnc691fda62016-08-12 00:43:164701 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244702 ASSERT_TRUE(response);
4703 ASSERT_TRUE(response->headers);
4704 EXPECT_TRUE(response->headers->IsKeepAlive());
4705 EXPECT_EQ(407, response->headers->response_code());
4706 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4707 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4708 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4709
4710 std::string response_data;
bnc691fda62016-08-12 00:43:164711 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014712 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244713
4714 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4715 session->CloseAllConnections();
4716}
4717
[email protected]8fdbcd22010-05-05 02:54:524718// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4719// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014720TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524721 HttpRequestInfo request;
4722 request.method = "GET";
bncce36dca22015-04-21 22:11:234723 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104724 request.traffic_annotation =
4725 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524726
[email protected]cb9bf6ca2011-01-28 13:15:274727 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094728 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164729 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274730
[email protected]8fdbcd22010-05-05 02:54:524731 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234732 MockWrite(
4733 "GET / HTTP/1.1\r\n"
4734 "Host: www.example.org\r\n"
4735 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524736 };
4737
4738 MockRead data_reads1[] = {
4739 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4740 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4741 // Large content-length -- won't matter, as connection will be reset.
4742 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064743 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524744 };
4745
Ryan Sleevib8d7ea02018-05-07 20:01:014746 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074747 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524748
[email protected]49639fa2011-12-20 23:22:414749 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524750
tfarina42834112016-09-22 13:38:204751 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014752 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524753
4754 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014755 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524756}
4757
[email protected]7a67a8152010-11-05 18:31:104758// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4759// through a non-authenticating proxy. The request should fail with
4760// ERR_UNEXPECTED_PROXY_AUTH.
4761// Note that it is impossible to detect if an HTTP server returns a 407 through
4762// a non-authenticating proxy - there is nothing to indicate whether the
4763// response came from the proxy or the server, so it is treated as if the proxy
4764// issued the challenge.
bncd16676a2016-07-20 16:23:014765TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274766 HttpRequestInfo request;
4767 request.method = "GET";
bncce36dca22015-04-21 22:11:234768 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104769 request.traffic_annotation =
4770 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274771
Ramin Halavatica8d5252018-03-12 05:33:494772 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4773 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514774 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074775 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094776 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104777
[email protected]7a67a8152010-11-05 18:31:104778 // Since we have proxy, should try to establish tunnel.
4779 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174780 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4781 "Host: www.example.org:443\r\n"
4782 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104783
rsleevidb16bb02015-11-12 23:47:174784 MockWrite("GET / HTTP/1.1\r\n"
4785 "Host: www.example.org\r\n"
4786 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104787 };
4788
4789 MockRead data_reads1[] = {
4790 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4791
4792 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4793 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4794 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064795 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104796 };
4797
Ryan Sleevib8d7ea02018-05-07 20:01:014798 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074799 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064800 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074801 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104802
[email protected]49639fa2011-12-20 23:22:414803 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104804
bnc691fda62016-08-12 00:43:164805 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104806
bnc691fda62016-08-12 00:43:164807 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014808 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104809
4810 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014811 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544812 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104813 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004814 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4815 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104816 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404817 entries, pos,
mikecirone8b85c432016-09-08 19:11:004818 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4819 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104820}
[email protected]2df19bb2010-08-25 20:13:464821
mmenke2a1781d2015-10-07 19:25:334822// Test a proxy auth scheme that allows default credentials and a proxy server
4823// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014824TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334825 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4826 HttpRequestInfo request;
4827 request.method = "GET";
4828 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104829 request.traffic_annotation =
4830 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334831
4832 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594833 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494834 ProxyResolutionService::CreateFixedFromPacResult(
4835 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334836
Jeremy Roman0579ed62017-08-29 15:56:194837 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334838 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194839 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334840 mock_handler->set_allows_default_credentials(true);
4841 auth_handler_factory->AddMockHandler(mock_handler.release(),
4842 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484843 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334844
4845 // Add NetLog just so can verify load timing information gets a NetLog ID.
4846 NetLog net_log;
4847 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094848 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334849
4850 // Since we have proxy, should try to establish tunnel.
4851 MockWrite data_writes1[] = {
4852 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174853 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334854 "Proxy-Connection: keep-alive\r\n\r\n"),
4855 };
4856
4857 // The proxy responds to the connect with a 407, using a non-persistent
4858 // connection.
4859 MockRead data_reads1[] = {
4860 // No credentials.
4861 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4862 MockRead("Proxy-Authenticate: Mock\r\n"),
4863 MockRead("Proxy-Connection: close\r\n\r\n"),
4864 };
4865
4866 // Since the first connection couldn't be reused, need to establish another
4867 // once given credentials.
4868 MockWrite data_writes2[] = {
4869 // After calling trans->RestartWithAuth(), this is the request we should
4870 // be issuing -- the final header line contains the credentials.
4871 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174872 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334873 "Proxy-Connection: keep-alive\r\n"
4874 "Proxy-Authorization: auth_token\r\n\r\n"),
4875
4876 MockWrite("GET / HTTP/1.1\r\n"
4877 "Host: www.example.org\r\n"
4878 "Connection: keep-alive\r\n\r\n"),
4879 };
4880
4881 MockRead data_reads2[] = {
4882 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4883
4884 MockRead("HTTP/1.1 200 OK\r\n"),
4885 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4886 MockRead("Content-Length: 5\r\n\r\n"),
4887 MockRead(SYNCHRONOUS, "hello"),
4888 };
4889
Ryan Sleevib8d7ea02018-05-07 20:01:014890 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334891 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014892 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334893 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4894 SSLSocketDataProvider ssl(ASYNC, OK);
4895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4896
bnc87dcefc2017-05-25 12:47:584897 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194898 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334899
4900 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204901 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014902 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334903
4904 const HttpResponseInfo* response = trans->GetResponseInfo();
4905 ASSERT_TRUE(response);
4906 ASSERT_TRUE(response->headers);
4907 EXPECT_FALSE(response->headers->IsKeepAlive());
4908 EXPECT_EQ(407, response->headers->response_code());
4909 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4910 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584911 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334912
4913 LoadTimingInfo load_timing_info;
4914 // CONNECT requests and responses are handled at the connect job level, so
4915 // the transaction does not yet have a connection.
4916 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4917
4918 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014919 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334920 response = trans->GetResponseInfo();
4921 ASSERT_TRUE(response);
4922 ASSERT_TRUE(response->headers);
4923 EXPECT_TRUE(response->headers->IsKeepAlive());
4924 EXPECT_EQ(200, response->headers->response_code());
4925 EXPECT_EQ(5, response->headers->GetContentLength());
4926 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4927
4928 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584929 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334930
4931 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4932 TestLoadTimingNotReusedWithPac(load_timing_info,
4933 CONNECT_TIMING_HAS_SSL_TIMES);
4934
4935 trans.reset();
4936 session->CloseAllConnections();
4937}
4938
4939// Test a proxy auth scheme that allows default credentials and a proxy server
4940// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014941TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334942 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4943 HttpRequestInfo request;
4944 request.method = "GET";
4945 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104946 request.traffic_annotation =
4947 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334948
4949 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594950 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494951 ProxyResolutionService::CreateFixedFromPacResult(
4952 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334953
Jeremy Roman0579ed62017-08-29 15:56:194954 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334955 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194956 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334957 mock_handler->set_allows_default_credentials(true);
4958 auth_handler_factory->AddMockHandler(mock_handler.release(),
4959 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484960 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334961
4962 // Add NetLog just so can verify load timing information gets a NetLog ID.
4963 NetLog net_log;
4964 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094965 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334966
4967 // Should try to establish tunnel.
4968 MockWrite data_writes1[] = {
4969 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174970 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334971 "Proxy-Connection: keep-alive\r\n\r\n"),
4972
4973 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174974 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334975 "Proxy-Connection: keep-alive\r\n"
4976 "Proxy-Authorization: auth_token\r\n\r\n"),
4977 };
4978
4979 // The proxy responds to the connect with a 407, using a non-persistent
4980 // connection.
4981 MockRead data_reads1[] = {
4982 // No credentials.
4983 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4984 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4985 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4986 };
4987
4988 // Since the first connection was closed, need to establish another once given
4989 // credentials.
4990 MockWrite data_writes2[] = {
4991 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174992 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334993 "Proxy-Connection: keep-alive\r\n"
4994 "Proxy-Authorization: auth_token\r\n\r\n"),
4995
4996 MockWrite("GET / HTTP/1.1\r\n"
4997 "Host: www.example.org\r\n"
4998 "Connection: keep-alive\r\n\r\n"),
4999 };
5000
5001 MockRead data_reads2[] = {
5002 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5003
5004 MockRead("HTTP/1.1 200 OK\r\n"),
5005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5006 MockRead("Content-Length: 5\r\n\r\n"),
5007 MockRead(SYNCHRONOUS, "hello"),
5008 };
5009
Ryan Sleevib8d7ea02018-05-07 20:01:015010 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335011 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015012 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335013 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5014 SSLSocketDataProvider ssl(ASYNC, OK);
5015 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5016
bnc87dcefc2017-05-25 12:47:585017 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195018 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335019
5020 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205021 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015022 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335023
5024 const HttpResponseInfo* response = trans->GetResponseInfo();
5025 ASSERT_TRUE(response);
5026 ASSERT_TRUE(response->headers);
5027 EXPECT_TRUE(response->headers->IsKeepAlive());
5028 EXPECT_EQ(407, response->headers->response_code());
5029 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5030 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585031 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335032
5033 LoadTimingInfo load_timing_info;
5034 // CONNECT requests and responses are handled at the connect job level, so
5035 // the transaction does not yet have a connection.
5036 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5037
5038 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015039 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335040
5041 response = trans->GetResponseInfo();
5042 ASSERT_TRUE(response);
5043 ASSERT_TRUE(response->headers);
5044 EXPECT_TRUE(response->headers->IsKeepAlive());
5045 EXPECT_EQ(200, response->headers->response_code());
5046 EXPECT_EQ(5, response->headers->GetContentLength());
5047 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5048
5049 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585050 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335051
5052 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5053 TestLoadTimingNotReusedWithPac(load_timing_info,
5054 CONNECT_TIMING_HAS_SSL_TIMES);
5055
5056 trans.reset();
5057 session->CloseAllConnections();
5058}
5059
5060// Test a proxy auth scheme that allows default credentials and a proxy server
5061// that hangs up when credentials are initially sent, and hangs up again when
5062// they are retried.
bncd16676a2016-07-20 16:23:015063TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335064 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
5065 HttpRequestInfo request;
5066 request.method = "GET";
5067 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105068 request.traffic_annotation =
5069 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335070
5071 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595072 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495073 ProxyResolutionService::CreateFixedFromPacResult(
5074 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335075
Jeremy Roman0579ed62017-08-29 15:56:195076 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335077 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195078 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335079 mock_handler->set_allows_default_credentials(true);
5080 auth_handler_factory->AddMockHandler(mock_handler.release(),
5081 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485082 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335083
5084 // Add NetLog just so can verify load timing information gets a NetLog ID.
5085 NetLog net_log;
5086 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:095087 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335088
5089 // Should try to establish tunnel.
5090 MockWrite data_writes1[] = {
5091 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175092 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335093 "Proxy-Connection: keep-alive\r\n\r\n"),
5094
5095 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175096 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335097 "Proxy-Connection: keep-alive\r\n"
5098 "Proxy-Authorization: auth_token\r\n\r\n"),
5099 };
5100
5101 // The proxy responds to the connect with a 407, and then hangs up after the
5102 // second request is sent.
5103 MockRead data_reads1[] = {
5104 // No credentials.
5105 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5106 MockRead("Content-Length: 0\r\n"),
5107 MockRead("Proxy-Connection: keep-alive\r\n"),
5108 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5109 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5110 };
5111
5112 // HttpNetworkTransaction sees a reused connection that was closed with
5113 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
5114 // request.
5115 MockWrite data_writes2[] = {
5116 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175117 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335118 "Proxy-Connection: keep-alive\r\n\r\n"),
5119 };
5120
5121 // The proxy, having had more than enough of us, just hangs up.
5122 MockRead data_reads2[] = {
5123 // No credentials.
5124 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5125 };
5126
Ryan Sleevib8d7ea02018-05-07 20:01:015127 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335128 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015129 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335130 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5131
bnc87dcefc2017-05-25 12:47:585132 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195133 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335134
5135 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205136 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015137 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335138
5139 const HttpResponseInfo* response = trans->GetResponseInfo();
5140 ASSERT_TRUE(response);
5141 ASSERT_TRUE(response->headers);
5142 EXPECT_TRUE(response->headers->IsKeepAlive());
5143 EXPECT_EQ(407, response->headers->response_code());
5144 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5145 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585146 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335147
5148 LoadTimingInfo load_timing_info;
5149 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5150
5151 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015152 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:335153
5154 trans.reset();
5155 session->CloseAllConnections();
5156}
5157
Asanka Herathbc3f8f62018-11-16 23:08:305158// This test exercises an odd edge case where the proxy closes the connection
5159// after the authentication handshake is complete. Presumably this technique is
5160// used in lieu of returning a 403 or 5xx status code when the authentication
5161// succeeds, but the user is not authorized to connect to the destination
5162// server. There's no standard for what a proxy should do to indicate a blocked
5163// site.
5164TEST_F(HttpNetworkTransactionTest,
5165 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
5166 HttpRequestInfo request;
5167 request.method = "GET";
5168 request.url = GURL("https://www.example.org/");
5169 request.traffic_annotation =
5170 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5171
5172 // Configure against proxy server "myproxy:70".
5173 session_deps_.proxy_resolution_service =
5174 ProxyResolutionService::CreateFixedFromPacResult(
5175 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5176
Asanka Herathbc3f8f62018-11-16 23:08:305177 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5178 auth_handler_factory->set_do_init_from_challenge(true);
5179
5180 // Create two mock AuthHandlers. This is because the transaction gets retried
5181 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
5182 // was a real network error.
5183 //
5184 // The handlers support both default and explicit credentials. The retry
5185 // mentioned above should be able to reuse the default identity. Thus there
5186 // should never be a need to prompt for explicit credentials.
5187 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5188 mock_handler->set_allows_default_credentials(true);
5189 mock_handler->set_allows_explicit_credentials(true);
5190 mock_handler->set_connection_based(true);
5191 auth_handler_factory->AddMockHandler(mock_handler.release(),
5192 HttpAuth::AUTH_PROXY);
5193 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5194 mock_handler->set_allows_default_credentials(true);
5195 mock_handler->set_allows_explicit_credentials(true);
5196 mock_handler->set_connection_based(true);
5197 auth_handler_factory->AddMockHandler(mock_handler.release(),
5198 HttpAuth::AUTH_PROXY);
5199 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5200
5201 NetLog net_log;
5202 session_deps_.net_log = &net_log;
5203 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5204
5205 // Data for both sockets.
5206 //
5207 // Writes are for the tunnel establishment attempts and the
5208 // authentication handshake.
5209 MockWrite data_writes1[] = {
5210 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5211 "Host: www.example.org:443\r\n"
5212 "Proxy-Connection: keep-alive\r\n\r\n"),
5213
5214 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5215 "Host: www.example.org:443\r\n"
5216 "Proxy-Connection: keep-alive\r\n"
5217 "Proxy-Authorization: auth_token\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
5225 // The server side of the authentication handshake. Note that the response to
5226 // the final CONNECT request is ERR_CONNECTION_CLOSED.
5227 MockRead data_reads1[] = {
5228 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5229 MockRead("Content-Length: 0\r\n"),
5230 MockRead("Proxy-Connection: keep-alive\r\n"),
5231 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5232
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 foo\r\n\r\n"),
5237
5238 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5239 };
5240
5241 StaticSocketDataProvider data1(data_reads1, data_writes1);
5242 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5243
5244 // The second socket is for the reconnection attempt. Data is identical to the
5245 // first attempt.
5246 StaticSocketDataProvider data2(data_reads1, data_writes1);
5247 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5248
5249 auto trans =
5250 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5251
5252 TestCompletionCallback callback;
5253 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5254
5255 // Two rounds per handshake. After one retry, the error is propagated up the
5256 // stack.
5257 for (int i = 0; i < 4; ++i) {
5258 EXPECT_THAT(callback.GetResult(rv), IsOk());
5259
5260 const HttpResponseInfo* response = trans->GetResponseInfo();
5261 ASSERT_TRUE(response);
5262 ASSERT_TRUE(response->headers);
5263 EXPECT_EQ(407, response->headers->response_code());
5264 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
5265
5266 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5267 }
5268
5269 // One shall be the number thou shalt retry, and the number of the retrying
5270 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
5271 // that thou then proceed to one. Three is right out. Once the number one,
5272 // being the first number, be reached, then lobbest thou thy
5273 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
5274 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
5275
5276 trans.reset();
5277 session->CloseAllConnections();
5278}
5279
mmenke2a1781d2015-10-07 19:25:335280// Test a proxy auth scheme that allows default credentials and a proxy server
5281// that hangs up when credentials are initially sent, and sends a challenge
5282// again they are retried.
bncd16676a2016-07-20 16:23:015283TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335284 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
5285 HttpRequestInfo request;
5286 request.method = "GET";
5287 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105288 request.traffic_annotation =
5289 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335290
5291 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595292 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495293 ProxyResolutionService::CreateFixedFromPacResult(
5294 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335295
Jeremy Roman0579ed62017-08-29 15:56:195296 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335297 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195298 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335299 mock_handler->set_allows_default_credentials(true);
5300 auth_handler_factory->AddMockHandler(mock_handler.release(),
5301 HttpAuth::AUTH_PROXY);
5302 // Add another handler for the second challenge. It supports default
5303 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195304 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335305 mock_handler->set_allows_default_credentials(true);
5306 auth_handler_factory->AddMockHandler(mock_handler.release(),
5307 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485308 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335309
5310 // Add NetLog just so can verify load timing information gets a NetLog ID.
5311 NetLog net_log;
5312 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:095313 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335314
5315 // Should try to establish tunnel.
5316 MockWrite data_writes1[] = {
5317 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175318 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335319 "Proxy-Connection: keep-alive\r\n\r\n"),
5320 };
5321
5322 // The proxy responds to the connect with a 407, using a non-persistent
5323 // connection.
5324 MockRead data_reads1[] = {
5325 // No credentials.
5326 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5327 MockRead("Proxy-Authenticate: Mock\r\n"),
5328 MockRead("Proxy-Connection: close\r\n\r\n"),
5329 };
5330
5331 // Since the first connection was closed, need to establish another once given
5332 // credentials.
5333 MockWrite data_writes2[] = {
5334 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175335 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335336 "Proxy-Connection: keep-alive\r\n"
5337 "Proxy-Authorization: auth_token\r\n\r\n"),
5338 };
5339
5340 MockRead data_reads2[] = {
5341 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5342 MockRead("Proxy-Authenticate: Mock\r\n"),
5343 MockRead("Proxy-Connection: close\r\n\r\n"),
5344 };
5345
Ryan Sleevib8d7ea02018-05-07 20:01:015346 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335347 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015348 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335349 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5350 SSLSocketDataProvider ssl(ASYNC, OK);
5351 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5352
bnc87dcefc2017-05-25 12:47:585353 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195354 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335355
5356 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205357 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015358 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335359
5360 const HttpResponseInfo* response = trans->GetResponseInfo();
5361 ASSERT_TRUE(response);
5362 ASSERT_TRUE(response->headers);
5363 EXPECT_EQ(407, response->headers->response_code());
5364 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5365 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585366 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335367
5368 LoadTimingInfo load_timing_info;
5369 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5370
5371 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015372 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335373 response = trans->GetResponseInfo();
5374 ASSERT_TRUE(response);
5375 ASSERT_TRUE(response->headers);
5376 EXPECT_EQ(407, response->headers->response_code());
5377 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585378 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335379
5380 trans.reset();
5381 session->CloseAllConnections();
5382}
5383
asankae2257db2016-10-11 22:03:165384// A more nuanced test than GenerateAuthToken test which asserts that
5385// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
5386// unnecessarily invalidated, and that if the server co-operates, the
5387// authentication handshake can continue with the same scheme but with a
5388// different identity.
5389TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
5390 HttpRequestInfo request;
5391 request.method = "GET";
5392 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105393 request.traffic_annotation =
5394 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:165395
Jeremy Roman0579ed62017-08-29 15:56:195396 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:165397 auth_handler_factory->set_do_init_from_challenge(true);
5398
5399 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:195400 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165401 mock_handler->set_allows_default_credentials(true);
5402 mock_handler->set_allows_explicit_credentials(true);
5403 mock_handler->set_connection_based(true);
5404 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
5405 auth_handler_factory->AddMockHandler(mock_handler.release(),
5406 HttpAuth::AUTH_SERVER);
5407
5408 // Add another handler for the second challenge. It supports default
5409 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195410 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165411 mock_handler->set_allows_default_credentials(true);
5412 mock_handler->set_allows_explicit_credentials(true);
5413 mock_handler->set_connection_based(true);
5414 auth_handler_factory->AddMockHandler(mock_handler.release(),
5415 HttpAuth::AUTH_SERVER);
5416 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5417
5418 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5419
5420 MockWrite data_writes1[] = {
5421 MockWrite("GET / HTTP/1.1\r\n"
5422 "Host: www.example.org\r\n"
5423 "Connection: keep-alive\r\n\r\n"),
5424 };
5425
5426 MockRead data_reads1[] = {
5427 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5428 "WWW-Authenticate: Mock\r\n"
5429 "Connection: keep-alive\r\n\r\n"),
5430 };
5431
5432 // Identical to data_writes1[]. The AuthHandler encounters a
5433 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
5434 // transaction procceds without an authorization header.
5435 MockWrite data_writes2[] = {
5436 MockWrite("GET / HTTP/1.1\r\n"
5437 "Host: www.example.org\r\n"
5438 "Connection: keep-alive\r\n\r\n"),
5439 };
5440
5441 MockRead data_reads2[] = {
5442 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5443 "WWW-Authenticate: Mock\r\n"
5444 "Connection: keep-alive\r\n\r\n"),
5445 };
5446
5447 MockWrite data_writes3[] = {
5448 MockWrite("GET / HTTP/1.1\r\n"
5449 "Host: www.example.org\r\n"
5450 "Connection: keep-alive\r\n"
5451 "Authorization: auth_token\r\n\r\n"),
5452 };
5453
5454 MockRead data_reads3[] = {
5455 MockRead("HTTP/1.1 200 OK\r\n"
5456 "Content-Length: 5\r\n"
5457 "Content-Type: text/plain\r\n"
5458 "Connection: keep-alive\r\n\r\n"
5459 "Hello"),
5460 };
5461
Ryan Sleevib8d7ea02018-05-07 20:01:015462 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:165463 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5464
Ryan Sleevib8d7ea02018-05-07 20:01:015465 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:165466 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5467
Ryan Sleevib8d7ea02018-05-07 20:01:015468 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:165469 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5470
bnc87dcefc2017-05-25 12:47:585471 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195472 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:165473
5474 TestCompletionCallback callback;
5475 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5476 EXPECT_THAT(callback.GetResult(rv), IsOk());
5477
5478 const HttpResponseInfo* response = trans->GetResponseInfo();
5479 ASSERT_TRUE(response);
5480 ASSERT_TRUE(response->headers);
5481 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5482
5483 // The following three tests assert that an authentication challenge was
5484 // received and that the stack is ready to respond to the challenge using
5485 // ambient credentials.
5486 EXPECT_EQ(401, response->headers->response_code());
5487 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585488 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165489
5490 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5491 EXPECT_THAT(callback.GetResult(rv), IsOk());
5492 response = trans->GetResponseInfo();
5493 ASSERT_TRUE(response);
5494 ASSERT_TRUE(response->headers);
5495
5496 // The following three tests assert that an authentication challenge was
5497 // received and that the stack needs explicit credentials before it is ready
5498 // to respond to the challenge.
5499 EXPECT_EQ(401, response->headers->response_code());
5500 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585501 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165502
5503 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5504 EXPECT_THAT(callback.GetResult(rv), IsOk());
5505 response = trans->GetResponseInfo();
5506 ASSERT_TRUE(response);
5507 ASSERT_TRUE(response->headers);
5508 EXPECT_EQ(200, response->headers->response_code());
5509
5510 trans.reset();
5511 session->CloseAllConnections();
5512}
5513
Matt Menked1eb6d42018-01-17 04:54:065514// Proxy resolver that returns a proxy with the same host and port for different
5515// schemes, based on the path of the URL being requests.
5516class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
5517 public:
5518 SameProxyWithDifferentSchemesProxyResolver() {}
5519 ~SameProxyWithDifferentSchemesProxyResolver() override {}
5520
5521 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
5522
5523 static HostPortPair ProxyHostPortPair() {
5524 return HostPortPair::FromString(ProxyHostPortPairAsString());
5525 }
5526
5527 // ProxyResolver implementation.
5528 int GetProxyForURL(const GURL& url,
5529 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:175530 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:065531 std::unique_ptr<Request>* request,
5532 const NetLogWithSource& /*net_log*/) override {
5533 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:575534 results->set_traffic_annotation(
5535 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:065536 if (url.path() == "/socks4") {
5537 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
5538 return OK;
5539 }
5540 if (url.path() == "/socks5") {
5541 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
5542 return OK;
5543 }
5544 if (url.path() == "/http") {
5545 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
5546 return OK;
5547 }
5548 if (url.path() == "/https") {
5549 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
5550 return OK;
5551 }
Matt Menkee8648fa2019-01-17 16:47:075552 if (url.path() == "/https_trusted") {
5553 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
5554 ProxyHostPortPair(),
5555 true /* is_trusted_proxy */));
5556 return OK;
5557 }
Matt Menked1eb6d42018-01-17 04:54:065558 NOTREACHED();
5559 return ERR_NOT_IMPLEMENTED;
5560 }
5561
5562 private:
5563 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
5564};
5565
5566class SameProxyWithDifferentSchemesProxyResolverFactory
5567 : public ProxyResolverFactory {
5568 public:
5569 SameProxyWithDifferentSchemesProxyResolverFactory()
5570 : ProxyResolverFactory(false) {}
5571
Lily Houghton99597862018-03-07 16:40:425572 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
5573 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:175574 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:425575 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:065576 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
5577 return OK;
5578 }
5579
5580 private:
5581 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
5582};
5583
5584// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:075585// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:065586// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
5587// request to foo.com using proxy.com as an HTTP proxy.
5588TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:495589 session_deps_.proxy_resolution_service =
5590 std::make_unique<ProxyResolutionService>(
5591 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5592 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
5593 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
5594 nullptr);
Matt Menked1eb6d42018-01-17 04:54:065595
5596 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5597
5598 MockWrite socks_writes[] = {
5599 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
5600 kSOCKS4OkRequestLocalHostPort80Length),
5601 MockWrite(SYNCHRONOUS,
5602 "GET /socks4 HTTP/1.1\r\n"
5603 "Host: test\r\n"
5604 "Connection: keep-alive\r\n\r\n"),
5605 };
5606 MockRead socks_reads[] = {
5607 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
5608 MockRead("HTTP/1.0 200 OK\r\n"
5609 "Connection: keep-alive\r\n"
5610 "Content-Length: 15\r\n\r\n"
5611 "SOCKS4 Response"),
5612 };
Ryan Sleevib8d7ea02018-05-07 20:01:015613 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065614 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5615
5616 const char kSOCKS5Request[] = {
5617 0x05, // Version
5618 0x01, // Command (CONNECT)
5619 0x00, // Reserved
5620 0x03, // Address type (DOMAINNAME)
5621 0x04, // Length of domain (4)
5622 't', 'e', 's', 't', // Domain string
5623 0x00, 0x50, // 16-bit port (80)
5624 };
5625 MockWrite socks5_writes[] = {
5626 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245627 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065628 MockWrite(SYNCHRONOUS,
5629 "GET /socks5 HTTP/1.1\r\n"
5630 "Host: test\r\n"
5631 "Connection: keep-alive\r\n\r\n"),
5632 };
5633 MockRead socks5_reads[] = {
5634 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5635 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5636 MockRead("HTTP/1.0 200 OK\r\n"
5637 "Connection: keep-alive\r\n"
5638 "Content-Length: 15\r\n\r\n"
5639 "SOCKS5 Response"),
5640 };
Ryan Sleevib8d7ea02018-05-07 20:01:015641 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065642 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5643
5644 MockWrite http_writes[] = {
5645 MockWrite(SYNCHRONOUS,
5646 "GET http://test/http HTTP/1.1\r\n"
5647 "Host: test\r\n"
5648 "Proxy-Connection: keep-alive\r\n\r\n"),
5649 };
5650 MockRead http_reads[] = {
5651 MockRead("HTTP/1.1 200 OK\r\n"
5652 "Proxy-Connection: keep-alive\r\n"
5653 "Content-Length: 13\r\n\r\n"
5654 "HTTP Response"),
5655 };
Ryan Sleevib8d7ea02018-05-07 20:01:015656 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065657 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5658
5659 MockWrite https_writes[] = {
5660 MockWrite(SYNCHRONOUS,
5661 "GET http://test/https HTTP/1.1\r\n"
5662 "Host: test\r\n"
5663 "Proxy-Connection: keep-alive\r\n\r\n"),
5664 };
5665 MockRead https_reads[] = {
5666 MockRead("HTTP/1.1 200 OK\r\n"
5667 "Proxy-Connection: keep-alive\r\n"
5668 "Content-Length: 14\r\n\r\n"
5669 "HTTPS Response"),
5670 };
Ryan Sleevib8d7ea02018-05-07 20:01:015671 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065672 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5673 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5674 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5675
Matt Menkee8648fa2019-01-17 16:47:075676 MockWrite https_trusted_writes[] = {
5677 MockWrite(SYNCHRONOUS,
5678 "GET http://test/https_trusted HTTP/1.1\r\n"
5679 "Host: test\r\n"
5680 "Proxy-Connection: keep-alive\r\n\r\n"),
5681 };
5682 MockRead https_trusted_reads[] = {
5683 MockRead("HTTP/1.1 200 OK\r\n"
5684 "Proxy-Connection: keep-alive\r\n"
5685 "Content-Length: 22\r\n\r\n"
5686 "HTTPS Trusted Response"),
5687 };
5688 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5689 https_trusted_writes);
5690 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5691 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5692 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5693
Matt Menked1eb6d42018-01-17 04:54:065694 struct TestCase {
5695 GURL url;
5696 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075697 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065698 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075699 int expected_idle_socks4_sockets;
5700 int expected_idle_socks5_sockets;
5701 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5702 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065703 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075704 int expected_idle_https_sockets;
5705 // How many idle sockets there should be in the HTTPS proxy socket pool with
5706 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5707 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065708 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075709 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5710 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5711 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5712 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5713 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5714 1},
Matt Menked1eb6d42018-01-17 04:54:065715 };
5716
5717 for (const auto& test_case : kTestCases) {
5718 HttpRequestInfo request;
5719 request.method = "GET";
5720 request.url = test_case.url;
Ramin Halavatib5e433e62018-02-07 07:41:105721 request.traffic_annotation =
5722 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065723 std::unique_ptr<HttpNetworkTransaction> trans =
5724 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5725 session.get());
5726 TestCompletionCallback callback;
5727 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5728 EXPECT_THAT(callback.GetResult(rv), IsOk());
5729
5730 const HttpResponseInfo* response = trans->GetResponseInfo();
5731 ASSERT_TRUE(response);
5732 ASSERT_TRUE(response->headers);
5733 EXPECT_EQ(200, response->headers->response_code());
5734 std::string response_data;
5735 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5736 EXPECT_EQ(test_case.expected_response, response_data);
5737
5738 // Return the socket to the socket pool, so can make sure it's not used for
5739 // the next requests.
5740 trans.reset();
5741 base::RunLoop().RunUntilIdle();
5742
5743 // Check the number of idle sockets in the pool, to make sure that used
5744 // sockets are indeed being returned to the socket pool. If each request
5745 // doesn't return an idle socket to the pool, the test would incorrectly
5746 // pass.
Matt Menkee8648fa2019-01-17 16:47:075747 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5748 session
Matt Menked23ab952019-03-06 00:24:405749 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075750 HttpNetworkSession::NORMAL_SOCKET_POOL,
5751 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5752 SameProxyWithDifferentSchemesProxyResolver::
5753 ProxyHostPortPair()))
5754 ->IdleSocketCount());
5755 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5756 session
Matt Menked23ab952019-03-06 00:24:405757 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075758 HttpNetworkSession::NORMAL_SOCKET_POOL,
5759 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5760 SameProxyWithDifferentSchemesProxyResolver::
5761 ProxyHostPortPair()))
5762 ->IdleSocketCount());
5763 EXPECT_EQ(test_case.expected_idle_http_sockets,
5764 session
Matt Menked23ab952019-03-06 00:24:405765 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075766 HttpNetworkSession::NORMAL_SOCKET_POOL,
5767 ProxyServer(ProxyServer::SCHEME_HTTP,
5768 SameProxyWithDifferentSchemesProxyResolver::
5769 ProxyHostPortPair()))
5770 ->IdleSocketCount());
5771 EXPECT_EQ(test_case.expected_idle_https_sockets,
5772 session
Matt Menked23ab952019-03-06 00:24:405773 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075774 HttpNetworkSession::NORMAL_SOCKET_POOL,
5775 ProxyServer(ProxyServer::SCHEME_HTTPS,
5776 SameProxyWithDifferentSchemesProxyResolver::
5777 ProxyHostPortPair()))
5778 ->IdleSocketCount());
5779 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5780 session
Matt Menked23ab952019-03-06 00:24:405781 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075782 HttpNetworkSession::NORMAL_SOCKET_POOL,
5783 ProxyServer(ProxyServer::SCHEME_HTTPS,
5784 SameProxyWithDifferentSchemesProxyResolver::
5785 ProxyHostPortPair(),
5786 true /* is_trusted_proxy */))
5787 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065788 }
5789}
5790
[email protected]029c83b62013-01-24 05:28:205791// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015792TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205793 HttpRequestInfo request1;
5794 request1.method = "GET";
bncce36dca22015-04-21 22:11:235795 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105796 request1.traffic_annotation =
5797 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205798
5799 HttpRequestInfo request2;
5800 request2.method = "GET";
bncce36dca22015-04-21 22:11:235801 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105802 request2.traffic_annotation =
5803 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205804
5805 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495806 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5807 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515808 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075809 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095810 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205811
5812 // Since we have proxy, should try to establish tunnel.
5813 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175814 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5815 "Host: www.example.org:443\r\n"
5816 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205817
rsleevidb16bb02015-11-12 23:47:175818 MockWrite("GET /1 HTTP/1.1\r\n"
5819 "Host: www.example.org\r\n"
5820 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205821
rsleevidb16bb02015-11-12 23:47:175822 MockWrite("GET /2 HTTP/1.1\r\n"
5823 "Host: www.example.org\r\n"
5824 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205825 };
5826
5827 // The proxy responds to the connect with a 407, using a persistent
5828 // connection.
5829 MockRead data_reads1[] = {
5830 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5831
5832 MockRead("HTTP/1.1 200 OK\r\n"),
5833 MockRead("Content-Length: 1\r\n\r\n"),
5834 MockRead(SYNCHRONOUS, "1"),
5835
5836 MockRead("HTTP/1.1 200 OK\r\n"),
5837 MockRead("Content-Length: 2\r\n\r\n"),
5838 MockRead(SYNCHRONOUS, "22"),
5839 };
5840
Ryan Sleevib8d7ea02018-05-07 20:01:015841 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075842 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205843 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075844 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205845
5846 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585847 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195848 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205849
5850 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015851 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205852
5853 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015854 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205855
5856 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525857 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475858 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525859 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205860 EXPECT_EQ(1, response1->headers->GetContentLength());
5861
5862 LoadTimingInfo load_timing_info1;
5863 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5864 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5865
5866 trans1.reset();
5867
5868 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585869 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195870 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205871
5872 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015873 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205874
5875 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015876 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205877
5878 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525879 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475880 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525881 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205882 EXPECT_EQ(2, response2->headers->GetContentLength());
5883
5884 LoadTimingInfo load_timing_info2;
5885 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5886 TestLoadTimingReused(load_timing_info2);
5887
5888 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5889
5890 trans2.reset();
5891 session->CloseAllConnections();
5892}
5893
5894// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015895TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205896 HttpRequestInfo request1;
5897 request1.method = "GET";
bncce36dca22015-04-21 22:11:235898 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105899 request1.traffic_annotation =
5900 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205901
5902 HttpRequestInfo request2;
5903 request2.method = "GET";
bncce36dca22015-04-21 22:11:235904 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105905 request2.traffic_annotation =
5906 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205907
5908 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595909 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495910 ProxyResolutionService::CreateFixedFromPacResult(
5911 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515912 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075913 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095914 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205915
5916 // Since we have proxy, should try to establish tunnel.
5917 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175918 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5919 "Host: www.example.org:443\r\n"
5920 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205921
rsleevidb16bb02015-11-12 23:47:175922 MockWrite("GET /1 HTTP/1.1\r\n"
5923 "Host: www.example.org\r\n"
5924 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205925
rsleevidb16bb02015-11-12 23:47:175926 MockWrite("GET /2 HTTP/1.1\r\n"
5927 "Host: www.example.org\r\n"
5928 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205929 };
5930
5931 // The proxy responds to the connect with a 407, using a persistent
5932 // connection.
5933 MockRead data_reads1[] = {
5934 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5935
5936 MockRead("HTTP/1.1 200 OK\r\n"),
5937 MockRead("Content-Length: 1\r\n\r\n"),
5938 MockRead(SYNCHRONOUS, "1"),
5939
5940 MockRead("HTTP/1.1 200 OK\r\n"),
5941 MockRead("Content-Length: 2\r\n\r\n"),
5942 MockRead(SYNCHRONOUS, "22"),
5943 };
5944
Ryan Sleevib8d7ea02018-05-07 20:01:015945 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075946 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205947 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075948 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205949
5950 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585951 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195952 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205953
5954 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015955 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205956
5957 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015958 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205959
5960 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525961 ASSERT_TRUE(response1);
5962 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205963 EXPECT_EQ(1, response1->headers->GetContentLength());
5964
5965 LoadTimingInfo load_timing_info1;
5966 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5967 TestLoadTimingNotReusedWithPac(load_timing_info1,
5968 CONNECT_TIMING_HAS_SSL_TIMES);
5969
5970 trans1.reset();
5971
5972 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585973 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195974 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205975
5976 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015977 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205978
5979 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015980 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205981
5982 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525983 ASSERT_TRUE(response2);
5984 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205985 EXPECT_EQ(2, response2->headers->GetContentLength());
5986
5987 LoadTimingInfo load_timing_info2;
5988 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5989 TestLoadTimingReusedWithPac(load_timing_info2);
5990
5991 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5992
5993 trans2.reset();
5994 session->CloseAllConnections();
5995}
5996
[email protected]2df19bb2010-08-25 20:13:465997// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015998TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275999 HttpRequestInfo request;
6000 request.method = "GET";
bncce36dca22015-04-21 22:11:236001 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106002 request.traffic_annotation =
6003 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276004
[email protected]2df19bb2010-08-25 20:13:466005 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496006 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6007 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516008 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076009 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096010 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:466011
[email protected]2df19bb2010-08-25 20:13:466012 // Since we have proxy, should use full url
6013 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236014 MockWrite(
6015 "GET http://www.example.org/ HTTP/1.1\r\n"
6016 "Host: www.example.org\r\n"
6017 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466018 };
6019
6020 MockRead data_reads1[] = {
6021 MockRead("HTTP/1.1 200 OK\r\n"),
6022 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6023 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066024 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466025 };
6026
Ryan Sleevib8d7ea02018-05-07 20:01:016027 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076028 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066029 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076030 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466031
[email protected]49639fa2011-12-20 23:22:416032 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466033
bnc691fda62016-08-12 00:43:166034 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506035
bnc691fda62016-08-12 00:43:166036 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016037 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466038
6039 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016040 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466041
[email protected]58e32bb2013-01-21 18:23:256042 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166043 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256044 TestLoadTimingNotReused(load_timing_info,
6045 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6046
bnc691fda62016-08-12 00:43:166047 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526048 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466049
tbansal2ecbbc72016-10-06 17:15:476050 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:466051 EXPECT_TRUE(response->headers->IsKeepAlive());
6052 EXPECT_EQ(200, response->headers->response_code());
6053 EXPECT_EQ(100, response->headers->GetContentLength());
6054 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6055
6056 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586057 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466058}
6059
[email protected]7642b5ae2010-09-01 20:55:176060// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016061TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276062 HttpRequestInfo request;
6063 request.method = "GET";
bncce36dca22015-04-21 22:11:236064 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106065 request.traffic_annotation =
6066 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276067
[email protected]7642b5ae2010-09-01 20:55:176068 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496069 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6070 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516071 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076072 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096073 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:176074
bncce36dca22015-04-21 22:11:236075 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136076 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456077 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416078 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:176079
Ryan Hamilton0239aac2018-05-19 00:03:136080 spdy::SpdySerializedFrame resp(
6081 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6082 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:176083 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416084 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:176085 };
6086
Ryan Sleevib8d7ea02018-05-07 20:01:016087 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076088 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:176089
[email protected]8ddf8322012-02-23 18:08:066090 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366091 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076092 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:176093
[email protected]49639fa2011-12-20 23:22:416094 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:176095
bnc691fda62016-08-12 00:43:166096 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506097
bnc691fda62016-08-12 00:43:166098 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016099 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:176100
6101 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016102 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:176103
[email protected]58e32bb2013-01-21 18:23:256104 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166105 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256106 TestLoadTimingNotReused(load_timing_info,
6107 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6108
bnc691fda62016-08-12 00:43:166109 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526110 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:476111 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:526112 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026113 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:176114
6115 std::string response_data;
bnc691fda62016-08-12 00:43:166116 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236117 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:176118}
6119
[email protected]1c173852014-06-19 12:51:506120// Verifies that a session which races and wins against the owning transaction
6121// (completing prior to host resolution), doesn't fail the transaction.
6122// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:016123TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:506124 HttpRequestInfo request;
6125 request.method = "GET";
bncce36dca22015-04-21 22:11:236126 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106127 request.traffic_annotation =
6128 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:506129
6130 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496131 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6132 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516133 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:506134 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096135 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:506136
bncce36dca22015-04-21 22:11:236137 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:136138 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456139 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416140 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:506141
Raul Tambre94493c652019-03-11 17:18:356142 spdy::SpdySerializedFrame resp(
6143 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136144 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:506145 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416146 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:506147 };
6148
Ryan Sleevib8d7ea02018-05-07 20:01:016149 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:506150 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6151
6152 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366153 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:506154 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6155
6156 TestCompletionCallback callback1;
6157
bnc691fda62016-08-12 00:43:166158 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:506159
6160 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:506161 session_deps_.host_resolver->set_ondemand_mode(true);
6162
bnc691fda62016-08-12 00:43:166163 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016164 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:506165
6166 // Race a session to the proxy, which completes first.
6167 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:046168 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:116169 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:346170 SpdySessionKey::IsProxySession::kTrue, SocketTag(),
6171 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]1c173852014-06-19 12:51:506172 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:526173 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:506174
6175 // Unstall the resolution begun by the transaction.
6176 session_deps_.host_resolver->set_ondemand_mode(true);
6177 session_deps_.host_resolver->ResolveAllPending();
6178
6179 EXPECT_FALSE(callback1.have_result());
6180 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016181 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:506182
bnc691fda62016-08-12 00:43:166183 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526184 ASSERT_TRUE(response);
6185 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026186 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:506187
6188 std::string response_data;
bnc691fda62016-08-12 00:43:166189 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:506190 EXPECT_EQ(kUploadData, response_data);
6191}
6192
[email protected]dc7bd1c52010-11-12 00:01:136193// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016194TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:276195 HttpRequestInfo request;
6196 request.method = "GET";
bncce36dca22015-04-21 22:11:236197 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106198 request.traffic_annotation =
6199 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276200
[email protected]79cb5c12011-09-12 13:12:046201 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496202 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6203 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516204 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076205 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096206 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:136207
[email protected]dc7bd1c52010-11-12 00:01:136208 // The first request will be a bare GET, the second request will be a
6209 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:456210 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:136211 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:486212 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:386213 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:136214 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466215 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:136216 };
Ryan Hamilton0239aac2018-05-19 00:03:136217 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:246218 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:486219 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:136220 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416221 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:136222 };
6223
6224 // The first response is a 407 proxy authentication challenge, and the second
6225 // response will be a 200 response since the second request includes a valid
6226 // Authorization header.
6227 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466228 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:136229 };
Ryan Hamilton0239aac2018-05-19 00:03:136230 spdy::SpdySerializedFrame resp_authentication(
6231 spdy_util_.ConstructSpdyReplyError(
6232 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:246233 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136234 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:416235 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:136236 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:356237 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136238 spdy::SpdySerializedFrame body_data(
6239 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:136240 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416241 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:466242 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416243 CreateMockRead(resp_data, 4),
6244 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:136245 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:136246 };
6247
Ryan Sleevib8d7ea02018-05-07 20:01:016248 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076249 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:136250
[email protected]8ddf8322012-02-23 18:08:066251 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366252 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076253 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:136254
[email protected]49639fa2011-12-20 23:22:416255 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:136256
bnc691fda62016-08-12 00:43:166257 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:136258
bnc691fda62016-08-12 00:43:166259 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016260 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136261
6262 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016263 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136264
bnc691fda62016-08-12 00:43:166265 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136266
wezca1070932016-05-26 20:30:526267 ASSERT_TRUE(response);
6268 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:136269 EXPECT_EQ(407, response->headers->response_code());
6270 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:586271 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:136272
[email protected]49639fa2011-12-20 23:22:416273 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:136274
bnc691fda62016-08-12 00:43:166275 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016276 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136277
6278 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016279 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136280
bnc691fda62016-08-12 00:43:166281 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136282
wezca1070932016-05-26 20:30:526283 ASSERT_TRUE(response_restart);
6284 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:136285 EXPECT_EQ(200, response_restart->headers->response_code());
6286 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586287 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:136288}
6289
[email protected]d9da5fe2010-10-13 22:37:166290// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:016291TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:276292 HttpRequestInfo request;
6293 request.method = "GET";
bncce36dca22015-04-21 22:11:236294 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106295 request.traffic_annotation =
6296 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276297
[email protected]d9da5fe2010-10-13 22:37:166298 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496299 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6300 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516301 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076302 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096303 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166304
bnc691fda62016-08-12 00:43:166305 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166306
bncce36dca22015-04-21 22:11:236307 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136308 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046309 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6310 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236311 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:166312
bncce36dca22015-04-21 22:11:236313 const char get[] =
6314 "GET / HTTP/1.1\r\n"
6315 "Host: www.example.org\r\n"
6316 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136317 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:196318 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:136319 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356320 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:166321 const char resp[] = "HTTP/1.1 200 OK\r\n"
6322 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136323 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:196324 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:136325 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:196326 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:136327 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416328 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:046329
6330 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416331 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6332 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:046333 };
6334
[email protected]d9da5fe2010-10-13 22:37:166335 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416336 CreateMockRead(conn_resp, 1, ASYNC),
6337 CreateMockRead(wrapped_get_resp, 3, ASYNC),
6338 CreateMockRead(wrapped_body, 4, ASYNC),
6339 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136340 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:166341 };
6342
Ryan Sleevib8d7ea02018-05-07 20:01:016343 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076344 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166345
[email protected]8ddf8322012-02-23 18:08:066346 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366347 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076348 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066349 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076350 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166351
[email protected]49639fa2011-12-20 23:22:416352 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166353
bnc691fda62016-08-12 00:43:166354 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016355 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166356
6357 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016358 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166359
[email protected]58e32bb2013-01-21 18:23:256360 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166361 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256362 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6363
bnc691fda62016-08-12 00:43:166364 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526365 ASSERT_TRUE(response);
6366 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:166367 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6368
6369 std::string response_data;
bnc691fda62016-08-12 00:43:166370 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:166371 EXPECT_EQ("1234567890", response_data);
6372}
6373
6374// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:016375TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
6376 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:386377
[email protected]cb9bf6ca2011-01-28 13:15:276378 HttpRequestInfo request;
6379 request.method = "GET";
bncce36dca22015-04-21 22:11:236380 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106381 request.traffic_annotation =
6382 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276383
[email protected]d9da5fe2010-10-13 22:37:166384 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496385 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6386 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516387 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076388 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096389 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166390
bnc691fda62016-08-12 00:43:166391 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166392
bncce36dca22015-04-21 22:11:236393 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136394 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046395 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6396 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236397 // fetch https://www.example.org/ via SPDY
6398 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:136399 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:496400 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:136401 spdy::SpdySerializedFrame wrapped_get(
6402 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6403 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356404 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136405 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356406 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136407 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:026408 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136409 spdy::SpdySerializedFrame body(
6410 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
6411 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:026412 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136413 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:416414 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:136415 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:416416 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:046417
6418 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416419 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6420 CreateMockWrite(window_update_get_resp, 6),
6421 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:046422 };
6423
[email protected]d9da5fe2010-10-13 22:37:166424 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416425 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:096426 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:416427 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6428 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136429 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:166430 };
6431
Ryan Sleevib8d7ea02018-05-07 20:01:016432 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076433 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166434
[email protected]8ddf8322012-02-23 18:08:066435 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366436 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076437 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066438 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366439 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076440 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166441
[email protected]49639fa2011-12-20 23:22:416442 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166443
bnc691fda62016-08-12 00:43:166444 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016445 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166446
rch32320842015-05-16 15:57:096447 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:556448 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:096449 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:596450 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:166451 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016452 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166453
[email protected]58e32bb2013-01-21 18:23:256454 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166455 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256456 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6457
bnc691fda62016-08-12 00:43:166458 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526459 ASSERT_TRUE(response);
6460 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026461 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:166462
6463 std::string response_data;
bnc691fda62016-08-12 00:43:166464 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236465 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:166466}
6467
6468// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016469TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:276470 HttpRequestInfo request;
6471 request.method = "GET";
bncce36dca22015-04-21 22:11:236472 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106473 request.traffic_annotation =
6474 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276475
[email protected]d9da5fe2010-10-13 22:37:166476 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496477 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6478 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516479 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076480 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096481 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166482
bnc691fda62016-08-12 00:43:166483 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166484
bncce36dca22015-04-21 22:11:236485 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136486 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046487 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6488 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136489 spdy::SpdySerializedFrame get(
6490 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:166491
6492 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416493 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:166494 };
6495
Ryan Hamilton0239aac2018-05-19 00:03:136496 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
6497 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:166498 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416499 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:166500 };
6501
Ryan Sleevib8d7ea02018-05-07 20:01:016502 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076503 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166504
[email protected]8ddf8322012-02-23 18:08:066505 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366506 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076507 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066508 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366509 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076510 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166511
[email protected]49639fa2011-12-20 23:22:416512 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166513
bnc691fda62016-08-12 00:43:166514 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016515 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166516
6517 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016518 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:166519
ttuttle960fcbf2016-04-19 13:26:326520 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:166521}
6522
Matt Menkecb2cd0982018-12-19 17:54:046523// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:246524// is observed, but does exist by the time auth credentials are provided. In
6525// this case, auth and SSL are fully negotated on the second request, but then
6526// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:046527TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
6528 ProxyConfig proxy_config;
6529 proxy_config.set_auto_detect(true);
6530 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6531
6532 CapturingProxyResolver capturing_proxy_resolver;
6533 capturing_proxy_resolver.set_proxy_server(
6534 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
6535 session_deps_.proxy_resolution_service =
6536 std::make_unique<ProxyResolutionService>(
6537 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6538 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6539 std::make_unique<CapturingProxyResolverFactory>(
6540 &capturing_proxy_resolver),
6541 nullptr);
6542
6543 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6544
6545 const char kMyUrl[] = "https://www.example.org/";
6546 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6547 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356548 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:046549 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6550
6551 spdy_util_.UpdateWithStreamDestruction(1);
6552 spdy::SpdySerializedFrame get2(
6553 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
6554 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356555 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:046556 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
6557
6558 MockWrite auth_challenge_writes[] = {
6559 MockWrite(ASYNC, 0,
6560 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6561 "Host: www.example.org:443\r\n"
6562 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:246563 MockWrite(ASYNC, 2,
6564 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6565 "Host: www.example.org:443\r\n"
6566 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:046567 };
6568
6569 MockRead auth_challenge_reads[] = {
6570 MockRead(ASYNC, 1,
6571 "HTTP/1.1 407 Authentication Required\r\n"
6572 "Content-Length: 0\r\n"
6573 "Proxy-Connection: close\r\n"
6574 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
6575 };
6576
6577 MockWrite spdy_writes[] = {
6578 MockWrite(ASYNC, 0,
6579 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6580 "Host: www.example.org:443\r\n"
6581 "Proxy-Connection: keep-alive\r\n"
6582 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6583 CreateMockWrite(get, 2),
6584 CreateMockWrite(get2, 5),
6585 };
6586
6587 MockRead spdy_reads[] = {
6588 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6589 CreateMockRead(get_resp, 3, ASYNC),
6590 CreateMockRead(body, 4, ASYNC),
6591 CreateMockRead(get_resp2, 6, ASYNC),
6592 CreateMockRead(body2, 7, ASYNC),
6593
6594 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
6595 };
6596
Matt Menke5062be22019-05-01 17:50:246597 MockWrite auth_response_writes_discarded_socket[] = {
6598 MockWrite(ASYNC, 0,
6599 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6600 "Host: www.example.org:443\r\n"
6601 "Proxy-Connection: keep-alive\r\n"
6602 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6603 };
6604
6605 MockRead auth_response_reads_discarded_socket[] = {
6606 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6607 };
6608
Matt Menkecb2cd0982018-12-19 17:54:046609 SequencedSocketData auth_challenge1(auth_challenge_reads,
6610 auth_challenge_writes);
6611 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
6612
6613 SequencedSocketData auth_challenge2(auth_challenge_reads,
6614 auth_challenge_writes);
6615 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
6616
6617 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6618 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6619
Matt Menke5062be22019-05-01 17:50:246620 SequencedSocketData auth_response_discarded_socket(
6621 auth_response_reads_discarded_socket,
6622 auth_response_writes_discarded_socket);
6623 session_deps_.socket_factory->AddSocketDataProvider(
6624 &auth_response_discarded_socket);
6625
Matt Menkecb2cd0982018-12-19 17:54:046626 SSLSocketDataProvider ssl(ASYNC, OK);
6627 ssl.next_proto = kProtoHTTP2;
6628 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6629
Matt Menke5062be22019-05-01 17:50:246630 SSLSocketDataProvider ssl2(ASYNC, OK);
6631 ssl2.next_proto = kProtoHTTP2;
6632 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6633
Matt Menkecb2cd0982018-12-19 17:54:046634 TestCompletionCallback callback;
6635 std::string response_data;
6636
6637 // Run first request until an auth challenge is observed.
6638 HttpRequestInfo request1;
6639 request1.method = "GET";
6640 request1.url = GURL(kMyUrl);
6641 request1.traffic_annotation =
6642 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6643 HttpNetworkTransaction trans1(LOWEST, session.get());
6644 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6645 EXPECT_THAT(callback.GetResult(rv), IsOk());
6646 const HttpResponseInfo* response = trans1.GetResponseInfo();
6647 ASSERT_TRUE(response);
6648 ASSERT_TRUE(response->headers);
6649 EXPECT_EQ(407, response->headers->response_code());
6650 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586651 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046652
6653 // Run second request until an auth challenge is observed.
6654 HttpRequestInfo request2;
6655 request2.method = "GET";
6656 request2.url = GURL(kMyUrl);
6657 request2.traffic_annotation =
6658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6659 HttpNetworkTransaction trans2(LOWEST, session.get());
6660 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6661 EXPECT_THAT(callback.GetResult(rv), IsOk());
6662 response = trans2.GetResponseInfo();
6663 ASSERT_TRUE(response);
6664 ASSERT_TRUE(response->headers);
6665 EXPECT_EQ(407, response->headers->response_code());
6666 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586667 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046668
6669 // Now provide credentials for the first request, and wait for it to complete.
6670 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6671 rv = callback.GetResult(rv);
6672 EXPECT_THAT(rv, IsOk());
6673 response = trans1.GetResponseInfo();
6674 ASSERT_TRUE(response);
6675 ASSERT_TRUE(response->headers);
6676 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6677 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6678 EXPECT_EQ(kUploadData, response_data);
6679
6680 // Now provide credentials for the second request. It should notice the
6681 // existing session, and reuse it.
6682 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6683 EXPECT_THAT(callback.GetResult(rv), IsOk());
6684 response = trans2.GetResponseInfo();
6685 ASSERT_TRUE(response);
6686 ASSERT_TRUE(response->headers);
6687 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6688 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6689 EXPECT_EQ(kUploadData, response_data);
6690}
6691
[email protected]f6c63db52013-02-02 00:35:226692// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6693// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016694TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226695 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6696 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496697 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6698 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516699 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076700 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096701 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506702 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226703
6704 HttpRequestInfo request1;
6705 request1.method = "GET";
bncce36dca22015-04-21 22:11:236706 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226707 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106708 request1.traffic_annotation =
6709 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226710
6711 HttpRequestInfo request2;
6712 request2.method = "GET";
bncce36dca22015-04-21 22:11:236713 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226714 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106715 request2.traffic_annotation =
6716 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226717
bncce36dca22015-04-21 22:11:236718 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136719 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046720 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6721 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136722 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356723 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226724
bncce36dca22015-04-21 22:11:236725 // Fetch https://www.example.org/ via HTTP.
6726 const char get1[] =
6727 "GET / HTTP/1.1\r\n"
6728 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226729 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136730 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196731 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226732 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6733 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136734 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196735 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136736 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196737 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136738 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416739 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226740
bncce36dca22015-04-21 22:11:236741 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136742 spdy::SpdyHeaderBlock connect2_block;
6743 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6744 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6745 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046746 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6747 false));
[email protected]601e03f12014-04-06 16:26:396748
Ryan Hamilton0239aac2018-05-19 00:03:136749 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356750 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226751
bncce36dca22015-04-21 22:11:236752 // Fetch https://mail.example.org/ via HTTP.
6753 const char get2[] =
6754 "GET / HTTP/1.1\r\n"
6755 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226756 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136757 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196758 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226759 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6760 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136761 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196762 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136763 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196764 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226765
6766 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416767 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6768 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226769 };
6770
6771 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416772 CreateMockRead(conn_resp1, 1, ASYNC),
6773 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6774 CreateMockRead(wrapped_body1, 4, ASYNC),
6775 CreateMockRead(conn_resp2, 6, ASYNC),
6776 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6777 CreateMockRead(wrapped_body2, 9, ASYNC),
6778 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226779 };
6780
Ryan Sleevib8d7ea02018-05-07 20:01:016781 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506782 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226783
6784 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366785 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226787 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506788 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226789 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506790 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226791
6792 TestCompletionCallback callback;
6793
bnc691fda62016-08-12 00:43:166794 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206795 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016796 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226797
6798 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166799 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226800 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6801
bnc691fda62016-08-12 00:43:166802 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526803 ASSERT_TRUE(response);
6804 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226805 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6806
6807 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446808 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166809 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506810 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226811
bnc691fda62016-08-12 00:43:166812 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206813 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016814 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226815
6816 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166817 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226818 // Even though the SPDY connection is reused, a new tunnelled connection has
6819 // to be created, so the socket's load timing looks like a fresh connection.
6820 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6821
6822 // The requests should have different IDs, since they each are using their own
6823 // separate stream.
6824 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6825
bnc691fda62016-08-12 00:43:166826 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506827 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226828}
6829
6830// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6831// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016832TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226833 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6834 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496835 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6836 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516837 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076838 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096839 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506840 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226841
6842 HttpRequestInfo request1;
6843 request1.method = "GET";
bncce36dca22015-04-21 22:11:236844 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226845 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106846 request1.traffic_annotation =
6847 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226848
6849 HttpRequestInfo request2;
6850 request2.method = "GET";
bncce36dca22015-04-21 22:11:236851 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226852 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106853 request2.traffic_annotation =
6854 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226855
bncce36dca22015-04-21 22:11:236856 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136857 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046858 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6859 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136860 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356861 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226862
bncce36dca22015-04-21 22:11:236863 // Fetch https://www.example.org/ via HTTP.
6864 const char get1[] =
6865 "GET / HTTP/1.1\r\n"
6866 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226867 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136868 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196869 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226870 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6871 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136872 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196873 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136874 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196875 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136876 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416877 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226878
bncce36dca22015-04-21 22:11:236879 // Fetch https://www.example.org/2 via HTTP.
6880 const char get2[] =
6881 "GET /2 HTTP/1.1\r\n"
6882 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226883 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136884 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196885 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226886 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6887 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136888 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196889 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136890 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196891 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226892
6893 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416894 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6895 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226896 };
6897
6898 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416899 CreateMockRead(conn_resp1, 1, ASYNC),
6900 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466901 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416902 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466903 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416904 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226905 };
6906
Ryan Sleevib8d7ea02018-05-07 20:01:016907 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506908 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226909
6910 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366911 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506912 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226913 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506914 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226915
6916 TestCompletionCallback callback;
6917
bnc87dcefc2017-05-25 12:47:586918 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196919 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206920 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016921 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226922
6923 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016924 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226925
6926 LoadTimingInfo load_timing_info;
6927 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6928 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6929
6930 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526931 ASSERT_TRUE(response);
6932 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226933 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6934
6935 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446936 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506937 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226938 trans.reset();
6939
bnc87dcefc2017-05-25 12:47:586940 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196941 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206942 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226944
[email protected]f6c63db52013-02-02 00:35:226945 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016946 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226947
6948 LoadTimingInfo load_timing_info2;
6949 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6950 TestLoadTimingReused(load_timing_info2);
6951
6952 // The requests should have the same ID.
6953 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6954
[email protected]90499482013-06-01 00:39:506955 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226956}
6957
6958// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6959// Proxy to different servers.
bncd16676a2016-07-20 16:23:016960TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226961 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496962 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6963 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516964 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076965 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096966 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506967 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226968
6969 HttpRequestInfo request1;
6970 request1.method = "GET";
bncce36dca22015-04-21 22:11:236971 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226972 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106973 request1.traffic_annotation =
6974 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226975
6976 HttpRequestInfo request2;
6977 request2.method = "GET";
bncce36dca22015-04-21 22:11:236978 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226979 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106980 request2.traffic_annotation =
6981 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226982
bncce36dca22015-04-21 22:11:236983 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136984 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236985 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136986 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156987 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136988 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356989 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136990 spdy::SpdySerializedFrame body1(
6991 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386992 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226993
bncce36dca22015-04-21 22:11:236994 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136995 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:236996 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136997 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:156998 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136999 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:357000 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:137001 spdy::SpdySerializedFrame body2(
7002 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:227003
7004 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417005 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:227006 };
7007
7008 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417009 CreateMockRead(get_resp1, 1, ASYNC),
7010 CreateMockRead(body1, 2, ASYNC),
7011 CreateMockRead(get_resp2, 4, ASYNC),
7012 CreateMockRead(body2, 5, ASYNC),
7013 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:227014 };
7015
Ryan Sleevib8d7ea02018-05-07 20:01:017016 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507017 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227018
7019 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367020 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507021 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227022
7023 TestCompletionCallback callback;
7024
bnc87dcefc2017-05-25 12:47:587025 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197026 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207027 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017028 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227029
7030 LoadTimingInfo load_timing_info;
7031 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7032 TestLoadTimingNotReused(load_timing_info,
7033 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7034
7035 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527036 ASSERT_TRUE(response);
7037 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:027038 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:227039
7040 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447041 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:507042 rv = trans->Read(buf.get(), 256, callback.callback());
7043 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227044 // Delete the first request, so the second one can reuse the socket.
7045 trans.reset();
7046
bnc691fda62016-08-12 00:43:167047 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207048 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017049 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227050
7051 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:167052 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:227053 TestLoadTimingReused(load_timing_info2);
7054
7055 // The requests should have the same ID.
7056 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7057
bnc691fda62016-08-12 00:43:167058 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507059 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227060}
7061
Matt Menke2436b2f2018-12-11 18:07:117062// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
7063// direct (non-proxied) request to the proxy server are not pooled, as that
7064// would break socket pool isolation.
7065TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
7066 ProxyConfig proxy_config;
7067 proxy_config.set_auto_detect(true);
7068 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7069
7070 CapturingProxyResolver capturing_proxy_resolver;
7071 session_deps_.proxy_resolution_service =
7072 std::make_unique<ProxyResolutionService>(
7073 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7074 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7075 std::make_unique<CapturingProxyResolverFactory>(
7076 &capturing_proxy_resolver),
7077 nullptr);
7078
7079 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7080
7081 SpdyTestUtil spdy_util1;
7082 // CONNECT to www.example.org:443 via HTTP/2.
7083 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047084 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7085 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117086 // fetch https://www.example.org/ via HTTP/2.
7087 const char kMyUrl[] = "https://www.example.org/";
7088 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7089 spdy::SpdySerializedFrame wrapped_get(
7090 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7091 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:357092 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117093 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:357094 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117095 spdy::SpdySerializedFrame wrapped_get_resp(
7096 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7097 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
7098 spdy::SpdySerializedFrame wrapped_body(
7099 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7100 spdy::SpdySerializedFrame window_update_get_resp(
7101 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7102 spdy::SpdySerializedFrame window_update_body(
7103 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7104
7105 MockWrite spdy_writes1[] = {
7106 CreateMockWrite(connect, 0),
7107 CreateMockWrite(wrapped_get, 2),
7108 CreateMockWrite(window_update_get_resp, 6),
7109 CreateMockWrite(window_update_body, 7),
7110 };
7111
7112 MockRead spdy_reads1[] = {
7113 CreateMockRead(conn_resp, 1, ASYNC),
7114 MockRead(ASYNC, ERR_IO_PENDING, 3),
7115 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7116 CreateMockRead(wrapped_body, 5, ASYNC),
7117 MockRead(ASYNC, 0, 8),
7118 };
7119
7120 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7121 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7122
7123 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
7124 // a new pipe.
7125 SpdyTestUtil spdy_util2;
7126 spdy::SpdySerializedFrame req(
7127 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7128 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
7129
7130 spdy::SpdySerializedFrame resp(
7131 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7132 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
7133 MockRead spdy_reads2[] = {
7134 CreateMockRead(resp, 1),
7135 CreateMockRead(data, 2),
7136 MockRead(ASYNC, 0, 3),
7137 };
7138 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7139 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7140
7141 SSLSocketDataProvider ssl(ASYNC, OK);
7142 ssl.next_proto = kProtoHTTP2;
7143 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7144 SSLSocketDataProvider ssl2(ASYNC, OK);
7145 ssl2.next_proto = kProtoHTTP2;
7146 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7147 SSLSocketDataProvider ssl3(ASYNC, OK);
7148 ssl3.next_proto = kProtoHTTP2;
7149 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7150
7151 TestCompletionCallback callback;
7152 std::string response_data;
7153
7154 // Make a request using proxy:70 as a HTTP/2 proxy.
7155 capturing_proxy_resolver.set_proxy_server(
7156 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7157 HttpRequestInfo request1;
7158 request1.method = "GET";
7159 request1.url = GURL("https://www.example.org/");
7160 request1.traffic_annotation =
7161 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7162
7163 HttpNetworkTransaction trans1(LOWEST, session.get());
7164 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
7165 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7166
7167 // Allow the SpdyProxyClientSocket's write callback to complete.
7168 base::RunLoop().RunUntilIdle();
7169 // Now allow the read of the response to complete.
7170 spdy_data1.Resume();
7171 rv = callback.WaitForResult();
7172 EXPECT_THAT(rv, IsOk());
7173
7174 const HttpResponseInfo* response = trans1.GetResponseInfo();
7175 ASSERT_TRUE(response);
7176 ASSERT_TRUE(response->headers);
7177 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7178
7179 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7180 EXPECT_EQ(kUploadData, response_data);
7181 RunUntilIdle();
7182
7183 // Make a direct HTTP/2 request to proxy:70.
7184 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7185 HttpRequestInfo request2;
7186 request2.method = "GET";
7187 request2.url = GURL("https://proxy:70/");
7188 request2.traffic_annotation =
7189 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7190 HttpNetworkTransaction trans2(LOWEST, session.get());
7191 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
7192 NetLogWithSource())),
7193 IsOk());
7194 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7195}
7196
7197// Same as above, but reverse request order, since the code to check for an
7198// existing session is different for tunnels and direct connections.
7199TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
7200 // Configure against https proxy server "myproxy:80".
7201 ProxyConfig proxy_config;
7202 proxy_config.set_auto_detect(true);
7203 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7204
7205 CapturingProxyResolver capturing_proxy_resolver;
7206 session_deps_.proxy_resolution_service =
7207 std::make_unique<ProxyResolutionService>(
7208 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7209 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7210 std::make_unique<CapturingProxyResolverFactory>(
7211 &capturing_proxy_resolver),
7212 nullptr);
7213
7214 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7215 // Fetch https://proxy:70/ via HTTP/2.
7216 SpdyTestUtil spdy_util1;
7217 spdy::SpdySerializedFrame req(
7218 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7219 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
7220
7221 spdy::SpdySerializedFrame resp(
7222 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
7223 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
7224 MockRead spdy_reads1[] = {
7225 CreateMockRead(resp, 1),
7226 CreateMockRead(data, 2),
7227 MockRead(ASYNC, 0, 3),
7228 };
7229 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7230 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7231
7232 SpdyTestUtil spdy_util2;
7233 // CONNECT to www.example.org:443 via HTTP/2.
7234 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047235 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7236 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117237 // fetch https://www.example.org/ via HTTP/2.
7238 const char kMyUrl[] = "https://www.example.org/";
7239 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7240 spdy::SpdySerializedFrame wrapped_get(
7241 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7242 spdy::SpdySerializedFrame conn_resp(
7243 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7244 spdy::SpdySerializedFrame get_resp(
7245 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7246 spdy::SpdySerializedFrame wrapped_get_resp(
7247 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7248 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
7249 spdy::SpdySerializedFrame wrapped_body(
7250 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7251 spdy::SpdySerializedFrame window_update_get_resp(
7252 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7253 spdy::SpdySerializedFrame window_update_body(
7254 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7255
7256 MockWrite spdy_writes2[] = {
7257 CreateMockWrite(connect, 0),
7258 CreateMockWrite(wrapped_get, 2),
7259 CreateMockWrite(window_update_get_resp, 6),
7260 CreateMockWrite(window_update_body, 7),
7261 };
7262
7263 MockRead spdy_reads2[] = {
7264 CreateMockRead(conn_resp, 1, ASYNC),
7265 MockRead(ASYNC, ERR_IO_PENDING, 3),
7266 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7267 CreateMockRead(wrapped_body, 5, ASYNC),
7268 MockRead(ASYNC, 0, 8),
7269 };
7270
7271 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7272 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7273
7274 SSLSocketDataProvider ssl(ASYNC, OK);
7275 ssl.next_proto = kProtoHTTP2;
7276 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7277 SSLSocketDataProvider ssl2(ASYNC, OK);
7278 ssl2.next_proto = kProtoHTTP2;
7279 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7280 SSLSocketDataProvider ssl3(ASYNC, OK);
7281 ssl3.next_proto = kProtoHTTP2;
7282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7283
7284 TestCompletionCallback callback;
7285 std::string response_data;
7286
7287 // Make a direct HTTP/2 request to proxy:70.
7288 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7289 HttpRequestInfo request1;
7290 request1.method = "GET";
7291 request1.url = GURL("https://proxy:70/");
7292 request1.traffic_annotation =
7293 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7294 HttpNetworkTransaction trans1(LOWEST, session.get());
7295 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
7296 NetLogWithSource())),
7297 IsOk());
7298 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7299 RunUntilIdle();
7300
7301 // Make a request using proxy:70 as a HTTP/2 proxy.
7302 capturing_proxy_resolver.set_proxy_server(
7303 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7304 HttpRequestInfo request2;
7305 request2.method = "GET";
7306 request2.url = GURL("https://www.example.org/");
7307 request2.traffic_annotation =
7308 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7309
7310 HttpNetworkTransaction trans2(LOWEST, session.get());
7311 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
7312 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7313
7314 // Allow the SpdyProxyClientSocket's write callback to complete.
7315 base::RunLoop().RunUntilIdle();
7316 // Now allow the read of the response to complete.
7317 spdy_data2.Resume();
7318 rv = callback.WaitForResult();
7319 EXPECT_THAT(rv, IsOk());
7320
7321 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
7322 ASSERT_TRUE(response2);
7323 ASSERT_TRUE(response2->headers);
7324 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
7325
7326 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7327 EXPECT_EQ(kUploadData, response_data);
7328}
7329
[email protected]2df19bb2010-08-25 20:13:467330// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:017331TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:467332 HttpRequestInfo request;
7333 request.method = "GET";
bncce36dca22015-04-21 22:11:237334 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467335 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297336 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:107337 request.traffic_annotation =
7338 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:467339
[email protected]79cb5c12011-09-12 13:12:047340 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497341 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7342 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:517343 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077344 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097345 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277346
[email protected]2df19bb2010-08-25 20:13:467347 // Since we have proxy, should use full url
7348 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:167349 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7350 "Host: www.example.org\r\n"
7351 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467352
bnc691fda62016-08-12 00:43:167353 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:237354 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:167355 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7356 "Host: www.example.org\r\n"
7357 "Proxy-Connection: keep-alive\r\n"
7358 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467359 };
7360
7361 // The proxy responds to the GET with a 407, using a persistent
7362 // connection.
7363 MockRead data_reads1[] = {
7364 // No credentials.
7365 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7366 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7367 MockRead("Proxy-Connection: keep-alive\r\n"),
7368 MockRead("Content-Length: 0\r\n\r\n"),
7369
7370 MockRead("HTTP/1.1 200 OK\r\n"),
7371 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7372 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067373 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467374 };
7375
Ryan Sleevib8d7ea02018-05-07 20:01:017376 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077377 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:067378 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077379 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467380
[email protected]49639fa2011-12-20 23:22:417381 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:467382
bnc691fda62016-08-12 00:43:167383 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507384
bnc691fda62016-08-12 00:43:167385 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:017386 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467387
7388 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017389 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467390
[email protected]58e32bb2013-01-21 18:23:257391 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:167392 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257393 TestLoadTimingNotReused(load_timing_info,
7394 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7395
bnc691fda62016-08-12 00:43:167396 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527397 ASSERT_TRUE(response);
7398 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:467399 EXPECT_EQ(407, response->headers->response_code());
7400 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587401 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:507402 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467403
[email protected]49639fa2011-12-20 23:22:417404 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:467405
bnc691fda62016-08-12 00:43:167406 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017407 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467408
7409 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017410 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467411
[email protected]58e32bb2013-01-21 18:23:257412 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:167413 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257414 // Retrying with HTTP AUTH is considered to be reusing a socket.
7415 TestLoadTimingReused(load_timing_info);
7416
bnc691fda62016-08-12 00:43:167417 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527418 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:467419
7420 EXPECT_TRUE(response->headers->IsKeepAlive());
7421 EXPECT_EQ(200, response->headers->response_code());
7422 EXPECT_EQ(100, response->headers->GetContentLength());
7423 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:507424 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467425
7426 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:587427 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:467428}
7429
[email protected]23e482282013-06-14 16:08:027430void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:087431 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:427432 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:087433 request.method = "GET";
bncce36dca22015-04-21 22:11:237434 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107435 request.traffic_annotation =
7436 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:087437
[email protected]cb9bf6ca2011-01-28 13:15:277438 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497439 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7440 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097441 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277442
[email protected]c744cf22009-02-27 07:28:087443 // Since we have proxy, should try to establish tunnel.
7444 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177445 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7446 "Host: www.example.org:443\r\n"
7447 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:087448 };
7449
7450 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:237451 status, MockRead("Content-Length: 10\r\n\r\n"),
7452 // No response body because the test stops reading here.
7453 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:087454 };
7455
Ryan Sleevib8d7ea02018-05-07 20:01:017456 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:077457 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:087458
[email protected]49639fa2011-12-20 23:22:417459 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:087460
bnc691fda62016-08-12 00:43:167461 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507462
tfarina42834112016-09-22 13:38:207463 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017464 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:087465
7466 rv = callback.WaitForResult();
7467 EXPECT_EQ(expected_status, rv);
7468}
7469
[email protected]23e482282013-06-14 16:08:027470void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:237471 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:087472 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:427473 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:087474}
7475
bncd16676a2016-07-20 16:23:017476TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:087477 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
7478}
7479
bncd16676a2016-07-20 16:23:017480TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:087481 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
7482}
7483
bncd16676a2016-07-20 16:23:017484TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:087485 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
7486}
7487
bncd16676a2016-07-20 16:23:017488TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:087489 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
7490}
7491
bncd16676a2016-07-20 16:23:017492TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:087493 ConnectStatusHelper(
7494 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
7495}
7496
bncd16676a2016-07-20 16:23:017497TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:087498 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
7499}
7500
bncd16676a2016-07-20 16:23:017501TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:087502 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
7503}
7504
bncd16676a2016-07-20 16:23:017505TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:087506 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
7507}
7508
bncd16676a2016-07-20 16:23:017509TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:087510 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
7511}
7512
bncd16676a2016-07-20 16:23:017513TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:087514 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
7515}
7516
bncd16676a2016-07-20 16:23:017517TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:087518 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
7519}
7520
bncd16676a2016-07-20 16:23:017521TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:087522 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
7523}
7524
bncd16676a2016-07-20 16:23:017525TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:087526 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
7527}
7528
bncd16676a2016-07-20 16:23:017529TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:087530 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
7531}
7532
bncd16676a2016-07-20 16:23:017533TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:087534 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
7535}
7536
bncd16676a2016-07-20 16:23:017537TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:087538 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
7539}
7540
bncd16676a2016-07-20 16:23:017541TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:377542 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
7543}
7544
bncd16676a2016-07-20 16:23:017545TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:087546 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
7547}
7548
bncd16676a2016-07-20 16:23:017549TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:087550 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
7551}
7552
bncd16676a2016-07-20 16:23:017553TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:087554 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
7555}
7556
bncd16676a2016-07-20 16:23:017557TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:087558 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
7559}
7560
bncd16676a2016-07-20 16:23:017561TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:087562 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
7563}
7564
bncd16676a2016-07-20 16:23:017565TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:087566 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
7567}
7568
bncd16676a2016-07-20 16:23:017569TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:087570 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
7571}
7572
bncd16676a2016-07-20 16:23:017573TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:087574 ConnectStatusHelperWithExpectedStatus(
7575 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:547576 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:087577}
7578
bncd16676a2016-07-20 16:23:017579TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:087580 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
7581}
7582
bncd16676a2016-07-20 16:23:017583TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:087584 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
7585}
7586
bncd16676a2016-07-20 16:23:017587TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:087588 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
7589}
7590
bncd16676a2016-07-20 16:23:017591TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:087592 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
7593}
7594
bncd16676a2016-07-20 16:23:017595TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:087596 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
7597}
7598
bncd16676a2016-07-20 16:23:017599TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:087600 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
7601}
7602
bncd16676a2016-07-20 16:23:017603TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:087604 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
7605}
7606
bncd16676a2016-07-20 16:23:017607TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:087608 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
7609}
7610
bncd16676a2016-07-20 16:23:017611TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:087612 ConnectStatusHelper(
7613 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
7614}
7615
bncd16676a2016-07-20 16:23:017616TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:087617 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
7618}
7619
bncd16676a2016-07-20 16:23:017620TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:087621 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
7622}
7623
bncd16676a2016-07-20 16:23:017624TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:087625 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
7626}
7627
bncd16676a2016-07-20 16:23:017628TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:087629 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
7630}
7631
bncd16676a2016-07-20 16:23:017632TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:087633 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
7634}
7635
bncd16676a2016-07-20 16:23:017636TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:087637 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
7638}
7639
bncd16676a2016-07-20 16:23:017640TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087641 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7642}
7643
[email protected]038e9a32008-10-08 22:40:167644// Test the flow when both the proxy server AND origin server require
7645// authentication. Again, this uses basic auth for both since that is
7646// the simplest to mock.
bncd16676a2016-07-20 16:23:017647TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277648 HttpRequestInfo request;
7649 request.method = "GET";
bncce36dca22015-04-21 22:11:237650 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107651 request.traffic_annotation =
7652 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277653
[email protected]038e9a32008-10-08 22:40:167654 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497655 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7656 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097657 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077658
bnc691fda62016-08-12 00:43:167659 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167660
[email protected]f9ee6b52008-11-08 06:46:237661 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237662 MockWrite(
7663 "GET http://www.example.org/ HTTP/1.1\r\n"
7664 "Host: www.example.org\r\n"
7665 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237666 };
7667
[email protected]038e9a32008-10-08 22:40:167668 MockRead data_reads1[] = {
7669 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7670 // Give a couple authenticate options (only the middle one is actually
7671 // supported).
[email protected]22927ad2009-09-21 19:56:197672 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167673 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7674 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7676 // Large content-length -- won't matter, as connection will be reset.
7677 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067678 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167679 };
7680
bnc691fda62016-08-12 00:43:167681 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167682 // request we should be issuing -- the final header line contains the
7683 // proxy's credentials.
7684 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237685 MockWrite(
7686 "GET http://www.example.org/ HTTP/1.1\r\n"
7687 "Host: www.example.org\r\n"
7688 "Proxy-Connection: keep-alive\r\n"
7689 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167690 };
7691
7692 // Now the proxy server lets the request pass through to origin server.
7693 // The origin server responds with a 401.
7694 MockRead data_reads2[] = {
7695 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7696 // Note: We are using the same realm-name as the proxy server. This is
7697 // completely valid, as realms are unique across hosts.
7698 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7699 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7700 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067701 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167702 };
7703
bnc691fda62016-08-12 00:43:167704 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167705 // the credentials for both the proxy and origin server.
7706 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237707 MockWrite(
7708 "GET http://www.example.org/ HTTP/1.1\r\n"
7709 "Host: www.example.org\r\n"
7710 "Proxy-Connection: keep-alive\r\n"
7711 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7712 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167713 };
7714
7715 // Lastly we get the desired content.
7716 MockRead data_reads3[] = {
7717 MockRead("HTTP/1.0 200 OK\r\n"),
7718 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7719 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067720 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167721 };
7722
Ryan Sleevib8d7ea02018-05-07 20:01:017723 StaticSocketDataProvider data1(data_reads1, data_writes1);
7724 StaticSocketDataProvider data2(data_reads2, data_writes2);
7725 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077726 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7727 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7728 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167729
[email protected]49639fa2011-12-20 23:22:417730 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167731
tfarina42834112016-09-22 13:38:207732 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017733 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167734
7735 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017736 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167737
bnc691fda62016-08-12 00:43:167738 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527739 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587740 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167741
[email protected]49639fa2011-12-20 23:22:417742 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167743
bnc691fda62016-08-12 00:43:167744 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017745 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167746
7747 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017748 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167749
bnc691fda62016-08-12 00:43:167750 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527751 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587752 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167753
[email protected]49639fa2011-12-20 23:22:417754 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167755
bnc691fda62016-08-12 00:43:167756 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7757 callback3.callback());
robpercival214763f2016-07-01 23:27:017758 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167759
7760 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017761 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167762
bnc691fda62016-08-12 00:43:167763 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587764 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167765 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167766}
[email protected]4ddaf2502008-10-23 18:26:197767
[email protected]ea9dc9a2009-09-05 00:43:327768// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7769// can't hook into its internals to cause it to generate predictable NTLM
7770// authorization headers.
7771#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377772// The NTLM authentication unit tests are based on known test data from the
7773// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7774// flow rather than the implementation of the NTLM protocol. See net/ntlm
7775// for the implementation and testing of the protocol.
7776//
7777// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297778
7779// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557780TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427781 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247782 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557783 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107784 request.traffic_annotation =
7785 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547786
7787 // Ensure load is not disrupted by flags which suppress behaviour specific
7788 // to other auth schemes.
7789 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247790
Zentaro Kavanagh6ccee512017-09-28 18:34:097791 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7792 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097793 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277794
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377795 // Generate the NTLM messages based on known test data.
7796 std::string negotiate_msg;
7797 std::string challenge_msg;
7798 std::string authenticate_msg;
7799 base::Base64Encode(
7800 base::StringPiece(
7801 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247802 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377803 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557804 base::Base64Encode(
7805 base::StringPiece(
7806 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247807 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557808 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377809 base::Base64Encode(
7810 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097811 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557812 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247813 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557814 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377815 &authenticate_msg);
7816
[email protected]3f918782009-02-28 01:29:247817 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557818 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7819 "Host: server\r\n"
7820 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247821 };
7822
7823 MockRead data_reads1[] = {
7824 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047825 // Negotiate and NTLM are often requested together. However, we only want
7826 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7827 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247828 MockRead("WWW-Authenticate: NTLM\r\n"),
7829 MockRead("Connection: close\r\n"),
7830 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367831 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247832 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247833 };
7834
7835 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167836 // After restarting with a null identity, this is the
7837 // request we should be issuing -- the final header line contains a Type
7838 // 1 message.
7839 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557840 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167841 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377842 "Authorization: NTLM "),
7843 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247844
bnc691fda62016-08-12 00:43:167845 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377846 // (using correct credentials). The second request continues on the
7847 // same connection.
bnc691fda62016-08-12 00:43:167848 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557849 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167850 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377851 "Authorization: NTLM "),
7852 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247853 };
7854
7855 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027856 // The origin server responds with a Type 2 message.
7857 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377858 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7859 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027860 MockRead("Content-Type: text/html\r\n\r\n"),
7861 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247862
Bence Béky1e4ef192017-09-18 19:58:027863 // Lastly we get the desired content.
7864 MockRead("HTTP/1.1 200 OK\r\n"),
7865 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7866 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247867 };
7868
Ryan Sleevib8d7ea02018-05-07 20:01:017869 StaticSocketDataProvider data1(data_reads1, data_writes1);
7870 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077871 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7872 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247873
Bence Béky83eb3512017-09-05 12:56:097874 SSLSocketDataProvider ssl1(ASYNC, OK);
7875 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7876 SSLSocketDataProvider ssl2(ASYNC, OK);
7877 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7878
[email protected]49639fa2011-12-20 23:22:417879 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247880
bnc691fda62016-08-12 00:43:167881 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507882
tfarina42834112016-09-22 13:38:207883 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017884 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247885
7886 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017887 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247888
bnc691fda62016-08-12 00:43:167889 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227890
bnc691fda62016-08-12 00:43:167891 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527892 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587893 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247894
[email protected]49639fa2011-12-20 23:22:417895 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257896
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377897 rv = trans.RestartWithAuth(
7898 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7899 callback2.callback());
robpercival214763f2016-07-01 23:27:017900 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257901
7902 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017903 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257904
bnc691fda62016-08-12 00:43:167905 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257906
bnc691fda62016-08-12 00:43:167907 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527908 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587909 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257910
[email protected]49639fa2011-12-20 23:22:417911 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247912
bnc691fda62016-08-12 00:43:167913 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017914 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247915
[email protected]0757e7702009-03-27 04:00:227916 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017917 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247918
bnc691fda62016-08-12 00:43:167919 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527920 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587921 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027922 EXPECT_EQ(14, response->headers->GetContentLength());
7923
7924 std::string response_data;
7925 rv = ReadTransaction(&trans, &response_data);
7926 EXPECT_THAT(rv, IsOk());
7927 EXPECT_EQ("Please Login\r\n", response_data);
7928
7929 EXPECT_TRUE(data1.AllReadDataConsumed());
7930 EXPECT_TRUE(data1.AllWriteDataConsumed());
7931 EXPECT_TRUE(data2.AllReadDataConsumed());
7932 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247933}
7934
[email protected]385a4672009-03-11 22:21:297935// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557936TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427937 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297938 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557939 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107940 request.traffic_annotation =
7941 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297942
Zentaro Kavanagh6ccee512017-09-28 18:34:097943 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7944 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097945 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277946
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377947 // Generate the NTLM messages based on known test data.
7948 std::string negotiate_msg;
7949 std::string challenge_msg;
7950 std::string authenticate_msg;
7951 base::Base64Encode(
7952 base::StringPiece(
7953 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247954 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377955 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557956 base::Base64Encode(
7957 base::StringPiece(
7958 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247959 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557960 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377961 base::Base64Encode(
7962 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097963 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557964 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247965 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557966 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377967 &authenticate_msg);
7968
7969 // The authenticate message when |kWrongPassword| is sent.
7970 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557971 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7972 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7973 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7974 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7975 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7976 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377977
Zentaro Kavanagh1890a3d2018-01-29 19:52:557978 // Sanity check that it's the same length as the correct authenticate message
7979 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377980 ASSERT_EQ(authenticate_msg.length(),
7981 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557982 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377983
[email protected]385a4672009-03-11 22:21:297984 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557985 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7986 "Host: server\r\n"
7987 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297988 };
7989
7990 MockRead data_reads1[] = {
7991 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047992 // Negotiate and NTLM are often requested together. However, we only want
7993 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7994 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:297995 MockRead("WWW-Authenticate: NTLM\r\n"),
7996 MockRead("Connection: close\r\n"),
7997 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367998 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297999 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298000 };
8001
8002 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:168003 // After restarting with a null identity, this is the
8004 // request we should be issuing -- the final header line contains a Type
8005 // 1 message.
8006 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558007 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168008 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378009 "Authorization: NTLM "),
8010 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298011
bnc691fda62016-08-12 00:43:168012 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378013 // (using incorrect credentials). The second request continues on the
8014 // same connection.
bnc691fda62016-08-12 00:43:168015 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558016 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168017 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378018 "Authorization: NTLM "),
8019 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298020 };
8021
8022 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378023 // The origin server responds with a Type 2 message.
8024 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8025 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8026 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
8027 MockRead("Content-Type: text/html\r\n\r\n"),
8028 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298029
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378030 // Wrong password.
8031 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8032 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
8033 MockRead("Content-Length: 42\r\n"),
8034 MockRead("Content-Type: text/html\r\n\r\n"),
8035 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298036 };
8037
8038 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:168039 // After restarting with a null identity, this is the
8040 // request we should be issuing -- the final header line contains a Type
8041 // 1 message.
8042 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558043 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168044 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378045 "Authorization: NTLM "),
8046 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298047
bnc691fda62016-08-12 00:43:168048 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8049 // (the credentials for the origin server). The second request continues
8050 // on the same connection.
8051 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558052 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168053 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378054 "Authorization: NTLM "),
8055 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298056 };
8057
8058 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:028059 // The origin server responds with a Type 2 message.
8060 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378061 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8062 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028063 MockRead("Content-Type: text/html\r\n\r\n"),
8064 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298065
Bence Béky1e4ef192017-09-18 19:58:028066 // Lastly we get the desired content.
8067 MockRead("HTTP/1.1 200 OK\r\n"),
8068 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
8069 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:298070 };
8071
Ryan Sleevib8d7ea02018-05-07 20:01:018072 StaticSocketDataProvider data1(data_reads1, data_writes1);
8073 StaticSocketDataProvider data2(data_reads2, data_writes2);
8074 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078075 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8076 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8077 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:298078
Bence Béky83eb3512017-09-05 12:56:098079 SSLSocketDataProvider ssl1(ASYNC, OK);
8080 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8081 SSLSocketDataProvider ssl2(ASYNC, OK);
8082 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8083 SSLSocketDataProvider ssl3(ASYNC, OK);
8084 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8085
[email protected]49639fa2011-12-20 23:22:418086 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:298087
bnc691fda62016-08-12 00:43:168088 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508089
tfarina42834112016-09-22 13:38:208090 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018091 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298092
8093 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018094 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298095
bnc691fda62016-08-12 00:43:168096 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:298097
bnc691fda62016-08-12 00:43:168098 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528099 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588100 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:298101
[email protected]49639fa2011-12-20 23:22:418102 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:298103
[email protected]0757e7702009-03-27 04:00:228104 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378105 rv = trans.RestartWithAuth(
8106 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
8107 callback2.callback());
robpercival214763f2016-07-01 23:27:018108 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298109
[email protected]10af5fe72011-01-31 16:17:258110 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018111 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298112
bnc691fda62016-08-12 00:43:168113 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:418114 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168115 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018116 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258117 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018118 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168119 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228120
bnc691fda62016-08-12 00:43:168121 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528122 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588123 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:228124
[email protected]49639fa2011-12-20 23:22:418125 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:228126
8127 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378128 rv = trans.RestartWithAuth(
8129 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8130 callback4.callback());
robpercival214763f2016-07-01 23:27:018131 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258132
8133 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:018134 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258135
bnc691fda62016-08-12 00:43:168136 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258137
[email protected]49639fa2011-12-20 23:22:418138 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:258139
8140 // One more roundtrip
bnc691fda62016-08-12 00:43:168141 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:018142 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:228143
8144 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:018145 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:228146
bnc691fda62016-08-12 00:43:168147 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:588148 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028149 EXPECT_EQ(14, response->headers->GetContentLength());
8150
8151 std::string response_data;
8152 rv = ReadTransaction(&trans, &response_data);
8153 EXPECT_THAT(rv, IsOk());
8154 EXPECT_EQ("Please Login\r\n", response_data);
8155
8156 EXPECT_TRUE(data1.AllReadDataConsumed());
8157 EXPECT_TRUE(data1.AllWriteDataConsumed());
8158 EXPECT_TRUE(data2.AllReadDataConsumed());
8159 EXPECT_TRUE(data2.AllWriteDataConsumed());
8160 EXPECT_TRUE(data3.AllReadDataConsumed());
8161 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:298162}
Bence Béky83eb3512017-09-05 12:56:098163
Bence Béky3238f2e12017-09-22 22:44:498164// Server requests NTLM authentication, which is not supported over HTTP/2.
8165// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:098166TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:098167 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
8168 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:098169
Zentaro Kavanagh1890a3d2018-01-29 19:52:558170 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:098171
8172 HttpRequestInfo request;
8173 request.method = "GET";
8174 request.url = GURL(kUrl);
Ramin Halavatib5e433e62018-02-07 07:41:108175 request.traffic_annotation =
8176 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:098177
8178 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:138179 spdy::SpdyHeaderBlock request_headers0(
8180 spdy_util_.ConstructGetHeaderBlock(kUrl));
8181 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:098182 1, std::move(request_headers0), LOWEST, true));
8183
Ryan Hamilton0239aac2018-05-19 00:03:138184 spdy::SpdyHeaderBlock response_headers0;
8185 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:098186 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:138187 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:098188 1, std::move(response_headers0), true));
8189
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378190 // Stream 1 is closed.
8191 spdy_util_.UpdateWithStreamDestruction(1);
8192
8193 // Generate the NTLM messages based on known test data.
8194 std::string negotiate_msg;
8195 std::string challenge_msg;
8196 std::string authenticate_msg;
8197 base::Base64Encode(
8198 base::StringPiece(
8199 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248200 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378201 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558202 base::Base64Encode(
8203 base::StringPiece(
8204 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248205 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558206 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378207 base::Base64Encode(
8208 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098209 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558210 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248211 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558212 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378213 &authenticate_msg);
8214
Bence Béky3238f2e12017-09-22 22:44:498215 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:168216 MockRead reads0[] = {CreateMockRead(resp, 1),
8217 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:098218
8219 // Retry yet again using HTTP/1.1.
8220 MockWrite writes1[] = {
8221 // After restarting with a null identity, this is the
8222 // request we should be issuing -- the final header line contains a Type
8223 // 1 message.
8224 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558225 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098226 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378227 "Authorization: NTLM "),
8228 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098229
8230 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8231 // (the credentials for the origin server). The second request continues
8232 // on the same connection.
8233 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558234 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098235 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378236 "Authorization: NTLM "),
8237 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098238 };
8239
8240 MockRead reads1[] = {
8241 // The origin server responds with a Type 2 message.
8242 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378243 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8244 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:098245 MockRead("Content-Type: text/html\r\n\r\n"),
8246 MockRead("You are not authorized to view this page\r\n"),
8247
8248 // Lastly we get the desired content.
8249 MockRead("HTTP/1.1 200 OK\r\n"),
8250 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028251 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:098252 };
Ryan Sleevib8d7ea02018-05-07 20:01:018253 SequencedSocketData data0(reads0, writes0);
8254 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:098255 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8256 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8257
8258 SSLSocketDataProvider ssl0(ASYNC, OK);
8259 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:168260 ssl0.next_protos_expected_in_ssl_config =
8261 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098262 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:168263 // When creating the second connection, only HTTP/1.1 should be allowed.
8264 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8266 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8267
8268 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8269 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8270
8271 TestCompletionCallback callback1;
8272 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
8273 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8274
8275 rv = callback1.WaitForResult();
8276 EXPECT_THAT(rv, IsOk());
8277
8278 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8279
8280 const HttpResponseInfo* response = trans.GetResponseInfo();
8281 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588282 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:098283
8284 TestCompletionCallback callback2;
8285
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378286 rv = trans.RestartWithAuth(
8287 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8288 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:098289 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8290
8291 rv = callback2.WaitForResult();
8292 EXPECT_THAT(rv, IsOk());
8293
8294 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8295
8296 response = trans.GetResponseInfo();
8297 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588298 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:098299
8300 TestCompletionCallback callback3;
8301
8302 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
8303 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8304
8305 rv = callback3.WaitForResult();
8306 EXPECT_THAT(rv, IsOk());
8307
8308 response = trans.GetResponseInfo();
8309 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588310 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028311 EXPECT_EQ(14, response->headers->GetContentLength());
8312
8313 std::string response_data;
8314 rv = ReadTransaction(&trans, &response_data);
8315 EXPECT_THAT(rv, IsOk());
8316 EXPECT_EQ("Please Login\r\n", response_data);
8317
8318 EXPECT_TRUE(data0.AllReadDataConsumed());
8319 EXPECT_TRUE(data0.AllWriteDataConsumed());
8320 EXPECT_TRUE(data1.AllReadDataConsumed());
8321 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:098322}
David Benjamin5cb91132018-04-06 05:54:498323
Matt Menkef2ee07c2019-08-29 02:10:368324#if BUILDFLAG(ENABLE_WEBSOCKETS)
8325
8326// Variant of above test using WebSockets.
8327TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
8328 const GURL kInitialUrl("https://server/");
8329 const GURL kWebSocketUrl("wss://server/");
8330 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
8331 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8332
8333 // Initial request establishes an H2 connection, which will then be reused for
8334 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
8335 // it won't create a new one.
8336 spdy::SpdyHeaderBlock initial_request_headers(
8337 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
8338 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
8339 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
8340 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
8341
8342 // Settings frame, indicating WebSockets is supported.
8343 spdy::SettingsMap settings;
8344 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
8345 spdy::SpdySerializedFrame settings_frame(
8346 spdy_util_.ConstructSpdySettings(settings));
8347
8348 // Response headers for first request. Body is never received, but that
8349 // shouldn't matter for the purposes of this test.
8350 spdy::SpdySerializedFrame initial_response(
8351 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8352
8353 // First WebSocket request, which has no credentials.
8354 spdy::SpdyHeaderBlock websocket_request_headers;
8355 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
8356 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
8357 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
8358 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
8359 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
8360 websocket_request_headers["origin"] = "http://server";
8361 websocket_request_headers["sec-websocket-version"] = "13";
8362 websocket_request_headers["sec-websocket-extensions"] =
8363 "permessage-deflate; client_max_window_bits";
8364 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
8365 3, std::move(websocket_request_headers), MEDIUM, false));
8366
8367 // Auth challenge to WebSocket request.
8368 spdy::SpdyHeaderBlock auth_challenge_headers;
8369 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
8370 auth_challenge_headers["www-authenticate"] = "NTLM";
8371 spdy::SpdySerializedFrame websocket_auth_challenge(
8372 spdy_util_.ConstructSpdyResponseHeaders(
8373 3, std::move(auth_challenge_headers), true));
8374
8375 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
8376 CreateMockWrite(settings_ack, 2),
8377 CreateMockWrite(websocket_request, 4),
8378 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
8379 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
8380 CreateMockRead(initial_response, 3),
8381 CreateMockRead(websocket_auth_challenge, 5),
8382 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
8383
8384 // Generate the NTLM messages based on known test data.
8385 std::string negotiate_msg;
8386 std::string challenge_msg;
8387 std::string authenticate_msg;
8388 base::Base64Encode(
8389 base::StringPiece(
8390 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
8391 base::size(ntlm::test::kExpectedNegotiateMsg)),
8392 &negotiate_msg);
8393 base::Base64Encode(
8394 base::StringPiece(
8395 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
8396 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
8397 &challenge_msg);
8398 base::Base64Encode(
8399 base::StringPiece(
8400 reinterpret_cast<const char*>(
8401 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
8402 base::size(
8403 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8404 &authenticate_msg);
8405
8406 // Retry yet again using HTTP/1.1.
8407 MockWrite writes1[] = {
8408 // After restarting with a null identity, this is the
8409 // request we should be issuing -- the final header line contains a Type
8410 // 1 message.
8411 MockWrite("GET / HTTP/1.1\r\n"
8412 "Host: server\r\n"
8413 "Connection: Upgrade\r\n"
8414 "Authorization: NTLM "),
8415 MockWrite(negotiate_msg.c_str()),
8416 MockWrite("\r\n"),
8417 MockWrite("Origin: http://server\r\n"
8418 "Sec-WebSocket-Version: 13\r\n"
8419 "Upgrade: websocket\r\n"
8420 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8421 "Sec-WebSocket-Extensions: permessage-deflate; "
8422 "client_max_window_bits\r\n\r\n"),
8423
8424 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8425 // (the credentials for the origin server). The second request continues
8426 // on the same connection.
8427 MockWrite("GET / HTTP/1.1\r\n"
8428 "Host: server\r\n"
8429 "Connection: Upgrade\r\n"
8430 "Authorization: NTLM "),
8431 MockWrite(authenticate_msg.c_str()),
8432 MockWrite("\r\n"),
8433 MockWrite("Origin: http://server\r\n"
8434 "Sec-WebSocket-Version: 13\r\n"
8435 "Upgrade: websocket\r\n"
8436 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8437 "Sec-WebSocket-Extensions: permessage-deflate; "
8438 "client_max_window_bits\r\n\r\n"),
8439 };
8440
8441 MockRead reads1[] = {
8442 // The origin server responds with a Type 2 message.
8443 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8444 MockRead("WWW-Authenticate: NTLM "),
8445 MockRead(challenge_msg.c_str()),
8446 MockRead("\r\n"),
8447 MockRead("Content-Length: 42\r\n"),
8448 MockRead("Content-Type: text/html\r\n\r\n"),
8449 MockRead("You are not authorized to view this page\r\n"),
8450
8451 // Lastly we get the desired content.
8452 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
8453 "Upgrade: websocket\r\n"
8454 "Connection: Upgrade\r\n"
8455 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
8456 };
8457 SequencedSocketData data0(reads0, writes0);
8458 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8459 SSLSocketDataProvider ssl0(ASYNC, OK);
8460 ssl0.next_proto = kProtoHTTP2;
8461 ssl0.next_protos_expected_in_ssl_config =
8462 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
8463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8464
8465 StaticSocketDataProvider data1(reads1, writes1);
8466 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8467 SSLSocketDataProvider ssl1(ASYNC, OK);
8468 // When creating the second connection, only HTTP/1.1 should be allowed.
8469 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
8470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8471
8472 session_deps_.enable_websocket_over_http2 = true;
8473 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8474
8475 HttpRequestInfo initial_request_info;
8476 initial_request_info.method = "GET";
8477 initial_request_info.url = kInitialUrl;
8478 initial_request_info.traffic_annotation =
8479 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8480 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
8481 TestCompletionCallback initial_callback;
8482 int rv = initial_trans.Start(&initial_request_info,
8483 initial_callback.callback(), NetLogWithSource());
8484 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
8485
8486 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
8487 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8488
8489 HttpRequestInfo websocket_request_info;
8490 websocket_request_info.method = "GET";
8491 websocket_request_info.url = kWebSocketUrl;
8492 websocket_request_info.traffic_annotation =
8493 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8494 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
8495 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
8496 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
8497 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
8498 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
8499 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
8500 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
8501
8502 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8503
8504 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
8505 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
8506 &websocket_stream_create_helper);
8507
8508 TestCompletionCallback websocket_callback;
8509 rv = websocket_trans.Start(&websocket_request_info,
8510 websocket_callback.callback(), NetLogWithSource());
8511 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8512
8513 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
8514
8515 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
8516 ASSERT_TRUE(response);
8517 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
8518
8519 rv = websocket_trans.RestartWithAuth(
8520 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8521 websocket_callback.callback());
8522 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8523
8524 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
8525
8526 response = websocket_trans.GetResponseInfo();
8527 ASSERT_TRUE(response);
8528 EXPECT_FALSE(response->auth_challenge.has_value());
8529
8530 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
8531 websocket_callback.callback());
8532 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8533
8534 // The server should have been marked as requiring HTTP/1.1. The important
8535 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
8536 // WSS.
8537 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
8538 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8539}
8540
8541#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
8542
David Benjamin5cb91132018-04-06 05:54:498543// Test that, if we have an NTLM proxy and the origin resets the connection, we
8544// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:378545// regression test for https://crbug.com/823387. The version interference probe
8546// has since been removed, but retain the regression test so we can update it if
8547// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:498548TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
8549 // The NTLM test data expects the proxy to be named 'server'. The origin is
8550 // https://origin/.
8551 session_deps_.proxy_resolution_service =
8552 ProxyResolutionService::CreateFixedFromPacResult(
8553 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
8554
David Benjamin151ec6b2019-08-02 19:38:528555 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:498556 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:078557 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:498558
8559 HttpRequestInfo request;
8560 request.method = "GET";
8561 request.url = GURL("https://origin/");
8562 request.traffic_annotation =
8563 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8564
8565 // Ensure load is not disrupted by flags which suppress behaviour specific
8566 // to other auth schemes.
8567 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
8568
8569 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
8570 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8571 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8572
8573 // Generate the NTLM messages based on known test data.
8574 std::string negotiate_msg;
8575 std::string challenge_msg;
8576 std::string authenticate_msg;
8577 base::Base64Encode(
8578 base::StringPiece(
8579 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248580 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:498581 &negotiate_msg);
8582 base::Base64Encode(
8583 base::StringPiece(
8584 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248585 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:498586 &challenge_msg);
8587 base::Base64Encode(
8588 base::StringPiece(
8589 reinterpret_cast<const char*>(
8590 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248591 base::size(
David Benjamin5cb91132018-04-06 05:54:498592 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8593 &authenticate_msg);
8594
8595 MockWrite data_writes[] = {
8596 // The initial CONNECT request.
8597 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8598 "Host: origin:443\r\n"
8599 "Proxy-Connection: keep-alive\r\n\r\n"),
8600
8601 // After restarting with an identity.
8602 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8603 "Host: origin:443\r\n"
8604 "Proxy-Connection: keep-alive\r\n"
8605 "Proxy-Authorization: NTLM "),
8606 MockWrite(negotiate_msg.c_str()),
8607 // End headers.
8608 MockWrite("\r\n\r\n"),
8609
8610 // The second restart.
8611 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8612 "Host: origin:443\r\n"
8613 "Proxy-Connection: keep-alive\r\n"
8614 "Proxy-Authorization: NTLM "),
8615 MockWrite(authenticate_msg.c_str()),
8616 // End headers.
8617 MockWrite("\r\n\r\n"),
8618 };
8619
8620 MockRead data_reads[] = {
8621 // The initial NTLM response.
8622 MockRead("HTTP/1.1 407 Access Denied\r\n"
8623 "Content-Length: 0\r\n"
8624 "Proxy-Authenticate: NTLM\r\n\r\n"),
8625
8626 // The NTLM challenge message.
8627 MockRead("HTTP/1.1 407 Access Denied\r\n"
8628 "Content-Length: 0\r\n"
8629 "Proxy-Authenticate: NTLM "),
8630 MockRead(challenge_msg.c_str()),
8631 // End headers.
8632 MockRead("\r\n\r\n"),
8633
8634 // Finally the tunnel is established.
8635 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
8636 };
8637
Ryan Sleevib8d7ea02018-05-07 20:01:018638 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:498639 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:498640 session_deps_.socket_factory->AddSocketDataProvider(&data);
8641 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:498642
8643 // Start the transaction. The proxy responds with an NTLM authentication
8644 // request.
8645 TestCompletionCallback callback;
8646 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8647 int rv = callback.GetResult(
8648 trans.Start(&request, callback.callback(), NetLogWithSource()));
8649
8650 EXPECT_THAT(rv, IsOk());
8651 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8652 const HttpResponseInfo* response = trans.GetResponseInfo();
8653 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588654 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:498655
David Benjamind61bd532019-04-23 21:11:378656 // Configure credentials and restart. The proxy responds with the challenge
8657 // message.
David Benjamin5cb91132018-04-06 05:54:498658 rv = callback.GetResult(trans.RestartWithAuth(
8659 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8660 callback.callback()));
8661 EXPECT_THAT(rv, IsOk());
8662 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8663 response = trans.GetResponseInfo();
8664 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588665 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:498666
David Benjamind61bd532019-04-23 21:11:378667 // Restart once more. The tunnel will be established and then the SSL
8668 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:498669 rv = callback.GetResult(
8670 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
8671 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
8672}
8673
[email protected]ea9dc9a2009-09-05 00:43:328674#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:298675
[email protected]4ddaf2502008-10-23 18:26:198676// Test reading a server response which has only headers, and no body.
8677// After some maximum number of bytes is consumed, the transaction should
8678// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:018679TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:428680 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:198681 request.method = "GET";
bncce36dca22015-04-21 22:11:238682 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108683 request.traffic_annotation =
8684 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:198685
danakj1fd259a02016-04-16 03:17:098686 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168687 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278688
[email protected]b75b7b2f2009-10-06 00:54:538689 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:438690 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:538691 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:198692
8693 MockRead data_reads[] = {
8694 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:068695 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:198696 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:068697 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:198698 };
Ryan Sleevib8d7ea02018-05-07 20:01:018699 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078700 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:198701
[email protected]49639fa2011-12-20 23:22:418702 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:198703
tfarina42834112016-09-22 13:38:208704 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018705 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:198706
8707 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018708 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:198709}
[email protected]f4e426b2008-11-05 00:24:498710
8711// Make sure that we don't try to reuse a TCPClientSocket when failing to
8712// establish tunnel.
8713// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:018714TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:278715 HttpRequestInfo request;
8716 request.method = "GET";
bncce36dca22015-04-21 22:11:238717 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108718 request.traffic_annotation =
8719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278720
[email protected]f4e426b2008-11-05 00:24:498721 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:498722 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
8723 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:018724
danakj1fd259a02016-04-16 03:17:098725 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:498726
bnc87dcefc2017-05-25 12:47:588727 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198728 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:498729
[email protected]f4e426b2008-11-05 00:24:498730 // Since we have proxy, should try to establish tunnel.
8731 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:178732 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8733 "Host: www.example.org:443\r\n"
8734 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:498735 };
8736
[email protected]77848d12008-11-14 00:00:228737 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:498738 // connection. Usually a proxy would return 501 (not implemented),
8739 // or 200 (tunnel established).
8740 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:238741 MockRead("HTTP/1.1 404 Not Found\r\n"),
8742 MockRead("Content-Length: 10\r\n\r\n"),
8743 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:498744 };
8745
Ryan Sleevib8d7ea02018-05-07 20:01:018746 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078747 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:498748
[email protected]49639fa2011-12-20 23:22:418749 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:498750
tfarina42834112016-09-22 13:38:208751 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018752 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:498753
8754 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018755 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:498756
[email protected]b4404c02009-04-10 16:38:528757 // Empty the current queue. This is necessary because idle sockets are
8758 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558759 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528760
[email protected]f4e426b2008-11-05 00:24:498761 // We now check to make sure the TCPClientSocket was not added back to
8762 // the pool.
[email protected]90499482013-06-01 00:39:508763 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498764 trans.reset();
fdoray92e35a72016-06-10 15:54:558765 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:498766 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:508767 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498768}
[email protected]372d34a2008-11-05 21:30:518769
[email protected]1b157c02009-04-21 01:55:408770// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:018771TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:428772 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:408773 request.method = "GET";
bncce36dca22015-04-21 22:11:238774 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108775 request.traffic_annotation =
8776 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:408777
danakj1fd259a02016-04-16 03:17:098778 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278779
bnc691fda62016-08-12 00:43:168780 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278781
[email protected]1b157c02009-04-21 01:55:408782 MockRead data_reads[] = {
8783 // A part of the response body is received with the response headers.
8784 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8785 // The rest of the response body is received in two parts.
8786 MockRead("lo"),
8787 MockRead(" world"),
8788 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068789 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:408790 };
8791
Ryan Sleevib8d7ea02018-05-07 20:01:018792 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078793 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:408794
[email protected]49639fa2011-12-20 23:22:418795 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:408796
tfarina42834112016-09-22 13:38:208797 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018798 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:408799
8800 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018801 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408802
bnc691fda62016-08-12 00:43:168803 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528804 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:408805
wezca1070932016-05-26 20:30:528806 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:408807 std::string status_line = response->headers->GetStatusLine();
8808 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8809
[email protected]90499482013-06-01 00:39:508810 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408811
8812 std::string response_data;
bnc691fda62016-08-12 00:43:168813 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018814 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408815 EXPECT_EQ("hello world", response_data);
8816
8817 // Empty the current queue. This is necessary because idle sockets are
8818 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558819 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:408820
8821 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508822 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408823}
8824
[email protected]76a505b2010-08-25 06:23:008825// Make sure that we recycle a SSL socket after reading all of the response
8826// body.
bncd16676a2016-07-20 16:23:018827TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008828 HttpRequestInfo request;
8829 request.method = "GET";
bncce36dca22015-04-21 22:11:238830 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108831 request.traffic_annotation =
8832 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008833
8834 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238835 MockWrite(
8836 "GET / HTTP/1.1\r\n"
8837 "Host: www.example.org\r\n"
8838 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008839 };
8840
8841 MockRead data_reads[] = {
8842 MockRead("HTTP/1.1 200 OK\r\n"),
8843 MockRead("Content-Length: 11\r\n\r\n"),
8844 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068845 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008846 };
8847
[email protected]8ddf8322012-02-23 18:08:068848 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078849 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:008850
Ryan Sleevib8d7ea02018-05-07 20:01:018851 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078852 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008853
[email protected]49639fa2011-12-20 23:22:418854 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008855
danakj1fd259a02016-04-16 03:17:098856 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168857 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008858
tfarina42834112016-09-22 13:38:208859 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008860
robpercival214763f2016-07-01 23:27:018861 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8862 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008863
bnc691fda62016-08-12 00:43:168864 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528865 ASSERT_TRUE(response);
8866 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008867 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8868
[email protected]90499482013-06-01 00:39:508869 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008870
8871 std::string response_data;
bnc691fda62016-08-12 00:43:168872 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018873 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008874 EXPECT_EQ("hello world", response_data);
8875
8876 // Empty the current queue. This is necessary because idle sockets are
8877 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558878 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008879
8880 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238881 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008882}
8883
8884// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8885// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018886TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008887 HttpRequestInfo request;
8888 request.method = "GET";
bncce36dca22015-04-21 22:11:238889 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108890 request.traffic_annotation =
8891 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008892
8893 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238894 MockWrite(
8895 "GET / HTTP/1.1\r\n"
8896 "Host: www.example.org\r\n"
8897 "Connection: keep-alive\r\n\r\n"),
8898 MockWrite(
8899 "GET / HTTP/1.1\r\n"
8900 "Host: www.example.org\r\n"
8901 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008902 };
8903
8904 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428905 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8906 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008907
[email protected]8ddf8322012-02-23 18:08:068908 SSLSocketDataProvider ssl(ASYNC, OK);
8909 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078910 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8911 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008912
Ryan Sleevib8d7ea02018-05-07 20:01:018913 StaticSocketDataProvider data(data_reads, data_writes);
8914 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078915 session_deps_.socket_factory->AddSocketDataProvider(&data);
8916 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008917
[email protected]49639fa2011-12-20 23:22:418918 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008919
danakj1fd259a02016-04-16 03:17:098920 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588921 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198922 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008923
tfarina42834112016-09-22 13:38:208924 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008925
robpercival214763f2016-07-01 23:27:018926 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8927 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008928
8929 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528930 ASSERT_TRUE(response);
8931 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008932 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8933
[email protected]90499482013-06-01 00:39:508934 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008935
8936 std::string response_data;
8937 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018938 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008939 EXPECT_EQ("hello world", response_data);
8940
8941 // Empty the current queue. This is necessary because idle sockets are
8942 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558943 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008944
8945 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238946 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008947
8948 // Now start the second transaction, which should reuse the previous socket.
8949
bnc87dcefc2017-05-25 12:47:588950 trans =
Jeremy Roman0579ed62017-08-29 15:56:198951 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008952
tfarina42834112016-09-22 13:38:208953 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008954
robpercival214763f2016-07-01 23:27:018955 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8956 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008957
8958 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528959 ASSERT_TRUE(response);
8960 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008961 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8962
[email protected]90499482013-06-01 00:39:508963 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008964
8965 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018966 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008967 EXPECT_EQ("hello world", response_data);
8968
8969 // Empty the current queue. This is necessary because idle sockets are
8970 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558971 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008972
8973 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238974 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008975}
8976
maksim.sisov0adf8592016-07-15 06:25:568977// Grab a socket, use it, and put it back into the pool. Then, make
8978// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018979TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568980 HttpRequestInfo request;
8981 request.method = "GET";
8982 request.url = GURL("http://www.example.org/");
8983 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108984 request.traffic_annotation =
8985 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568986
8987 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8988
bnc691fda62016-08-12 00:43:168989 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568990
8991 MockRead data_reads[] = {
8992 // A part of the response body is received with the response headers.
8993 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8994 // The rest of the response body is received in two parts.
8995 MockRead("lo"), MockRead(" world"),
8996 MockRead("junk"), // Should not be read!!
8997 MockRead(SYNCHRONOUS, OK),
8998 };
8999
Ryan Sleevib8d7ea02018-05-07 20:01:019000 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:569001 session_deps_.socket_factory->AddSocketDataProvider(&data);
9002
9003 TestCompletionCallback callback;
9004
tfarina42834112016-09-22 13:38:209005 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569006 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9007
9008 EXPECT_THAT(callback.GetResult(rv), IsOk());
9009
bnc691fda62016-08-12 00:43:169010 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569011 ASSERT_TRUE(response);
9012 EXPECT_TRUE(response->headers);
9013 std::string status_line = response->headers->GetStatusLine();
9014 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9015
9016 // Make memory critical notification and ensure the transaction still has been
9017 // operating right.
9018 base::MemoryPressureListener::NotifyMemoryPressure(
9019 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9020 base::RunLoop().RunUntilIdle();
9021
9022 // Socket should not be flushed as long as it is not idle.
9023 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9024
9025 std::string response_data;
bnc691fda62016-08-12 00:43:169026 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569027 EXPECT_THAT(rv, IsOk());
9028 EXPECT_EQ("hello world", response_data);
9029
9030 // Empty the current queue. This is necessary because idle sockets are
9031 // added to the connection pool asynchronously with a PostTask.
9032 base::RunLoop().RunUntilIdle();
9033
9034 // We now check to make sure the socket was added back to the pool.
9035 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9036
9037 // Idle sockets should be flushed now.
9038 base::MemoryPressureListener::NotifyMemoryPressure(
9039 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9040 base::RunLoop().RunUntilIdle();
9041
9042 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9043}
9044
yucliu48f235d2018-01-11 00:59:559045// Disable idle socket closing on memory pressure.
9046// Grab a socket, use it, and put it back into the pool. Then, make
9047// low memory notification and ensure the socket pool is NOT flushed.
9048TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
9049 HttpRequestInfo request;
9050 request.method = "GET";
9051 request.url = GURL("http://www.example.org/");
9052 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109053 request.traffic_annotation =
9054 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:559055
9056 // Disable idle socket closing on memory pressure.
9057 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
9058 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9059
9060 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9061
9062 MockRead data_reads[] = {
9063 // A part of the response body is received with the response headers.
9064 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9065 // The rest of the response body is received in two parts.
9066 MockRead("lo"), MockRead(" world"),
9067 MockRead("junk"), // Should not be read!!
9068 MockRead(SYNCHRONOUS, OK),
9069 };
9070
Ryan Sleevib8d7ea02018-05-07 20:01:019071 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:559072 session_deps_.socket_factory->AddSocketDataProvider(&data);
9073
9074 TestCompletionCallback callback;
9075
9076 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9077 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9078
9079 EXPECT_THAT(callback.GetResult(rv), IsOk());
9080
9081 const HttpResponseInfo* response = trans.GetResponseInfo();
9082 ASSERT_TRUE(response);
9083 EXPECT_TRUE(response->headers);
9084 std::string status_line = response->headers->GetStatusLine();
9085 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9086
9087 // Make memory critical notification and ensure the transaction still has been
9088 // operating right.
9089 base::MemoryPressureListener::NotifyMemoryPressure(
9090 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9091 base::RunLoop().RunUntilIdle();
9092
9093 // Socket should not be flushed as long as it is not idle.
9094 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9095
9096 std::string response_data;
9097 rv = ReadTransaction(&trans, &response_data);
9098 EXPECT_THAT(rv, IsOk());
9099 EXPECT_EQ("hello world", response_data);
9100
9101 // Empty the current queue. This is necessary because idle sockets are
9102 // added to the connection pool asynchronously with a PostTask.
9103 base::RunLoop().RunUntilIdle();
9104
9105 // We now check to make sure the socket was added back to the pool.
9106 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9107
9108 // Idle sockets should NOT be flushed on moderate memory pressure.
9109 base::MemoryPressureListener::NotifyMemoryPressure(
9110 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
9111 base::RunLoop().RunUntilIdle();
9112
9113 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9114
9115 // Idle sockets should NOT be flushed on critical memory pressure.
9116 base::MemoryPressureListener::NotifyMemoryPressure(
9117 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9118 base::RunLoop().RunUntilIdle();
9119
9120 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9121}
9122
maksim.sisov0adf8592016-07-15 06:25:569123// Grab an SSL socket, use it, and put it back into the pool. Then, make
9124// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019125TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569126 HttpRequestInfo request;
9127 request.method = "GET";
9128 request.url = GURL("https://www.example.org/");
9129 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109130 request.traffic_annotation =
9131 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569132
9133 MockWrite data_writes[] = {
9134 MockWrite("GET / HTTP/1.1\r\n"
9135 "Host: www.example.org\r\n"
9136 "Connection: keep-alive\r\n\r\n"),
9137 };
9138
9139 MockRead data_reads[] = {
9140 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9141 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
9142
9143 SSLSocketDataProvider ssl(ASYNC, OK);
9144 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9145
Ryan Sleevib8d7ea02018-05-07 20:01:019146 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:569147 session_deps_.socket_factory->AddSocketDataProvider(&data);
9148
9149 TestCompletionCallback callback;
9150
9151 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169152 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569153
Matt Menke9d5e2c92019-02-05 01:42:239154 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:209155 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569156
9157 EXPECT_THAT(callback.GetResult(rv), IsOk());
9158
bnc691fda62016-08-12 00:43:169159 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569160 ASSERT_TRUE(response);
9161 ASSERT_TRUE(response->headers);
9162 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9163
9164 // Make memory critical notification and ensure the transaction still has been
9165 // operating right.
9166 base::MemoryPressureListener::NotifyMemoryPressure(
9167 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9168 base::RunLoop().RunUntilIdle();
9169
Matt Menke9d5e2c92019-02-05 01:42:239170 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569171
9172 std::string response_data;
bnc691fda62016-08-12 00:43:169173 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569174 EXPECT_THAT(rv, IsOk());
9175 EXPECT_EQ("hello world", response_data);
9176
9177 // Empty the current queue. This is necessary because idle sockets are
9178 // added to the connection pool asynchronously with a PostTask.
9179 base::RunLoop().RunUntilIdle();
9180
9181 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239182 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569183
9184 // Make memory notification once again and ensure idle socket is closed.
9185 base::MemoryPressureListener::NotifyMemoryPressure(
9186 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9187 base::RunLoop().RunUntilIdle();
9188
Matt Menke9d5e2c92019-02-05 01:42:239189 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569190}
9191
[email protected]b4404c02009-04-10 16:38:529192// Make sure that we recycle a socket after a zero-length response.
9193// http://crbug.com/9880
bncd16676a2016-07-20 16:23:019194TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:429195 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:529196 request.method = "GET";
bncce36dca22015-04-21 22:11:239197 request.url = GURL(
9198 "http://www.example.org/csi?v=3&s=web&action=&"
9199 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
9200 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
9201 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e62018-02-07 07:41:109202 request.traffic_annotation =
9203 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:529204
danakj1fd259a02016-04-16 03:17:099205 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279206
[email protected]b4404c02009-04-10 16:38:529207 MockRead data_reads[] = {
9208 MockRead("HTTP/1.1 204 No Content\r\n"
9209 "Content-Length: 0\r\n"
9210 "Content-Type: text/html\r\n\r\n"),
9211 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069212 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:529213 };
9214
Ryan Sleevib8d7ea02018-05-07 20:01:019215 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079216 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:529217
mmenkecc2298e2015-12-07 18:20:189218 // Transaction must be created after the MockReads, so it's destroyed before
9219 // them.
bnc691fda62016-08-12 00:43:169220 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:189221
[email protected]49639fa2011-12-20 23:22:419222 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:529223
tfarina42834112016-09-22 13:38:209224 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019225 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:529226
9227 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019228 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529229
bnc691fda62016-08-12 00:43:169230 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529231 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:529232
wezca1070932016-05-26 20:30:529233 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:529234 std::string status_line = response->headers->GetStatusLine();
9235 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
9236
[email protected]90499482013-06-01 00:39:509237 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529238
9239 std::string response_data;
bnc691fda62016-08-12 00:43:169240 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019241 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529242 EXPECT_EQ("", response_data);
9243
9244 // Empty the current queue. This is necessary because idle sockets are
9245 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559246 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529247
9248 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509249 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529250}
9251
bncd16676a2016-07-20 16:23:019252TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:099253 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:229254 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:199255 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:229256 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279257
[email protected]1c773ea12009-04-28 19:58:429258 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:519259 // Transaction 1: a GET request that succeeds. The socket is recycled
9260 // after use.
9261 request[0].method = "GET";
9262 request[0].url = GURL("http://www.google.com/");
9263 request[0].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109264 request[0].traffic_annotation =
9265 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519266 // Transaction 2: a POST request. Reuses the socket kept alive from
9267 // transaction 1. The first attempts fails when writing the POST data.
9268 // This causes the transaction to retry with a new socket. The second
9269 // attempt succeeds.
9270 request[1].method = "POST";
9271 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:279272 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:519273 request[1].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109274 request[1].traffic_annotation =
9275 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519276
danakj1fd259a02016-04-16 03:17:099277 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:519278
9279 // The first socket is used for transaction 1 and the first attempt of
9280 // transaction 2.
9281
9282 // The response of transaction 1.
9283 MockRead data_reads1[] = {
9284 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
9285 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069286 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519287 };
9288 // The mock write results of transaction 1 and the first attempt of
9289 // transaction 2.
9290 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:069291 MockWrite(SYNCHRONOUS, 64), // GET
9292 MockWrite(SYNCHRONOUS, 93), // POST
9293 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:519294 };
Ryan Sleevib8d7ea02018-05-07 20:01:019295 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:519296
9297 // The second socket is used for the second attempt of transaction 2.
9298
9299 // The response of transaction 2.
9300 MockRead data_reads2[] = {
9301 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
9302 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:069303 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519304 };
9305 // The mock write results of the second attempt of transaction 2.
9306 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:069307 MockWrite(SYNCHRONOUS, 93), // POST
9308 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:519309 };
Ryan Sleevib8d7ea02018-05-07 20:01:019310 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:519311
[email protected]bb88e1d32013-05-03 23:11:079312 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9313 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:519314
thestig9d3bb0c2015-01-24 00:49:519315 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:519316 "hello world", "welcome"
9317 };
9318
9319 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:169320 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:519321
[email protected]49639fa2011-12-20 23:22:419322 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:519323
tfarina42834112016-09-22 13:38:209324 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019325 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:519326
9327 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019328 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519329
bnc691fda62016-08-12 00:43:169330 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529331 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:519332
wezca1070932016-05-26 20:30:529333 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:519334 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9335
9336 std::string response_data;
bnc691fda62016-08-12 00:43:169337 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019338 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519339 EXPECT_EQ(kExpectedResponseData[i], response_data);
9340 }
9341}
[email protected]f9ee6b52008-11-08 06:46:239342
9343// Test the request-challenge-retry sequence for basic auth when there is
9344// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:169345// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:019346TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:429347 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239348 request.method = "GET";
bncce36dca22015-04-21 22:11:239349 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:419350 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:109351 request.traffic_annotation =
9352 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:299353
danakj1fd259a02016-04-16 03:17:099354 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169355 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279356
[email protected]a97cca42009-08-14 01:00:299357 // The password contains an escaped character -- for this test to pass it
9358 // will need to be unescaped by HttpNetworkTransaction.
9359 EXPECT_EQ("b%40r", request.url.password());
9360
[email protected]f9ee6b52008-11-08 06:46:239361 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239362 MockWrite(
9363 "GET / HTTP/1.1\r\n"
9364 "Host: www.example.org\r\n"
9365 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239366 };
9367
9368 MockRead data_reads1[] = {
9369 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9370 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9371 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069372 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239373 };
9374
[email protected]2262e3a2012-05-22 16:08:169375 // After the challenge above, the transaction will be restarted using the
9376 // identity from the url (foo, b@r) to answer the challenge.
9377 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239378 MockWrite(
9379 "GET / HTTP/1.1\r\n"
9380 "Host: www.example.org\r\n"
9381 "Connection: keep-alive\r\n"
9382 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169383 };
9384
9385 MockRead data_reads2[] = {
9386 MockRead("HTTP/1.0 200 OK\r\n"),
9387 MockRead("Content-Length: 100\r\n\r\n"),
9388 MockRead(SYNCHRONOUS, OK),
9389 };
9390
Ryan Sleevib8d7ea02018-05-07 20:01:019391 StaticSocketDataProvider data1(data_reads1, data_writes1);
9392 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079393 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9394 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239395
[email protected]49639fa2011-12-20 23:22:419396 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209397 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019398 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239399 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019400 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169401 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169402
9403 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169404 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019405 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169406 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019407 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169408 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229409
bnc691fda62016-08-12 00:43:169410 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529411 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169412
9413 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:589414 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169415
9416 EXPECT_EQ(100, response->headers->GetContentLength());
9417
9418 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559419 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:169420}
9421
9422// Test the request-challenge-retry sequence for basic auth when there is an
9423// incorrect identity in the URL. The identity from the URL should be used only
9424// once.
bncd16676a2016-07-20 16:23:019425TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:169426 HttpRequestInfo request;
9427 request.method = "GET";
9428 // Note: the URL has a username:password in it. The password "baz" is
9429 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:239430 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:169431
9432 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:109433 request.traffic_annotation =
9434 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:169435
danakj1fd259a02016-04-16 03:17:099436 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169437 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:169438
9439 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239440 MockWrite(
9441 "GET / HTTP/1.1\r\n"
9442 "Host: www.example.org\r\n"
9443 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169444 };
9445
9446 MockRead data_reads1[] = {
9447 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9448 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9449 MockRead("Content-Length: 10\r\n\r\n"),
9450 MockRead(SYNCHRONOUS, ERR_FAILED),
9451 };
9452
9453 // After the challenge above, the transaction will be restarted using the
9454 // identity from the url (foo, baz) to answer the challenge.
9455 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239456 MockWrite(
9457 "GET / HTTP/1.1\r\n"
9458 "Host: www.example.org\r\n"
9459 "Connection: keep-alive\r\n"
9460 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169461 };
9462
9463 MockRead data_reads2[] = {
9464 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9465 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9466 MockRead("Content-Length: 10\r\n\r\n"),
9467 MockRead(SYNCHRONOUS, ERR_FAILED),
9468 };
9469
9470 // After the challenge above, the transaction will be restarted using the
9471 // identity supplied by the user (foo, bar) to answer the challenge.
9472 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239473 MockWrite(
9474 "GET / HTTP/1.1\r\n"
9475 "Host: www.example.org\r\n"
9476 "Connection: keep-alive\r\n"
9477 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169478 };
9479
9480 MockRead data_reads3[] = {
9481 MockRead("HTTP/1.0 200 OK\r\n"),
9482 MockRead("Content-Length: 100\r\n\r\n"),
9483 MockRead(SYNCHRONOUS, OK),
9484 };
9485
Ryan Sleevib8d7ea02018-05-07 20:01:019486 StaticSocketDataProvider data1(data_reads1, data_writes1);
9487 StaticSocketDataProvider data2(data_reads2, data_writes2);
9488 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079489 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9490 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9491 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:169492
9493 TestCompletionCallback callback1;
9494
tfarina42834112016-09-22 13:38:209495 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019496 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169497
9498 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019499 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:169500
bnc691fda62016-08-12 00:43:169501 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169502 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169503 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019504 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169505 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019506 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169507 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169508
bnc691fda62016-08-12 00:43:169509 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529510 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589511 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:169512
9513 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169514 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019515 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169516 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019517 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169518 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169519
bnc691fda62016-08-12 00:43:169520 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529521 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169522
9523 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589524 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169525
9526 EXPECT_EQ(100, response->headers->GetContentLength());
9527
[email protected]ea9dc9a2009-09-05 00:43:329528 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559529 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:329530}
9531
[email protected]2217aa22013-10-11 03:03:549532
9533// Test the request-challenge-retry sequence for basic auth when there is a
9534// correct identity in the URL, but its use is being suppressed. The identity
9535// from the URL should never be used.
bncd16676a2016-07-20 16:23:019536TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:549537 HttpRequestInfo request;
9538 request.method = "GET";
bncce36dca22015-04-21 22:11:239539 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:549540 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e62018-02-07 07:41:109541 request.traffic_annotation =
9542 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:549543
danakj1fd259a02016-04-16 03:17:099544 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169545 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:549546
9547 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239548 MockWrite(
9549 "GET / HTTP/1.1\r\n"
9550 "Host: www.example.org\r\n"
9551 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549552 };
9553
9554 MockRead data_reads1[] = {
9555 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9556 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9557 MockRead("Content-Length: 10\r\n\r\n"),
9558 MockRead(SYNCHRONOUS, ERR_FAILED),
9559 };
9560
9561 // After the challenge above, the transaction will be restarted using the
9562 // identity supplied by the user, not the one in the URL, to answer the
9563 // challenge.
9564 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239565 MockWrite(
9566 "GET / HTTP/1.1\r\n"
9567 "Host: www.example.org\r\n"
9568 "Connection: keep-alive\r\n"
9569 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549570 };
9571
9572 MockRead data_reads3[] = {
9573 MockRead("HTTP/1.0 200 OK\r\n"),
9574 MockRead("Content-Length: 100\r\n\r\n"),
9575 MockRead(SYNCHRONOUS, OK),
9576 };
9577
Ryan Sleevib8d7ea02018-05-07 20:01:019578 StaticSocketDataProvider data1(data_reads1, data_writes1);
9579 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:549580 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9581 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9582
9583 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209584 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019585 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549586 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019587 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169588 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549589
bnc691fda62016-08-12 00:43:169590 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529591 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589592 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:549593
9594 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169595 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019596 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:549597 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019598 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169599 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:549600
bnc691fda62016-08-12 00:43:169601 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529602 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:549603
9604 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589605 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:549606 EXPECT_EQ(100, response->headers->GetContentLength());
9607
9608 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559609 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:549610}
9611
[email protected]f9ee6b52008-11-08 06:46:239612// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:019613TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:099614 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:239615
9616 // Transaction 1: authenticate (foo, bar) on MyRealm1
9617 {
[email protected]1c773ea12009-04-28 19:58:429618 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239619 request.method = "GET";
bncce36dca22015-04-21 22:11:239620 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:109621 request.traffic_annotation =
9622 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239623
bnc691fda62016-08-12 00:43:169624 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279625
[email protected]f9ee6b52008-11-08 06:46:239626 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239627 MockWrite(
9628 "GET /x/y/z HTTP/1.1\r\n"
9629 "Host: www.example.org\r\n"
9630 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239631 };
9632
9633 MockRead data_reads1[] = {
9634 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9635 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9636 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069637 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239638 };
9639
9640 // Resend with authorization (username=foo, password=bar)
9641 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239642 MockWrite(
9643 "GET /x/y/z HTTP/1.1\r\n"
9644 "Host: www.example.org\r\n"
9645 "Connection: keep-alive\r\n"
9646 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239647 };
9648
9649 // Sever accepts the authorization.
9650 MockRead data_reads2[] = {
9651 MockRead("HTTP/1.0 200 OK\r\n"),
9652 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069653 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239654 };
9655
Ryan Sleevib8d7ea02018-05-07 20:01:019656 StaticSocketDataProvider data1(data_reads1, data_writes1);
9657 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079658 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9659 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239660
[email protected]49639fa2011-12-20 23:22:419661 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239662
tfarina42834112016-09-22 13:38:209663 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019664 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239665
9666 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019667 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239668
bnc691fda62016-08-12 00:43:169669 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529670 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589671 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239672
[email protected]49639fa2011-12-20 23:22:419673 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239674
bnc691fda62016-08-12 00:43:169675 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9676 callback2.callback());
robpercival214763f2016-07-01 23:27:019677 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239678
9679 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019680 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239681
bnc691fda62016-08-12 00:43:169682 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529683 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589684 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239685 EXPECT_EQ(100, response->headers->GetContentLength());
9686 }
9687
9688 // ------------------------------------------------------------------------
9689
9690 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
9691 {
[email protected]1c773ea12009-04-28 19:58:429692 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239693 request.method = "GET";
9694 // Note that Transaction 1 was at /x/y/z, so this is in the same
9695 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:239696 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109697 request.traffic_annotation =
9698 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239699
bnc691fda62016-08-12 00:43:169700 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279701
[email protected]f9ee6b52008-11-08 06:46:239702 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239703 MockWrite(
9704 "GET /x/y/a/b HTTP/1.1\r\n"
9705 "Host: www.example.org\r\n"
9706 "Connection: keep-alive\r\n"
9707 // Send preemptive authorization for MyRealm1
9708 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239709 };
9710
9711 // The server didn't like the preemptive authorization, and
9712 // challenges us for a different realm (MyRealm2).
9713 MockRead data_reads1[] = {
9714 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9715 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
9716 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069717 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239718 };
9719
9720 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
9721 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239722 MockWrite(
9723 "GET /x/y/a/b HTTP/1.1\r\n"
9724 "Host: www.example.org\r\n"
9725 "Connection: keep-alive\r\n"
9726 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239727 };
9728
9729 // Sever accepts the authorization.
9730 MockRead data_reads2[] = {
9731 MockRead("HTTP/1.0 200 OK\r\n"),
9732 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069733 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239734 };
9735
Ryan Sleevib8d7ea02018-05-07 20:01:019736 StaticSocketDataProvider data1(data_reads1, data_writes1);
9737 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079738 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9739 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239740
[email protected]49639fa2011-12-20 23:22:419741 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239742
tfarina42834112016-09-22 13:38:209743 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019744 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239745
9746 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019747 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239748
bnc691fda62016-08-12 00:43:169749 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529750 ASSERT_TRUE(response);
9751 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:049752 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:439753 EXPECT_EQ("http://www.example.org",
9754 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049755 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:199756 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:239757
[email protected]49639fa2011-12-20 23:22:419758 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239759
bnc691fda62016-08-12 00:43:169760 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
9761 callback2.callback());
robpercival214763f2016-07-01 23:27:019762 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239763
9764 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019765 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239766
bnc691fda62016-08-12 00:43:169767 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529768 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589769 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239770 EXPECT_EQ(100, response->headers->GetContentLength());
9771 }
9772
9773 // ------------------------------------------------------------------------
9774
9775 // Transaction 3: Resend a request in MyRealm's protection space --
9776 // succeed with preemptive authorization.
9777 {
[email protected]1c773ea12009-04-28 19:58:429778 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239779 request.method = "GET";
bncce36dca22015-04-21 22:11:239780 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e62018-02-07 07:41:109781 request.traffic_annotation =
9782 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239783
bnc691fda62016-08-12 00:43:169784 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279785
[email protected]f9ee6b52008-11-08 06:46:239786 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239787 MockWrite(
9788 "GET /x/y/z2 HTTP/1.1\r\n"
9789 "Host: www.example.org\r\n"
9790 "Connection: keep-alive\r\n"
9791 // The authorization for MyRealm1 gets sent preemptively
9792 // (since the url is in the same protection space)
9793 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239794 };
9795
9796 // Sever accepts the preemptive authorization
9797 MockRead data_reads1[] = {
9798 MockRead("HTTP/1.0 200 OK\r\n"),
9799 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069800 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239801 };
9802
Ryan Sleevib8d7ea02018-05-07 20:01:019803 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079804 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:239805
[email protected]49639fa2011-12-20 23:22:419806 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239807
tfarina42834112016-09-22 13:38:209808 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019809 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239810
9811 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019812 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239813
bnc691fda62016-08-12 00:43:169814 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529815 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:239816
Emily Starkf2c9bbd2019-04-09 17:08:589817 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239818 EXPECT_EQ(100, response->headers->GetContentLength());
9819 }
9820
9821 // ------------------------------------------------------------------------
9822
9823 // Transaction 4: request another URL in MyRealm (however the
9824 // url is not known to belong to the protection space, so no pre-auth).
9825 {
[email protected]1c773ea12009-04-28 19:58:429826 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239827 request.method = "GET";
bncce36dca22015-04-21 22:11:239828 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e62018-02-07 07:41:109829 request.traffic_annotation =
9830 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239831
bnc691fda62016-08-12 00:43:169832 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279833
[email protected]f9ee6b52008-11-08 06:46:239834 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239835 MockWrite(
9836 "GET /x/1 HTTP/1.1\r\n"
9837 "Host: www.example.org\r\n"
9838 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239839 };
9840
9841 MockRead data_reads1[] = {
9842 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9843 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9844 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069845 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239846 };
9847
9848 // Resend with authorization from MyRealm's cache.
9849 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239850 MockWrite(
9851 "GET /x/1 HTTP/1.1\r\n"
9852 "Host: www.example.org\r\n"
9853 "Connection: keep-alive\r\n"
9854 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239855 };
9856
9857 // Sever accepts the authorization.
9858 MockRead data_reads2[] = {
9859 MockRead("HTTP/1.0 200 OK\r\n"),
9860 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069861 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239862 };
9863
Ryan Sleevib8d7ea02018-05-07 20:01:019864 StaticSocketDataProvider data1(data_reads1, data_writes1);
9865 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079866 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9867 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239868
[email protected]49639fa2011-12-20 23:22:419869 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239870
tfarina42834112016-09-22 13:38:209871 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019872 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239873
9874 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019875 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239876
bnc691fda62016-08-12 00:43:169877 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419878 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169879 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019880 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229881 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019882 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169883 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229884
bnc691fda62016-08-12 00:43:169885 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529886 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589887 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239888 EXPECT_EQ(100, response->headers->GetContentLength());
9889 }
9890
9891 // ------------------------------------------------------------------------
9892
9893 // Transaction 5: request a URL in MyRealm, but the server rejects the
9894 // cached identity. Should invalidate and re-prompt.
9895 {
[email protected]1c773ea12009-04-28 19:58:429896 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239897 request.method = "GET";
bncce36dca22015-04-21 22:11:239898 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e62018-02-07 07:41:109899 request.traffic_annotation =
9900 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239901
bnc691fda62016-08-12 00:43:169902 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279903
[email protected]f9ee6b52008-11-08 06:46:239904 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239905 MockWrite(
9906 "GET /p/q/t HTTP/1.1\r\n"
9907 "Host: www.example.org\r\n"
9908 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239909 };
9910
9911 MockRead data_reads1[] = {
9912 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9913 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9914 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069915 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239916 };
9917
9918 // Resend with authorization from cache for MyRealm.
9919 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239920 MockWrite(
9921 "GET /p/q/t HTTP/1.1\r\n"
9922 "Host: www.example.org\r\n"
9923 "Connection: keep-alive\r\n"
9924 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239925 };
9926
9927 // Sever rejects the authorization.
9928 MockRead data_reads2[] = {
9929 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9930 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9931 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069932 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239933 };
9934
9935 // At this point we should prompt for new credentials for MyRealm.
9936 // Restart with username=foo3, password=foo4.
9937 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239938 MockWrite(
9939 "GET /p/q/t HTTP/1.1\r\n"
9940 "Host: www.example.org\r\n"
9941 "Connection: keep-alive\r\n"
9942 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239943 };
9944
9945 // Sever accepts the authorization.
9946 MockRead data_reads3[] = {
9947 MockRead("HTTP/1.0 200 OK\r\n"),
9948 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069949 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239950 };
9951
Ryan Sleevib8d7ea02018-05-07 20:01:019952 StaticSocketDataProvider data1(data_reads1, data_writes1);
9953 StaticSocketDataProvider data2(data_reads2, data_writes2);
9954 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079955 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9956 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9957 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239958
[email protected]49639fa2011-12-20 23:22:419959 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239960
tfarina42834112016-09-22 13:38:209961 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019962 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239963
9964 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019965 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239966
bnc691fda62016-08-12 00:43:169967 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419968 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169969 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019970 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229971 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019972 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169973 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229974
bnc691fda62016-08-12 00:43:169975 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529976 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589977 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239978
[email protected]49639fa2011-12-20 23:22:419979 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239980
bnc691fda62016-08-12 00:43:169981 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9982 callback3.callback());
robpercival214763f2016-07-01 23:27:019983 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239984
[email protected]0757e7702009-03-27 04:00:229985 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019986 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239987
bnc691fda62016-08-12 00:43:169988 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529989 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589990 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239991 EXPECT_EQ(100, response->headers->GetContentLength());
9992 }
9993}
[email protected]89ceba9a2009-03-21 03:46:069994
[email protected]3c32c5f2010-05-18 15:18:129995// Tests that nonce count increments when multiple auth attempts
9996// are started with the same nonce.
bncd16676a2016-07-20 16:23:019997TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:449998 HttpAuthHandlerDigest::Factory* digest_factory =
9999 new HttpAuthHandlerDigest::Factory();
10000 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
10001 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
10002 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:0710003 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:0910004 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:1210005
10006 // Transaction 1: authenticate (foo, bar) on MyRealm1
10007 {
[email protected]3c32c5f2010-05-18 15:18:1210008 HttpRequestInfo request;
10009 request.method = "GET";
bncce36dca22015-04-21 22:11:2310010 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:1010011 request.traffic_annotation =
10012 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210013
bnc691fda62016-08-12 00:43:1610014 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710015
[email protected]3c32c5f2010-05-18 15:18:1210016 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310017 MockWrite(
10018 "GET /x/y/z HTTP/1.1\r\n"
10019 "Host: www.example.org\r\n"
10020 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210021 };
10022
10023 MockRead data_reads1[] = {
10024 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10025 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
10026 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610027 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210028 };
10029
10030 // Resend with authorization (username=foo, password=bar)
10031 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310032 MockWrite(
10033 "GET /x/y/z HTTP/1.1\r\n"
10034 "Host: www.example.org\r\n"
10035 "Connection: keep-alive\r\n"
10036 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10037 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
10038 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
10039 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210040 };
10041
10042 // Sever accepts the authorization.
10043 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:0810044 MockRead("HTTP/1.0 200 OK\r\n"),
10045 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210046 };
10047
Ryan Sleevib8d7ea02018-05-07 20:01:0110048 StaticSocketDataProvider data1(data_reads1, data_writes1);
10049 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710050 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10051 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:1210052
[email protected]49639fa2011-12-20 23:22:4110053 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210054
tfarina42834112016-09-22 13:38:2010055 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110056 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210057
10058 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110059 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210060
bnc691fda62016-08-12 00:43:1610061 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210062 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810063 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:1210064
[email protected]49639fa2011-12-20 23:22:4110065 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:1210066
bnc691fda62016-08-12 00:43:1610067 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10068 callback2.callback());
robpercival214763f2016-07-01 23:27:0110069 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210070
10071 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110072 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210073
bnc691fda62016-08-12 00:43:1610074 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210075 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810076 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210077 }
10078
10079 // ------------------------------------------------------------------------
10080
10081 // Transaction 2: Request another resource in digestive's protection space.
10082 // This will preemptively add an Authorization header which should have an
10083 // "nc" value of 2 (as compared to 1 in the first use.
10084 {
[email protected]3c32c5f2010-05-18 15:18:1210085 HttpRequestInfo request;
10086 request.method = "GET";
10087 // Note that Transaction 1 was at /x/y/z, so this is in the same
10088 // protection space as digest.
bncce36dca22015-04-21 22:11:2310089 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:1010090 request.traffic_annotation =
10091 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210092
bnc691fda62016-08-12 00:43:1610093 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710094
[email protected]3c32c5f2010-05-18 15:18:1210095 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310096 MockWrite(
10097 "GET /x/y/a/b HTTP/1.1\r\n"
10098 "Host: www.example.org\r\n"
10099 "Connection: keep-alive\r\n"
10100 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10101 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
10102 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
10103 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210104 };
10105
10106 // Sever accepts the authorization.
10107 MockRead data_reads1[] = {
10108 MockRead("HTTP/1.0 200 OK\r\n"),
10109 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610110 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210111 };
10112
Ryan Sleevib8d7ea02018-05-07 20:01:0110113 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710114 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:1210115
[email protected]49639fa2011-12-20 23:22:4110116 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210117
tfarina42834112016-09-22 13:38:2010118 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110119 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210120
10121 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110122 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210123
bnc691fda62016-08-12 00:43:1610124 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210125 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810126 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210127 }
10128}
10129
[email protected]89ceba9a2009-03-21 03:46:0610130// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:0110131TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:0610132 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:0910133 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610134 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:0610135
10136 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:4410137 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:1610138 trans.read_buf_len_ = 15;
10139 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:0610140
10141 // Setup state in response_
bnc691fda62016-08-12 00:43:1610142 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:5810143 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:0810144 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:5710145 response->response_time = base::Time::Now();
10146 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:0610147
10148 { // Setup state for response_.vary_data
10149 HttpRequestInfo request;
10150 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
10151 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:2710152 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:4310153 request.extra_headers.SetHeader("Foo", "1");
10154 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:5010155 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:0610156 }
10157
10158 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:1610159 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:0610160
10161 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:1610162 EXPECT_FALSE(trans.read_buf_);
10163 EXPECT_EQ(0, trans.read_buf_len_);
10164 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:5810165 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:5210166 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:0410167 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:0810168 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:5710169 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:0610170}
10171
[email protected]bacff652009-03-31 17:50:3310172// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:0110173TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:3310174 HttpRequestInfo request;
10175 request.method = "GET";
bncce36dca22015-04-21 22:11:2310176 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010177 request.traffic_annotation =
10178 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310179
danakj1fd259a02016-04-16 03:17:0910180 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610181 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710182
[email protected]bacff652009-03-31 17:50:3310183 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310184 MockWrite(
10185 "GET / HTTP/1.1\r\n"
10186 "Host: www.example.org\r\n"
10187 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310188 };
10189
10190 MockRead data_reads[] = {
10191 MockRead("HTTP/1.0 200 OK\r\n"),
10192 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10193 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610194 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310195 };
10196
[email protected]5ecc992a42009-11-11 01:41:5910197 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:0110198 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610199 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10200 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310201
[email protected]bb88e1d32013-05-03 23:11:0710202 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10203 session_deps_.socket_factory->AddSocketDataProvider(&data);
10204 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10205 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310206
[email protected]49639fa2011-12-20 23:22:4110207 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310208
tfarina42834112016-09-22 13:38:2010209 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110210 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310211
10212 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110213 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310214
bnc691fda62016-08-12 00:43:1610215 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110216 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310217
10218 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110219 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310220
bnc691fda62016-08-12 00:43:1610221 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310222
wezca1070932016-05-26 20:30:5210223 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310224 EXPECT_EQ(100, response->headers->GetContentLength());
10225}
10226
10227// Test HTTPS connections to a site with a bad certificate, going through a
10228// proxy
bncd16676a2016-07-20 16:23:0110229TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910230 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10231 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310232
10233 HttpRequestInfo request;
10234 request.method = "GET";
bncce36dca22015-04-21 22:11:2310235 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010236 request.traffic_annotation =
10237 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310238
10239 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710240 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10241 "Host: www.example.org:443\r\n"
10242 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310243 };
10244
10245 MockRead proxy_reads[] = {
10246 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610247 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:3310248 };
10249
10250 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710251 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10252 "Host: www.example.org:443\r\n"
10253 "Proxy-Connection: keep-alive\r\n\r\n"),
10254 MockWrite("GET / HTTP/1.1\r\n"
10255 "Host: www.example.org\r\n"
10256 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310257 };
10258
10259 MockRead data_reads[] = {
10260 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10261 MockRead("HTTP/1.0 200 OK\r\n"),
10262 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10263 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610264 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310265 };
10266
Ryan Sleevib8d7ea02018-05-07 20:01:0110267 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
10268 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610269 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10270 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310271
[email protected]bb88e1d32013-05-03 23:11:0710272 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10273 session_deps_.socket_factory->AddSocketDataProvider(&data);
10274 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10275 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310276
[email protected]49639fa2011-12-20 23:22:4110277 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310278
10279 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:0710280 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:3310281
danakj1fd259a02016-04-16 03:17:0910282 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610283 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:3310284
tfarina42834112016-09-22 13:38:2010285 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110286 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310287
10288 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110289 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310290
bnc691fda62016-08-12 00:43:1610291 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110292 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310293
10294 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110295 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310296
bnc691fda62016-08-12 00:43:1610297 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310298
wezca1070932016-05-26 20:30:5210299 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310300 EXPECT_EQ(100, response->headers->GetContentLength());
10301 }
10302}
10303
[email protected]2df19bb2010-08-25 20:13:4610304
10305// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:0110306TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910307 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910308 ProxyResolutionService::CreateFixedFromPacResult(
10309 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110310 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710311 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:4610312
10313 HttpRequestInfo request;
10314 request.method = "GET";
bncce36dca22015-04-21 22:11:2310315 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010316 request.traffic_annotation =
10317 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610318
10319 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710320 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10321 "Host: www.example.org:443\r\n"
10322 "Proxy-Connection: keep-alive\r\n\r\n"),
10323 MockWrite("GET / HTTP/1.1\r\n"
10324 "Host: www.example.org\r\n"
10325 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610326 };
10327
10328 MockRead data_reads[] = {
10329 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10330 MockRead("HTTP/1.1 200 OK\r\n"),
10331 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10332 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610333 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610334 };
10335
Ryan Sleevib8d7ea02018-05-07 20:01:0110336 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610337 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10338 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:4610339
[email protected]bb88e1d32013-05-03 23:11:0710340 session_deps_.socket_factory->AddSocketDataProvider(&data);
10341 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10342 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:4610343
[email protected]49639fa2011-12-20 23:22:4110344 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610345
danakj1fd259a02016-04-16 03:17:0910346 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610347 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610348
tfarina42834112016-09-22 13:38:2010349 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110350 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610351
10352 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110353 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610354 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610355
wezca1070932016-05-26 20:30:5210356 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610357
tbansal2ecbbc72016-10-06 17:15:4710358 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:4610359 EXPECT_TRUE(response->headers->IsKeepAlive());
10360 EXPECT_EQ(200, response->headers->response_code());
10361 EXPECT_EQ(100, response->headers->GetContentLength());
10362 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2010363
10364 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610365 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010366 TestLoadTimingNotReusedWithPac(load_timing_info,
10367 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:4610368}
10369
Eric Roman695a7872019-04-16 21:53:2910370// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:0110371TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910372 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910373 ProxyResolutionService::CreateFixedFromPacResult(
10374 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110375 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710376 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:2910377
Matt Menkeecfecfc72019-02-05 19:15:2810378 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10379 session_deps_.host_resolver->set_ondemand_mode(true);
10380
[email protected]511f6f52010-12-17 03:58:2910381 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:1210382 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:2910383 request.method = "GET";
bncce36dca22015-04-21 22:11:2310384 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010385 request.traffic_annotation =
10386 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910387
10388 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810389 MockWrite(ASYNC, 0,
10390 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710391 "Host: www.example.org:443\r\n"
10392 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910393 };
10394
10395 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810396 // Pause on first read.
10397 MockRead(ASYNC, ERR_IO_PENDING, 1),
10398 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
10399 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
10400 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910401 };
10402
Matt Menkeecfecfc72019-02-05 19:15:2810403 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610404 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910405
[email protected]bb88e1d32013-05-03 23:11:0710406 session_deps_.socket_factory->AddSocketDataProvider(&data);
10407 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910408
[email protected]49639fa2011-12-20 23:22:4110409 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910410
danakj1fd259a02016-04-16 03:17:0910411 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610412 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910413
tfarina42834112016-09-22 13:38:2010414 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110415 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810416 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
10417
10418 // Host resolution takes |kTimeIncrement|.
10419 FastForwardBy(kTimeIncrement);
10420 // Resolving the current request with |ResolveNow| will cause the pending
10421 // request to instantly complete, and the async connect will start as well.
10422 session_deps_.host_resolver->ResolveOnlyRequestNow();
10423
10424 // Connecting takes |kTimeIncrement|.
10425 FastForwardBy(kTimeIncrement);
10426 data.RunUntilPaused();
10427
10428 // The server takes |kTimeIncrement| to respond.
10429 FastForwardBy(kTimeIncrement);
10430 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910431
10432 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910433 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910434}
10435
Eric Roman74103c72019-02-21 00:23:1210436// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
10437TEST_F(HttpNetworkTransactionTest,
10438 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
10439 base::HistogramTester histograms;
10440 session_deps_.proxy_resolution_service =
10441 ProxyResolutionService::CreateFixedFromPacResult(
10442 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10443 TestNetLog net_log;
10444 session_deps_.net_log = &net_log;
10445
10446 HttpRequestInfo request;
10447 request.method = "GET";
10448 request.url = GURL("https://www.example.org/");
10449 request.traffic_annotation =
10450 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10451
10452 MockWrite data_writes[] = {
10453 MockWrite(ASYNC, 0,
10454 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10455 "Host: www.example.org:443\r\n"
10456 "Proxy-Connection: keep-alive\r\n\r\n"),
10457 };
10458
10459 MockRead data_reads[] = {
10460 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10461 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10462 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10463 };
10464
10465 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10466 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10467
10468 session_deps_.socket_factory->AddSocketDataProvider(&data);
10469 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10470
10471 TestCompletionCallback callback;
10472
10473 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10474 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10475
10476 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10477 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10478
10479 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910480 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210481}
10482
10483// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
10484// request for main frames.
10485TEST_F(HttpNetworkTransactionTest,
10486 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
10487 base::HistogramTester histograms;
10488 session_deps_.proxy_resolution_service =
10489 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
10490 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10491 TestNetLog net_log;
10492 session_deps_.net_log = &net_log;
10493
10494 HttpRequestInfo request;
10495 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
10496 request.method = "GET";
10497 request.url = GURL("https://www.example.org/");
10498 request.traffic_annotation =
10499 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10500
10501 MockWrite data_writes[] = {
10502 MockWrite(ASYNC, 0,
10503 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10504 "Host: www.example.org:443\r\n"
10505 "Proxy-Connection: keep-alive\r\n\r\n"),
10506 };
10507
10508 MockRead data_reads[] = {
10509 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10510 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10511 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10512 };
10513
10514 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10515 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10516
10517 session_deps_.socket_factory->AddSocketDataProvider(&data);
10518 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10519
10520 TestCompletionCallback callback;
10521
10522 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10523 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10524
10525 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10527
10528 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910529 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210530}
10531
Eric Roman695a7872019-04-16 21:53:2910532// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:1210533// frames.
bncd16676a2016-07-20 16:23:0110534TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:1210535 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:4910536 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10537 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:2810538 TestNetLog net_log;
10539 session_deps_.net_log = &net_log;
10540
Matt Menkeecfecfc72019-02-05 19:15:2810541 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10542 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:2910543
10544 HttpRequestInfo request;
10545 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:1210546 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:2310547 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010548 request.traffic_annotation =
10549 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910550
Ryan Hamilton0239aac2018-05-19 00:03:1310551 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410552 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10553 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310554 spdy::SpdySerializedFrame goaway(
10555 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910556 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110557 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:2810558 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:2910559 };
10560
10561 static const char* const kExtraHeaders[] = {
10562 "location",
10563 "http://login.example.com/",
10564 };
Ryan Hamilton0239aac2018-05-19 00:03:1310565 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410566 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:2910567 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810568 // Pause on first read.
10569 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
10570 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910571 };
10572
Matt Menkeecfecfc72019-02-05 19:15:2810573 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610574 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610575 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910576
[email protected]bb88e1d32013-05-03 23:11:0710577 session_deps_.socket_factory->AddSocketDataProvider(&data);
10578 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910579
[email protected]49639fa2011-12-20 23:22:4110580 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910581
danakj1fd259a02016-04-16 03:17:0910582 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610583 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910584
tfarina42834112016-09-22 13:38:2010585 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110586 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810587 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:2910588
Matt Menkeecfecfc72019-02-05 19:15:2810589 // Host resolution takes |kTimeIncrement|.
10590 FastForwardBy(kTimeIncrement);
10591 // Resolving the current request with |ResolveNow| will cause the pending
10592 // request to instantly complete, and the async connect will start as well.
10593 session_deps_.host_resolver->ResolveOnlyRequestNow();
10594
10595 // Connecting takes |kTimeIncrement|.
10596 FastForwardBy(kTimeIncrement);
10597 data.RunUntilPaused();
10598
10599 FastForwardBy(kTimeIncrement);
10600 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910601 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910602 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910603}
10604
[email protected]4eddbc732012-08-09 05:40:1710605// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110606TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910607 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10608 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910609
10610 HttpRequestInfo request;
10611 request.method = "GET";
bncce36dca22015-04-21 22:11:2310612 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010613 request.traffic_annotation =
10614 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910615
10616 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710617 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10618 "Host: www.example.org:443\r\n"
10619 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910620 };
10621
10622 MockRead data_reads[] = {
10623 MockRead("HTTP/1.1 404 Not Found\r\n"),
10624 MockRead("Content-Length: 23\r\n\r\n"),
10625 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:0610626 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:2910627 };
10628
Ryan Sleevib8d7ea02018-05-07 20:01:0110629 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610630 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910631
[email protected]bb88e1d32013-05-03 23:11:0710632 session_deps_.socket_factory->AddSocketDataProvider(&data);
10633 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910634
[email protected]49639fa2011-12-20 23:22:4110635 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910636
danakj1fd259a02016-04-16 03:17:0910637 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610638 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910639
tfarina42834112016-09-22 13:38:2010640 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110641 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910642
10643 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110644 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910645
ttuttle960fcbf2016-04-19 13:26:3210646 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910647}
10648
[email protected]4eddbc732012-08-09 05:40:1710649// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0110650TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910651 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10652 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910653
10654 HttpRequestInfo request;
10655 request.method = "GET";
bncce36dca22015-04-21 22:11:2310656 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010657 request.traffic_annotation =
10658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910659
Ryan Hamilton0239aac2018-05-19 00:03:1310660 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410661 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10662 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310663 spdy::SpdySerializedFrame rst(
10664 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910665 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110666 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:2910667 };
10668
10669 static const char* const kExtraHeaders[] = {
10670 "location",
10671 "http://login.example.com/",
10672 };
Ryan Hamilton0239aac2018-05-19 00:03:1310673 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410674 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1310675 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:1910676 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:2910677 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110678 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1310679 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910680 };
10681
Ryan Sleevib8d7ea02018-05-07 20:01:0110682 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610683 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610684 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910685
[email protected]bb88e1d32013-05-03 23:11:0710686 session_deps_.socket_factory->AddSocketDataProvider(&data);
10687 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910688
[email protected]49639fa2011-12-20 23:22:4110689 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910690
danakj1fd259a02016-04-16 03:17:0910691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610692 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910693
tfarina42834112016-09-22 13:38:2010694 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110695 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910696
10697 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110698 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910699
ttuttle960fcbf2016-04-19 13:26:3210700 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910701}
10702
[email protected]0c5fb722012-02-28 11:50:3510703// Test the request-challenge-retry sequence for basic auth, through
10704// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0110705TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3510706 HttpRequestInfo request;
10707 request.method = "GET";
bncce36dca22015-04-21 22:11:2310708 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3510709 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:2910710 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:1010711 request.traffic_annotation =
10712 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3510713
10714 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5910715 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910716 ProxyResolutionService::CreateFixedFromPacResult(
10717 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110718 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710719 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0910720 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3510721
10722 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1310723 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410724 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10725 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310726 spdy::SpdySerializedFrame rst(
10727 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3810728 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3510729
bnc691fda62016-08-12 00:43:1610730 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3510731 // be issuing -- the final header line contains the credentials.
10732 const char* const kAuthCredentials[] = {
10733 "proxy-authorization", "Basic Zm9vOmJhcg==",
10734 };
Ryan Hamilton0239aac2018-05-19 00:03:1310735 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410736 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
10737 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2310738 HostPortPair("www.example.org", 443)));
10739 // fetch https://www.example.org/ via HTTP
10740 const char get[] =
10741 "GET / HTTP/1.1\r\n"
10742 "Host: www.example.org\r\n"
10743 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1310744 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1910745 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3510746
10747 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110748 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
10749 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3510750 };
10751
10752 // The proxy responds to the connect with a 407, using a persistent
10753 // connection.
thestig9d3bb0c2015-01-24 00:49:5110754 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3510755 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3510756 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
10757 };
Ryan Hamilton0239aac2018-05-19 00:03:1310758 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410759 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3510760
Ryan Hamilton0239aac2018-05-19 00:03:1310761 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3510762 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3510763 const char resp[] = "HTTP/1.1 200 OK\r\n"
10764 "Content-Length: 5\r\n\r\n";
10765
Ryan Hamilton0239aac2018-05-19 00:03:1310766 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1910767 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1310768 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1910769 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3510770 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110771 CreateMockRead(conn_auth_resp, 1, ASYNC),
10772 CreateMockRead(conn_resp, 4, ASYNC),
10773 CreateMockRead(wrapped_get_resp, 6, ASYNC),
10774 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1310775 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3510776 };
10777
Ryan Sleevib8d7ea02018-05-07 20:01:0110778 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710779 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3510780 // Negotiate SPDY to the proxy
10781 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610782 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710783 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3510784 // Vanilla SSL to the server
10785 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710786 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3510787
10788 TestCompletionCallback callback1;
10789
bnc87dcefc2017-05-25 12:47:5810790 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910791 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3510792
10793 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110794 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510795
10796 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110797 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5410798 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3510799 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0010800 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10801 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510802 ExpectLogContainsSomewhere(
10803 entries, pos,
mikecirone8b85c432016-09-08 19:11:0010804 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10805 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510806
10807 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210808 ASSERT_TRUE(response);
10809 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3510810 EXPECT_EQ(407, response->headers->response_code());
10811 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5810812 EXPECT_TRUE(response->auth_challenge.has_value());
10813 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3510814
10815 TestCompletionCallback callback2;
10816
10817 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
10818 callback2.callback());
robpercival214763f2016-07-01 23:27:0110819 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510820
10821 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110822 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3510823
10824 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210825 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3510826
10827 EXPECT_TRUE(response->headers->IsKeepAlive());
10828 EXPECT_EQ(200, response->headers->response_code());
10829 EXPECT_EQ(5, response->headers->GetContentLength());
10830 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10831
10832 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810833 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510834
[email protected]029c83b62013-01-24 05:28:2010835 LoadTimingInfo load_timing_info;
10836 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10837 TestLoadTimingNotReusedWithPac(load_timing_info,
10838 CONNECT_TIMING_HAS_SSL_TIMES);
10839
[email protected]0c5fb722012-02-28 11:50:3510840 trans.reset();
10841 session->CloseAllConnections();
10842}
10843
[email protected]7c6f7ba2012-04-03 04:09:2910844// Test that an explicitly trusted SPDY proxy can push a resource from an
10845// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0110846TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1510847 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910848 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510849 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10850 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2910851 HttpRequestInfo request;
10852 HttpRequestInfo push_request;
Ramin Halavatib5e433e62018-02-07 07:41:1010853 request.traffic_annotation =
10854 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910855
[email protected]7c6f7ba2012-04-03 04:09:2910856 request.method = "GET";
bncce36dca22015-04-21 22:11:2310857 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910858 push_request.method = "GET";
10859 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e62018-02-07 07:41:1010860 push_request.traffic_annotation =
10861 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910862
tbansal28e68f82016-02-04 02:56:1510863 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910864 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910865 ProxyResolutionService::CreateFixedFromPacResult(
10866 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110867 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710868 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010869
Eric Roman3d8546a2018-09-10 17:00:5210870 session_deps_.proxy_resolution_service->SetProxyDelegate(
10871 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010872
danakj1fd259a02016-04-16 03:17:0910873 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910874
Ryan Hamilton0239aac2018-05-19 00:03:1310875 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510876 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310877 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510878 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910879
10880 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110881 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510882 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910883 };
10884
Ryan Hamilton0239aac2018-05-19 00:03:1310885 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510886 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610887
Ryan Hamilton0239aac2018-05-19 00:03:1310888 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510889 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910890
Ryan Hamilton0239aac2018-05-19 00:03:1310891 spdy::SpdySerializedFrame stream1_body(
10892 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910893
Ryan Hamilton0239aac2018-05-19 00:03:1310894 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910895 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910896
10897 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610898 CreateMockRead(stream2_syn, 1, ASYNC),
10899 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510900 CreateMockRead(stream1_body, 4, ASYNC),
10901 CreateMockRead(stream2_body, 5, ASYNC),
10902 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910903 };
10904
Ryan Sleevib8d7ea02018-05-07 20:01:0110905 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710906 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910907 // Negotiate SPDY to the proxy
10908 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610909 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710910 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910911
bnc87dcefc2017-05-25 12:47:5810912 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910913 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910914 TestCompletionCallback callback;
10915 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110916 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910917
10918 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110919 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910920 const HttpResponseInfo* response = trans->GetResponseInfo();
10921
bnc87dcefc2017-05-25 12:47:5810922 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910923 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010924 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110925 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910926
10927 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110928 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910929 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10930
wezca1070932016-05-26 20:30:5210931 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910932 EXPECT_TRUE(response->headers->IsKeepAlive());
10933
10934 EXPECT_EQ(200, response->headers->response_code());
10935 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10936
10937 std::string response_data;
10938 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110939 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910940 EXPECT_EQ("hello!", response_data);
10941
[email protected]029c83b62013-01-24 05:28:2010942 LoadTimingInfo load_timing_info;
10943 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10944 TestLoadTimingNotReusedWithPac(load_timing_info,
10945 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10946
[email protected]7c6f7ba2012-04-03 04:09:2910947 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210948 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910949 EXPECT_EQ(200, push_response->headers->response_code());
10950
10951 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110952 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910953 EXPECT_EQ("pushed", response_data);
10954
[email protected]029c83b62013-01-24 05:28:2010955 LoadTimingInfo push_load_timing_info;
10956 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10957 TestLoadTimingReusedWithPac(push_load_timing_info);
10958 // The transactions should share a socket ID, despite being for different
10959 // origins.
10960 EXPECT_EQ(load_timing_info.socket_log_id,
10961 push_load_timing_info.socket_log_id);
10962
[email protected]7c6f7ba2012-04-03 04:09:2910963 trans.reset();
10964 push_trans.reset();
10965 session->CloseAllConnections();
10966}
10967
[email protected]8c843192012-04-05 07:15:0010968// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110969TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510970 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910971 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510972 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10973 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010974 HttpRequestInfo request;
10975
10976 request.method = "GET";
bncce36dca22015-04-21 22:11:2310977 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010978 request.traffic_annotation =
10979 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010980
Ramin Halavatica8d5252018-03-12 05:33:4910981 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10982 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110983 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710984 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010985
10986 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210987 session_deps_.proxy_resolution_service->SetProxyDelegate(
10988 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010989
danakj1fd259a02016-04-16 03:17:0910990 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010991
Ryan Hamilton0239aac2018-05-19 00:03:1310992 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510993 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010994
Ryan Hamilton0239aac2018-05-19 00:03:1310995 spdy::SpdySerializedFrame push_rst(
10996 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0010997
10998 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110999 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0011000 };
11001
Ryan Hamilton0239aac2018-05-19 00:03:1311002 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511003 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0011004
Ryan Hamilton0239aac2018-05-19 00:03:1311005 spdy::SpdySerializedFrame stream1_body(
11006 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0011007
Ryan Hamilton0239aac2018-05-19 00:03:1311008 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511009 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0011010
11011 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111012 CreateMockRead(stream1_reply, 1, ASYNC),
11013 CreateMockRead(stream2_syn, 2, ASYNC),
11014 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5911015 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0011016 };
11017
Ryan Sleevib8d7ea02018-05-07 20:01:0111018 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711019 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0011020 // Negotiate SPDY to the proxy
11021 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611022 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711023 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0011024
bnc87dcefc2017-05-25 12:47:5811025 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911026 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0011027 TestCompletionCallback callback;
11028 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111029 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0011030
11031 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111032 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011033 const HttpResponseInfo* response = trans->GetResponseInfo();
11034
wezca1070932016-05-26 20:30:5211035 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0011036 EXPECT_TRUE(response->headers->IsKeepAlive());
11037
11038 EXPECT_EQ(200, response->headers->response_code());
11039 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11040
11041 std::string response_data;
11042 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111043 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011044 EXPECT_EQ("hello!", response_data);
11045
11046 trans.reset();
11047 session->CloseAllConnections();
11048}
11049
tbansal8ef1d3e2016-02-03 04:05:4211050// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
11051// resources.
bncd16676a2016-07-20 16:23:0111052TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511053 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911054 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511055 proxy_delegate->set_trusted_spdy_proxy(
11056 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
11057
tbansal8ef1d3e2016-02-03 04:05:4211058 HttpRequestInfo request;
11059
11060 request.method = "GET";
11061 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011062 request.traffic_annotation =
11063 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211064
11065 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4911066 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11067 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211068 BoundTestNetLog log;
11069 session_deps_.net_log = log.bound().net_log();
11070
11071 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211072 session_deps_.proxy_resolution_service->SetProxyDelegate(
11073 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4211074
danakj1fd259a02016-04-16 03:17:0911075 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4211076
Ryan Hamilton0239aac2018-05-19 00:03:1311077 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511078 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311079 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511080 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4211081
11082 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111083 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511084 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4211085 };
11086
Ryan Hamilton0239aac2018-05-19 00:03:1311087 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1511088 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211089
Ryan Hamilton0239aac2018-05-19 00:03:1311090 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3311091 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4911092
Ryan Hamilton0239aac2018-05-19 00:03:1311093 spdy::SpdySerializedFrame stream1_body(
11094 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211095
Ryan Hamilton0239aac2018-05-19 00:03:1311096 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1511097 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211098
Ryan Hamilton0239aac2018-05-19 00:03:1311099 spdy::SpdySerializedFrame stream2_body(
11100 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211101
11102 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111103 CreateMockRead(stream1_reply, 1, ASYNC),
11104 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511105 CreateMockRead(stream1_body, 4, ASYNC),
11106 CreateMockRead(stream2_body, 5, ASYNC),
11107 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4211108 };
11109
Ryan Sleevib8d7ea02018-05-07 20:01:0111110 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4211111 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11112 // Negotiate SPDY to the proxy
11113 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611114 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4211115 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
11116
bnc87dcefc2017-05-25 12:47:5811117 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911118 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4211119 TestCompletionCallback callback;
11120 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111121 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4211122
11123 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111124 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211125 const HttpResponseInfo* response = trans->GetResponseInfo();
11126
wezca1070932016-05-26 20:30:5211127 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4211128 EXPECT_TRUE(response->headers->IsKeepAlive());
11129
11130 EXPECT_EQ(200, response->headers->response_code());
11131 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11132
11133 std::string response_data;
11134 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111135 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211136 EXPECT_EQ("hello!", response_data);
11137
11138 trans.reset();
11139 session->CloseAllConnections();
11140}
11141
[email protected]2df19bb2010-08-25 20:13:4611142// Test HTTPS connections to a site with a bad certificate, going through an
11143// HTTPS proxy
bncd16676a2016-07-20 16:23:0111144TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4911145 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11146 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611147
11148 HttpRequestInfo request;
11149 request.method = "GET";
bncce36dca22015-04-21 22:11:2311150 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011151 request.traffic_annotation =
11152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611153
11154 // Attempt to fetch the URL from a server with a bad cert
11155 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711156 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11157 "Host: www.example.org:443\r\n"
11158 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611159 };
11160
11161 MockRead bad_cert_reads[] = {
11162 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611163 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4611164 };
11165
11166 // Attempt to fetch the URL with a good cert
11167 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711168 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11169 "Host: www.example.org:443\r\n"
11170 "Proxy-Connection: keep-alive\r\n\r\n"),
11171 MockWrite("GET / HTTP/1.1\r\n"
11172 "Host: www.example.org\r\n"
11173 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611174 };
11175
11176 MockRead good_cert_reads[] = {
11177 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
11178 MockRead("HTTP/1.0 200 OK\r\n"),
11179 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11180 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611181 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4611182 };
11183
Ryan Sleevib8d7ea02018-05-07 20:01:0111184 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
11185 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0611186 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
11187 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4611188
11189 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0711190 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11191 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
11192 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4611193
11194 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0711195 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11196 session_deps_.socket_factory->AddSocketDataProvider(&data);
11197 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4611198
[email protected]49639fa2011-12-20 23:22:4111199 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4611200
danakj1fd259a02016-04-16 03:17:0911201 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611202 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4611203
tfarina42834112016-09-22 13:38:2011204 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111205 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611206
11207 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111208 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4611209
bnc691fda62016-08-12 00:43:1611210 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0111211 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611212
11213 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111214 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4611215
bnc691fda62016-08-12 00:43:1611216 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4611217
wezca1070932016-05-26 20:30:5211218 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4611219 EXPECT_EQ(100, response->headers->GetContentLength());
11220}
11221
bncd16676a2016-07-20 16:23:0111222TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4211223 HttpRequestInfo request;
11224 request.method = "GET";
bncce36dca22015-04-21 22:11:2311225 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311226 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11227 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e62018-02-07 07:41:1011228 request.traffic_annotation =
11229 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211230
danakj1fd259a02016-04-16 03:17:0911231 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611232 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711233
[email protected]1c773ea12009-04-28 19:58:4211234 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311235 MockWrite(
11236 "GET / HTTP/1.1\r\n"
11237 "Host: www.example.org\r\n"
11238 "Connection: keep-alive\r\n"
11239 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211240 };
11241
11242 // Lastly, the server responds with the actual content.
11243 MockRead data_reads[] = {
11244 MockRead("HTTP/1.0 200 OK\r\n"),
11245 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11246 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611247 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211248 };
11249
Ryan Sleevib8d7ea02018-05-07 20:01:0111250 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711251 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211252
[email protected]49639fa2011-12-20 23:22:4111253 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211254
tfarina42834112016-09-22 13:38:2011255 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111256 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211257
11258 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111259 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211260}
11261
bncd16676a2016-07-20 16:23:0111262TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0011263 // Test user agent values, used both for the request header of the original
11264 // request, and the value returned by the HttpUserAgentSettings. nullptr means
11265 // no request header / no HttpUserAgentSettings object.
11266 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2911267
Matt Menked732ea42019-03-08 12:05:0011268 for (const char* setting_user_agent : kTestUserAgents) {
11269 if (!setting_user_agent) {
11270 session_deps_.http_user_agent_settings.reset();
11271 } else {
11272 session_deps_.http_user_agent_settings =
11273 std::make_unique<StaticHttpUserAgentSettings>(
11274 std::string() /* accept-language */, setting_user_agent);
11275 }
11276 session_deps_.proxy_resolution_service =
11277 ProxyResolutionService::CreateFixed("myproxy:70",
11278 TRAFFIC_ANNOTATION_FOR_TESTS);
11279 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11280 for (const char* request_user_agent : kTestUserAgents) {
11281 HttpRequestInfo request;
11282 request.method = "GET";
11283 request.url = GURL("https://www.example.org/");
11284 if (request_user_agent) {
11285 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11286 request_user_agent);
11287 }
11288 request.traffic_annotation =
11289 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711290
Matt Menked732ea42019-03-08 12:05:0011291 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2911292
Matt Menked732ea42019-03-08 12:05:0011293 std::string expected_request;
11294 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
11295 expected_request =
11296 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11297 "Host: www.example.org:443\r\n"
11298 "Proxy-Connection: keep-alive\r\n\r\n";
11299 } else {
11300 expected_request = base::StringPrintf(
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"
11304 "User-Agent: %s\r\n\r\n",
11305 setting_user_agent);
11306 }
11307 MockWrite data_writes[] = {
11308 MockWrite(expected_request.c_str()),
11309 };
11310 MockRead data_reads[] = {
11311 // Return an error, so the transaction stops here (this test isn't
11312 // interested in the rest).
11313 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
11314 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11315 MockRead("Proxy-Connection: close\r\n\r\n"),
11316 };
[email protected]da81f132010-08-18 23:39:2911317
Matt Menked732ea42019-03-08 12:05:0011318 StaticSocketDataProvider data(data_reads, data_writes);
11319 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2911320
Matt Menked732ea42019-03-08 12:05:0011321 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2911322
Matt Menked732ea42019-03-08 12:05:0011323 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11324 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11325
11326 rv = callback.WaitForResult();
11327 EXPECT_THAT(rv, IsOk());
11328 }
11329 }
[email protected]da81f132010-08-18 23:39:2911330}
11331
bncd16676a2016-07-20 16:23:0111332TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4211333 HttpRequestInfo request;
11334 request.method = "GET";
bncce36dca22015-04-21 22:11:2311335 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1611336 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
11337 "http://the.previous.site.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011338 request.traffic_annotation =
11339 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211340
danakj1fd259a02016-04-16 03:17:0911341 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611342 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711343
[email protected]1c773ea12009-04-28 19:58:4211344 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311345 MockWrite(
11346 "GET / HTTP/1.1\r\n"
11347 "Host: www.example.org\r\n"
11348 "Connection: keep-alive\r\n"
11349 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211350 };
11351
11352 // Lastly, the server responds with the actual content.
11353 MockRead data_reads[] = {
11354 MockRead("HTTP/1.0 200 OK\r\n"),
11355 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11356 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611357 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211358 };
11359
Ryan Sleevib8d7ea02018-05-07 20:01:0111360 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711361 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211362
[email protected]49639fa2011-12-20 23:22:4111363 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211364
tfarina42834112016-09-22 13:38:2011365 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111366 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211367
11368 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111369 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211370}
11371
bncd16676a2016-07-20 16:23:0111372TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211373 HttpRequestInfo request;
11374 request.method = "POST";
bncce36dca22015-04-21 22:11:2311375 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011376 request.traffic_annotation =
11377 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211378
danakj1fd259a02016-04-16 03:17:0911379 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611380 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711381
[email protected]1c773ea12009-04-28 19:58:4211382 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311383 MockWrite(
11384 "POST / HTTP/1.1\r\n"
11385 "Host: www.example.org\r\n"
11386 "Connection: keep-alive\r\n"
11387 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211388 };
11389
11390 // Lastly, the server responds with the actual content.
11391 MockRead data_reads[] = {
11392 MockRead("HTTP/1.0 200 OK\r\n"),
11393 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11394 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611395 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211396 };
11397
Ryan Sleevib8d7ea02018-05-07 20:01:0111398 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711399 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211400
[email protected]49639fa2011-12-20 23:22:4111401 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211402
tfarina42834112016-09-22 13:38:2011403 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111404 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211405
11406 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111407 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211408}
11409
bncd16676a2016-07-20 16:23:0111410TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211411 HttpRequestInfo request;
11412 request.method = "PUT";
bncce36dca22015-04-21 22:11:2311413 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011414 request.traffic_annotation =
11415 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211416
danakj1fd259a02016-04-16 03:17:0911417 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611418 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711419
[email protected]1c773ea12009-04-28 19:58:4211420 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311421 MockWrite(
11422 "PUT / HTTP/1.1\r\n"
11423 "Host: www.example.org\r\n"
11424 "Connection: keep-alive\r\n"
11425 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211426 };
11427
11428 // Lastly, the server responds with the actual content.
11429 MockRead data_reads[] = {
11430 MockRead("HTTP/1.0 200 OK\r\n"),
11431 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11432 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611433 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211434 };
11435
Ryan Sleevib8d7ea02018-05-07 20:01:0111436 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711437 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211438
[email protected]49639fa2011-12-20 23:22:4111439 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211440
tfarina42834112016-09-22 13:38:2011441 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111442 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211443
11444 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111445 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211446}
11447
bncd16676a2016-07-20 16:23:0111448TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211449 HttpRequestInfo request;
11450 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2311451 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011452 request.traffic_annotation =
11453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211454
danakj1fd259a02016-04-16 03:17:0911455 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611456 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711457
[email protected]1c773ea12009-04-28 19:58:4211458 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1311459 MockWrite("HEAD / HTTP/1.1\r\n"
11460 "Host: www.example.org\r\n"
11461 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211462 };
11463
11464 // Lastly, the server responds with the actual content.
11465 MockRead data_reads[] = {
11466 MockRead("HTTP/1.0 200 OK\r\n"),
11467 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11468 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611469 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211470 };
11471
Ryan Sleevib8d7ea02018-05-07 20:01:0111472 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711473 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211474
[email protected]49639fa2011-12-20 23:22:4111475 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211476
tfarina42834112016-09-22 13:38:2011477 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111478 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211479
11480 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111481 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211482}
11483
bncd16676a2016-07-20 16:23:0111484TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4211485 HttpRequestInfo request;
11486 request.method = "GET";
bncce36dca22015-04-21 22:11:2311487 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211488 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1011489 request.traffic_annotation =
11490 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211491
danakj1fd259a02016-04-16 03:17:0911492 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611493 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711494
[email protected]1c773ea12009-04-28 19:58:4211495 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311496 MockWrite(
11497 "GET / HTTP/1.1\r\n"
11498 "Host: www.example.org\r\n"
11499 "Connection: keep-alive\r\n"
11500 "Pragma: no-cache\r\n"
11501 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211502 };
11503
11504 // Lastly, the server responds with the actual content.
11505 MockRead data_reads[] = {
11506 MockRead("HTTP/1.0 200 OK\r\n"),
11507 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11508 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611509 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211510 };
11511
Ryan Sleevib8d7ea02018-05-07 20:01:0111512 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711513 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211514
[email protected]49639fa2011-12-20 23:22:4111515 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211516
tfarina42834112016-09-22 13:38:2011517 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111518 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211519
11520 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111521 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211522}
11523
bncd16676a2016-07-20 16:23:0111524TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4211525 HttpRequestInfo request;
11526 request.method = "GET";
bncce36dca22015-04-21 22:11:2311527 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211528 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1011529 request.traffic_annotation =
11530 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211531
danakj1fd259a02016-04-16 03:17:0911532 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611533 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711534
[email protected]1c773ea12009-04-28 19:58:4211535 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311536 MockWrite(
11537 "GET / HTTP/1.1\r\n"
11538 "Host: www.example.org\r\n"
11539 "Connection: keep-alive\r\n"
11540 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211541 };
11542
11543 // Lastly, the server responds with the actual content.
11544 MockRead data_reads[] = {
11545 MockRead("HTTP/1.0 200 OK\r\n"),
11546 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11547 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611548 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211549 };
11550
Ryan Sleevib8d7ea02018-05-07 20:01:0111551 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711552 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211553
[email protected]49639fa2011-12-20 23:22:4111554 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211555
tfarina42834112016-09-22 13:38:2011556 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111557 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211558
11559 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111560 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211561}
11562
bncd16676a2016-07-20 16:23:0111563TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4211564 HttpRequestInfo request;
11565 request.method = "GET";
bncce36dca22015-04-21 22:11:2311566 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311567 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e62018-02-07 07:41:1011568 request.traffic_annotation =
11569 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211570
danakj1fd259a02016-04-16 03:17:0911571 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611572 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711573
[email protected]1c773ea12009-04-28 19:58:4211574 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311575 MockWrite(
11576 "GET / HTTP/1.1\r\n"
11577 "Host: www.example.org\r\n"
11578 "Connection: keep-alive\r\n"
11579 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211580 };
11581
11582 // Lastly, the server responds with the actual content.
11583 MockRead data_reads[] = {
11584 MockRead("HTTP/1.0 200 OK\r\n"),
11585 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11586 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611587 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211588 };
11589
Ryan Sleevib8d7ea02018-05-07 20:01:0111590 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711591 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211592
[email protected]49639fa2011-12-20 23:22:4111593 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211594
tfarina42834112016-09-22 13:38:2011595 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111596 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211597
11598 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111599 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211600}
11601
bncd16676a2016-07-20 16:23:0111602TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4711603 HttpRequestInfo request;
11604 request.method = "GET";
bncce36dca22015-04-21 22:11:2311605 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311606 request.extra_headers.SetHeader("referer", "www.foo.com");
11607 request.extra_headers.SetHeader("hEllo", "Kitty");
11608 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1011609 request.traffic_annotation =
11610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4711611
danakj1fd259a02016-04-16 03:17:0911612 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611613 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711614
[email protected]270c6412010-03-29 22:02:4711615 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311616 MockWrite(
11617 "GET / HTTP/1.1\r\n"
11618 "Host: www.example.org\r\n"
11619 "Connection: keep-alive\r\n"
11620 "referer: www.foo.com\r\n"
11621 "hEllo: Kitty\r\n"
11622 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4711623 };
11624
11625 // Lastly, the server responds with the actual content.
11626 MockRead data_reads[] = {
11627 MockRead("HTTP/1.0 200 OK\r\n"),
11628 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11629 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611630 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4711631 };
11632
Ryan Sleevib8d7ea02018-05-07 20:01:0111633 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711634 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4711635
[email protected]49639fa2011-12-20 23:22:4111636 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4711637
tfarina42834112016-09-22 13:38:2011638 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111639 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4711640
11641 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111642 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4711643}
11644
bncd16676a2016-07-20 16:23:0111645TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711646 HttpRequestInfo request;
11647 request.method = "GET";
bncce36dca22015-04-21 22:11:2311648 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011649 request.traffic_annotation =
11650 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711651
Lily Houghton8c2f97d2018-01-22 05:06:5911652 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911653 ProxyResolutionService::CreateFixedFromPacResult(
11654 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111655 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711656 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211657
danakj1fd259a02016-04-16 03:17:0911658 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611659 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211660
[email protected]3cd17242009-06-23 02:59:0211661 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11662 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11663
11664 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411665 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11666 MockWrite("GET / HTTP/1.1\r\n"
11667 "Host: www.example.org\r\n"
11668 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211669
11670 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411671 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11672 MockRead("HTTP/1.0 200 OK\r\n"),
11673 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11674 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211675
Ryan Sleevib8d7ea02018-05-07 20:01:0111676 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711677 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211678
[email protected]49639fa2011-12-20 23:22:4111679 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211680
tfarina42834112016-09-22 13:38:2011681 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111682 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211683
11684 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111685 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211686
bnc691fda62016-08-12 00:43:1611687 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211688 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0211689
tbansal2ecbbc72016-10-06 17:15:4711690 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2011691 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611692 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011693 TestLoadTimingNotReusedWithPac(load_timing_info,
11694 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11695
[email protected]3cd17242009-06-23 02:59:0211696 std::string response_text;
bnc691fda62016-08-12 00:43:1611697 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111698 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211699 EXPECT_EQ("Payload", response_text);
11700}
11701
bncd16676a2016-07-20 16:23:0111702TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711703 HttpRequestInfo request;
11704 request.method = "GET";
bncce36dca22015-04-21 22:11:2311705 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011706 request.traffic_annotation =
11707 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711708
Lily Houghton8c2f97d2018-01-22 05:06:5911709 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911710 ProxyResolutionService::CreateFixedFromPacResult(
11711 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111712 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711713 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211714
danakj1fd259a02016-04-16 03:17:0911715 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611716 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211717
[email protected]3cd17242009-06-23 02:59:0211718 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
11719 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11720
11721 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311722 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2411723 base::size(write_buffer)),
11724 MockWrite("GET / HTTP/1.1\r\n"
11725 "Host: www.example.org\r\n"
11726 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211727
11728 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411729 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
11730 base::size(read_buffer)),
11731 MockRead("HTTP/1.0 200 OK\r\n"),
11732 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11733 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511734
Ryan Sleevib8d7ea02018-05-07 20:01:0111735 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711736 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511737
[email protected]8ddf8322012-02-23 18:08:0611738 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711739 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3511740
[email protected]49639fa2011-12-20 23:22:4111741 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511742
tfarina42834112016-09-22 13:38:2011743 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111744 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511745
11746 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111747 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511748
[email protected]029c83b62013-01-24 05:28:2011749 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611750 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011751 TestLoadTimingNotReusedWithPac(load_timing_info,
11752 CONNECT_TIMING_HAS_SSL_TIMES);
11753
bnc691fda62016-08-12 00:43:1611754 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211755 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711756 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511757
11758 std::string response_text;
bnc691fda62016-08-12 00:43:1611759 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111760 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511761 EXPECT_EQ("Payload", response_text);
11762}
11763
bncd16676a2016-07-20 16:23:0111764TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2011765 HttpRequestInfo request;
11766 request.method = "GET";
bncce36dca22015-04-21 22:11:2311767 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011768 request.traffic_annotation =
11769 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2011770
Ramin Halavatica8d5252018-03-12 05:33:4911771 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11772 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111773 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711774 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2011775
danakj1fd259a02016-04-16 03:17:0911776 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611777 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2011778
11779 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11780 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11781
11782 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411783 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11784 MockWrite("GET / HTTP/1.1\r\n"
11785 "Host: www.example.org\r\n"
11786 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2011787
11788 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411789 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11790 MockRead("HTTP/1.0 200 OK\r\n"),
11791 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11792 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2011793
Ryan Sleevib8d7ea02018-05-07 20:01:0111794 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711795 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2011796
11797 TestCompletionCallback callback;
11798
tfarina42834112016-09-22 13:38:2011799 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111800 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2011801
11802 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111803 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011804
bnc691fda62016-08-12 00:43:1611805 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211806 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2011807
11808 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611809 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011810 TestLoadTimingNotReused(load_timing_info,
11811 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11812
11813 std::string response_text;
bnc691fda62016-08-12 00:43:1611814 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111815 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011816 EXPECT_EQ("Payload", response_text);
11817}
11818
bncd16676a2016-07-20 16:23:0111819TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711820 HttpRequestInfo request;
11821 request.method = "GET";
bncce36dca22015-04-21 22:11:2311822 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011823 request.traffic_annotation =
11824 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711825
Lily Houghton8c2f97d2018-01-22 05:06:5911826 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911827 ProxyResolutionService::CreateFixedFromPacResult(
11828 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111829 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711830 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511831
danakj1fd259a02016-04-16 03:17:0911832 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611833 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511834
[email protected]e0c27be2009-07-15 13:09:3511835 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11836 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711837 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311838 0x05, // Version
11839 0x01, // Command (CONNECT)
11840 0x00, // Reserved.
11841 0x03, // Address type (DOMAINNAME).
11842 0x0F, // Length of domain (15)
11843 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11844 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3711845 };
[email protected]e0c27be2009-07-15 13:09:3511846 const char kSOCKS5OkResponse[] =
11847 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
11848
11849 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411850 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
11851 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
11852 MockWrite("GET / HTTP/1.1\r\n"
11853 "Host: www.example.org\r\n"
11854 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511855
11856 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411857 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11858 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11859 MockRead("HTTP/1.0 200 OK\r\n"),
11860 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11861 MockRead("Payload"),
11862 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511863
Ryan Sleevib8d7ea02018-05-07 20:01:0111864 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711865 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511866
[email protected]49639fa2011-12-20 23:22:4111867 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511868
tfarina42834112016-09-22 13:38:2011869 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111870 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511871
11872 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111873 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511874
bnc691fda62016-08-12 00:43:1611875 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211876 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711877 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511878
[email protected]029c83b62013-01-24 05:28:2011879 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611880 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011881 TestLoadTimingNotReusedWithPac(load_timing_info,
11882 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11883
[email protected]e0c27be2009-07-15 13:09:3511884 std::string response_text;
bnc691fda62016-08-12 00:43:1611885 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111886 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511887 EXPECT_EQ("Payload", response_text);
11888}
11889
bncd16676a2016-07-20 16:23:0111890TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711891 HttpRequestInfo request;
11892 request.method = "GET";
bncce36dca22015-04-21 22:11:2311893 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011894 request.traffic_annotation =
11895 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711896
Lily Houghton8c2f97d2018-01-22 05:06:5911897 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911898 ProxyResolutionService::CreateFixedFromPacResult(
11899 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111900 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711901 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511902
danakj1fd259a02016-04-16 03:17:0911903 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611904 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511905
[email protected]e0c27be2009-07-15 13:09:3511906 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11907 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711908 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311909 0x05, // Version
11910 0x01, // Command (CONNECT)
11911 0x00, // Reserved.
11912 0x03, // Address type (DOMAINNAME).
11913 0x0F, // Length of domain (15)
11914 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11915 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711916 };
11917
[email protected]e0c27be2009-07-15 13:09:3511918 const char kSOCKS5OkResponse[] =
11919 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11920
11921 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411922 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311923 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411924 base::size(kSOCKS5OkRequest)),
11925 MockWrite("GET / HTTP/1.1\r\n"
11926 "Host: www.example.org\r\n"
11927 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511928
11929 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411930 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11931 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11932 MockRead("HTTP/1.0 200 OK\r\n"),
11933 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11934 MockRead("Payload"),
11935 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211936
Ryan Sleevib8d7ea02018-05-07 20:01:0111937 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711938 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211939
[email protected]8ddf8322012-02-23 18:08:0611940 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711941 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211942
[email protected]49639fa2011-12-20 23:22:4111943 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211944
tfarina42834112016-09-22 13:38:2011945 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111946 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211947
11948 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111949 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211950
bnc691fda62016-08-12 00:43:1611951 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211952 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711953 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211954
[email protected]029c83b62013-01-24 05:28:2011955 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611956 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011957 TestLoadTimingNotReusedWithPac(load_timing_info,
11958 CONNECT_TIMING_HAS_SSL_TIMES);
11959
[email protected]3cd17242009-06-23 02:59:0211960 std::string response_text;
bnc691fda62016-08-12 00:43:1611961 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111962 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211963 EXPECT_EQ("Payload", response_text);
11964}
11965
[email protected]448d4ca52012-03-04 04:12:2311966namespace {
11967
Matt Menkef6edce752019-03-19 17:21:5611968// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611969
Matt Menkef6edce752019-03-19 17:21:5611970struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611971 std::string proxy_server;
11972 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611973 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811974 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611975};
11976
Matt Menkef6edce752019-03-19 17:21:5611977std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711978 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911979 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611980
bnc525e175a2016-06-20 12:36:4011981 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311982 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111983 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211984 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111985 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211986 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0711987 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611988
11989 return session;
11990}
11991
Matt Menkef6edce752019-03-19 17:21:5611992int GroupIdTransactionHelper(const std::string& url,
11993 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611994 HttpRequestInfo request;
11995 request.method = "GET";
11996 request.url = GURL(url);
Ramin Halavatib5e433e62018-02-07 07:41:1011997 request.traffic_annotation =
11998 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0611999
bnc691fda62016-08-12 00:43:1612000 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2712001
[email protected]49639fa2011-12-20 23:22:4112002 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0612003
12004 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2012005 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0612006}
12007
[email protected]448d4ca52012-03-04 04:12:2312008} // namespace
12009
Matt Menkef6edce752019-03-19 17:21:5612010TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
12011 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312012 {
Matt Menkef6edce752019-03-19 17:21:5612013 "", // unused
12014 "http://www.example.org/direct",
12015 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12016 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412017 PrivacyMode::PRIVACY_MODE_DISABLED,
12018 NetworkIsolationKey(),
12019 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612020 false,
bncce36dca22015-04-21 22:11:2312021 },
12022 {
Matt Menkef6edce752019-03-19 17:21:5612023 "", // unused
12024 "http://[2001:1418:13:1::25]/direct",
12025 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
12026 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412027 PrivacyMode::PRIVACY_MODE_DISABLED,
12028 NetworkIsolationKey(),
12029 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612030 false,
bncce36dca22015-04-21 22:11:2312031 },
[email protected]04e5be32009-06-26 20:00:3112032
bncce36dca22015-04-21 22:11:2312033 // SSL Tests
12034 {
Matt Menkef6edce752019-03-19 17:21:5612035 "", // unused
12036 "https://www.example.org/direct_ssl",
12037 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12038 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412039 PrivacyMode::PRIVACY_MODE_DISABLED,
12040 NetworkIsolationKey(),
12041 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612042 true,
bncce36dca22015-04-21 22:11:2312043 },
12044 {
Matt Menkef6edce752019-03-19 17:21:5612045 "", // unused
12046 "https://[2001:1418:13:1::25]/direct",
12047 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
12048 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412049 PrivacyMode::PRIVACY_MODE_DISABLED,
12050 NetworkIsolationKey(),
12051 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612052 true,
bncce36dca22015-04-21 22:11:2312053 },
12054 {
Matt Menkef6edce752019-03-19 17:21:5612055 "", // unused
12056 "https://host.with.alternate/direct",
12057 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12058 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412059 PrivacyMode::PRIVACY_MODE_DISABLED,
12060 NetworkIsolationKey(),
12061 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612062 true,
bncce36dca22015-04-21 22:11:2312063 },
[email protected]2d731a32010-04-29 01:04:0612064 };
[email protected]2ff8b312010-04-26 22:20:5412065
Avi Drissman4365a4782018-12-28 19:26:2412066 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912067 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4912068 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
12069 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912070 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612071 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612072
mmenkee65e7af2015-10-13 17:16:4212073 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5612074 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612075 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912076 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012077 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
12078 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4812079 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612080
12081 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612082 GroupIdTransactionHelper(tests[i].url, session.get()));
12083 EXPECT_EQ(tests[i].expected_group_id,
12084 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2312085 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0612086 }
[email protected]2d731a32010-04-29 01:04:0612087}
12088
Matt Menkef6edce752019-03-19 17:21:5612089TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
12090 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312091 {
Matt Menke4802de62019-03-08 22:47:5012092 "http_proxy",
12093 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5612094 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12095 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412096 PrivacyMode::PRIVACY_MODE_DISABLED,
12097 NetworkIsolationKey(),
12098 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012099 false,
bncce36dca22015-04-21 22:11:2312100 },
[email protected]2d731a32010-04-29 01:04:0612101
bncce36dca22015-04-21 22:11:2312102 // SSL Tests
12103 {
Matt Menke4802de62019-03-08 22:47:5012104 "http_proxy",
12105 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5612106 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12107 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412108 PrivacyMode::PRIVACY_MODE_DISABLED,
12109 NetworkIsolationKey(),
12110 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012111 true,
bncce36dca22015-04-21 22:11:2312112 },
[email protected]af3490e2010-10-16 21:02:2912113
bncce36dca22015-04-21 22:11:2312114 {
Matt Menke4802de62019-03-08 22:47:5012115 "http_proxy",
12116 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612117 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12118 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412119 PrivacyMode::PRIVACY_MODE_DISABLED,
12120 NetworkIsolationKey(),
12121 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012122 true,
bncce36dca22015-04-21 22:11:2312123 },
[email protected]2d731a32010-04-29 01:04:0612124 };
12125
Avi Drissman4365a4782018-12-28 19:26:2412126 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912127 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4912128 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
12129 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912130 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612131 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612132
mmenkee65e7af2015-10-13 17:16:4212133 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0612134
Matt Menkee8648fa2019-01-17 16:47:0712135 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
12136 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5612137 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3612138 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912139 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012140 mock_pool_manager->SetSocketPool(proxy_server,
12141 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4812142 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612143
12144 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612145 GroupIdTransactionHelper(tests[i].url, session.get()));
12146 EXPECT_EQ(tests[i].expected_group_id,
12147 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0612148 }
[email protected]2d731a32010-04-29 01:04:0612149}
12150
Matt Menkef6edce752019-03-19 17:21:5612151TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
12152 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312153 {
Matt Menke4802de62019-03-08 22:47:5012154 "socks4://socks_proxy:1080",
12155 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5612156 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12157 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412158 PrivacyMode::PRIVACY_MODE_DISABLED,
12159 NetworkIsolationKey(),
12160 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012161 false,
bncce36dca22015-04-21 22:11:2312162 },
12163 {
Matt Menke4802de62019-03-08 22:47:5012164 "socks5://socks_proxy:1080",
12165 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5612166 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12167 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412168 PrivacyMode::PRIVACY_MODE_DISABLED,
12169 NetworkIsolationKey(),
12170 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012171 false,
bncce36dca22015-04-21 22:11:2312172 },
[email protected]2d731a32010-04-29 01:04:0612173
bncce36dca22015-04-21 22:11:2312174 // SSL Tests
12175 {
Matt Menke4802de62019-03-08 22:47:5012176 "socks4://socks_proxy:1080",
12177 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5612178 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12179 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412180 PrivacyMode::PRIVACY_MODE_DISABLED,
12181 NetworkIsolationKey(),
12182 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012183 true,
bncce36dca22015-04-21 22:11:2312184 },
12185 {
Matt Menke4802de62019-03-08 22:47:5012186 "socks5://socks_proxy:1080",
12187 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5612188 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12189 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412190 PrivacyMode::PRIVACY_MODE_DISABLED,
12191 NetworkIsolationKey(),
12192 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012193 true,
bncce36dca22015-04-21 22:11:2312194 },
[email protected]af3490e2010-10-16 21:02:2912195
bncce36dca22015-04-21 22:11:2312196 {
Matt Menke4802de62019-03-08 22:47:5012197 "socks4://socks_proxy:1080",
12198 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612199 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12200 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412201 PrivacyMode::PRIVACY_MODE_DISABLED,
12202 NetworkIsolationKey(),
12203 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012204 true,
bncce36dca22015-04-21 22:11:2312205 },
[email protected]04e5be32009-06-26 20:00:3112206 };
12207
Avi Drissman4365a4782018-12-28 19:26:2412208 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912209 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4912210 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
12211 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912212 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612213 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0212214
mmenkee65e7af2015-10-13 17:16:4212215 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3112216
Matt Menkee8648fa2019-01-17 16:47:0712217 ProxyServer proxy_server(
12218 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
12219 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5612220 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612221 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912222 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012223 mock_pool_manager->SetSocketPool(proxy_server,
12224 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4812225 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3112226
bnc691fda62016-08-12 00:43:1612227 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3112228
[email protected]2d731a32010-04-29 01:04:0612229 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612230 GroupIdTransactionHelper(tests[i].url, session.get()));
12231 EXPECT_EQ(tests[i].expected_group_id,
12232 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3112233 }
12234}
12235
bncd16676a2016-07-20 16:23:0112236TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2712237 HttpRequestInfo request;
12238 request.method = "GET";
bncce36dca22015-04-21 22:11:2312239 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012240 request.traffic_annotation =
12241 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712242
Ramin Halavatica8d5252018-03-12 05:33:4912243 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
12244 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3212245
[email protected]69719062010-01-05 20:09:2112246 // This simulates failure resolving all hostnames; that means we will fail
12247 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0712248 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3212249
danakj1fd259a02016-04-16 03:17:0912250 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612251 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2512252
[email protected]49639fa2011-12-20 23:22:4112253 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2512254
tfarina42834112016-09-22 13:38:2012255 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112256 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2512257
[email protected]9172a982009-06-06 00:30:2512258 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112259 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2512260}
12261
[email protected]0877e3d2009-10-17 22:29:5712262// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0112263TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5712264 HttpRequestInfo request;
12265 request.method = "GET";
12266 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1012267 request.traffic_annotation =
12268 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712269
12270 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0612271 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712272 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112273 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0712274 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912275 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712276
[email protected]49639fa2011-12-20 23:22:4112277 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712278
bnc691fda62016-08-12 00:43:1612279 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712280
tfarina42834112016-09-22 13:38:2012281 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112282 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712283
12284 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112285 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5912286
12287 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612288 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912289 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712290}
12291
zmo9528c9f42015-08-04 22:12:0812292// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0112293TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5712294 HttpRequestInfo request;
12295 request.method = "GET";
12296 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1012297 request.traffic_annotation =
12298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712299
12300 MockRead data_reads[] = {
12301 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0612302 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712303 };
12304
Ryan Sleevib8d7ea02018-05-07 20:01:0112305 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712306 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912307 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712308
[email protected]49639fa2011-12-20 23:22:4112309 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712310
bnc691fda62016-08-12 00:43:1612311 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712312
tfarina42834112016-09-22 13:38:2012313 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112314 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712315
12316 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112317 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812318
bnc691fda62016-08-12 00:43:1612319 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212320 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0812321
wezca1070932016-05-26 20:30:5212322 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0812323 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12324
12325 std::string response_data;
bnc691fda62016-08-12 00:43:1612326 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112327 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812328 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5912329
12330 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612331 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912332 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712333}
12334
12335// Make sure that a dropped connection while draining the body for auth
12336// restart does the right thing.
bncd16676a2016-07-20 16:23:0112337TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5712338 HttpRequestInfo request;
12339 request.method = "GET";
bncce36dca22015-04-21 22:11:2312340 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012341 request.traffic_annotation =
12342 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712343
12344 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312345 MockWrite(
12346 "GET / HTTP/1.1\r\n"
12347 "Host: www.example.org\r\n"
12348 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712349 };
12350
12351 MockRead data_reads1[] = {
12352 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
12353 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
12354 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12355 MockRead("Content-Length: 14\r\n\r\n"),
12356 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0612357 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712358 };
12359
Ryan Sleevib8d7ea02018-05-07 20:01:0112360 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0712361 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5712362
bnc691fda62016-08-12 00:43:1612363 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5712364 // be issuing -- the final header line contains the credentials.
12365 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312366 MockWrite(
12367 "GET / HTTP/1.1\r\n"
12368 "Host: www.example.org\r\n"
12369 "Connection: keep-alive\r\n"
12370 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712371 };
12372
12373 // Lastly, the server responds with the actual content.
12374 MockRead data_reads2[] = {
12375 MockRead("HTTP/1.1 200 OK\r\n"),
12376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12377 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612378 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712379 };
12380
Ryan Sleevib8d7ea02018-05-07 20:01:0112381 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0712382 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0912383 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712384
[email protected]49639fa2011-12-20 23:22:4112385 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5712386
bnc691fda62016-08-12 00:43:1612387 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012388
tfarina42834112016-09-22 13:38:2012389 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112390 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712391
12392 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112393 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712394
bnc691fda62016-08-12 00:43:1612395 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212396 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812397 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5712398
[email protected]49639fa2011-12-20 23:22:4112399 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5712400
bnc691fda62016-08-12 00:43:1612401 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0112402 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712403
12404 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112405 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712406
bnc691fda62016-08-12 00:43:1612407 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212408 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812409 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5712410 EXPECT_EQ(100, response->headers->GetContentLength());
12411}
12412
12413// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0112414TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4912415 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
12416 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712417
12418 HttpRequestInfo request;
12419 request.method = "GET";
bncce36dca22015-04-21 22:11:2312420 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012421 request.traffic_annotation =
12422 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712423
12424 MockRead proxy_reads[] = {
12425 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0612426 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5712427 };
12428
Ryan Sleevib8d7ea02018-05-07 20:01:0112429 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0612430 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5712431
[email protected]bb88e1d32013-05-03 23:11:0712432 session_deps_.socket_factory->AddSocketDataProvider(&data);
12433 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5712434
[email protected]49639fa2011-12-20 23:22:4112435 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712436
[email protected]bb88e1d32013-05-03 23:11:0712437 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5712438
danakj1fd259a02016-04-16 03:17:0912439 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612440 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712441
tfarina42834112016-09-22 13:38:2012442 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112443 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712444
12445 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112446 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5712447}
12448
bncd16676a2016-07-20 16:23:0112449TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4612450 HttpRequestInfo request;
12451 request.method = "GET";
bncce36dca22015-04-21 22:11:2312452 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012453 request.traffic_annotation =
12454 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4612455
danakj1fd259a02016-04-16 03:17:0912456 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612457 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712458
[email protected]e22e1362009-11-23 21:31:1212459 MockRead data_reads[] = {
12460 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612461 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1212462 };
[email protected]9492e4a2010-02-24 00:58:4612463
Ryan Sleevib8d7ea02018-05-07 20:01:0112464 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712465 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4612466
[email protected]49639fa2011-12-20 23:22:4112467 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4612468
tfarina42834112016-09-22 13:38:2012469 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112470 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4612471
robpercival214763f2016-07-01 23:27:0112472 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4612473
bnc691fda62016-08-12 00:43:1612474 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212475 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4612476
wezca1070932016-05-26 20:30:5212477 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4612478 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12479
12480 std::string response_data;
bnc691fda62016-08-12 00:43:1612481 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112482 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1212483}
12484
bncd16676a2016-07-20 16:23:0112485TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1512486 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5212487 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1412488 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2112489 UploadFileElementReader::ScopedOverridingContentLengthForTests
12490 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3312491
danakj1fd259a02016-04-16 03:17:0912492 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912493 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412494 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0712495 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212496 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712497
12498 HttpRequestInfo request;
12499 request.method = "POST";
bncce36dca22015-04-21 22:11:2312500 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712501 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012502 request.traffic_annotation =
12503 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712504
danakj1fd259a02016-04-16 03:17:0912505 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612506 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3312507
12508 MockRead data_reads[] = {
12509 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
12510 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612511 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3312512 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112513 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712514 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3312515
[email protected]49639fa2011-12-20 23:22:4112516 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3312517
tfarina42834112016-09-22 13:38:2012518 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112519 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3312520
12521 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112522 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3312523
bnc691fda62016-08-12 00:43:1612524 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212525 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3312526
maksim.sisove869bf52016-06-23 17:11:5212527 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3312528
[email protected]dd3aa792013-07-16 19:10:2312529 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3312530}
12531
bncd16676a2016-07-20 16:23:0112532TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1512533 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5212534 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3612535 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4812536 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
12537 base::WriteFile(temp_file, temp_file_content.c_str(),
12538 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1112539 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3612540
danakj1fd259a02016-04-16 03:17:0912541 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912542 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412543 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0712544 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212545 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712546
12547 HttpRequestInfo request;
12548 request.method = "POST";
bncce36dca22015-04-21 22:11:2312549 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712550 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012551 request.traffic_annotation =
12552 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712553
[email protected]999dd8c2013-11-12 06:45:5412554 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0912555 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612556 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3612557
Ryan Sleevib8d7ea02018-05-07 20:01:0112558 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0712559 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3612560
[email protected]49639fa2011-12-20 23:22:4112561 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3612562
tfarina42834112016-09-22 13:38:2012563 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112564 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3612565
12566 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112567 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3612568
[email protected]dd3aa792013-07-16 19:10:2312569 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3612570}
12571
bncd16676a2016-07-20 16:23:0112572TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0312573 class FakeUploadElementReader : public UploadElementReader {
12574 public:
Chris Watkins7a41d3552017-12-01 02:13:2712575 FakeUploadElementReader() = default;
12576 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0312577
Matt Menkecc1d3a902018-02-05 18:27:3312578 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0312579
12580 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3312581 int Init(CompletionOnceCallback callback) override {
12582 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0312583 return ERR_IO_PENDING;
12584 }
avibf0746c2015-12-09 19:53:1412585 uint64_t GetContentLength() const override { return 0; }
12586 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2012587 int Read(IOBuffer* buf,
12588 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3312589 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0312590 return ERR_FAILED;
12591 }
12592
12593 private:
Matt Menkecc1d3a902018-02-05 18:27:3312594 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0312595 };
12596
12597 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0912598 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
12599 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2212600 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0312601
12602 HttpRequestInfo request;
12603 request.method = "POST";
bncce36dca22015-04-21 22:11:2312604 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0312605 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012606 request.traffic_annotation =
12607 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0312608
danakj1fd259a02016-04-16 03:17:0912609 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812610 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912611 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0312612
12613 StaticSocketDataProvider data;
12614 session_deps_.socket_factory->AddSocketDataProvider(&data);
12615
12616 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2012617 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112618 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5512619 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0312620
12621 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3312622 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
12623 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0312624
12625 // Return Init()'s result after the transaction gets destroyed.
12626 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3312627 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0312628}
12629
[email protected]aeefc9e82010-02-19 16:18:2712630// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0112631TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2712632 HttpRequestInfo request;
12633 request.method = "GET";
bncce36dca22015-04-21 22:11:2312634 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012635 request.traffic_annotation =
12636 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2712637
12638 // First transaction will request a resource and receive a Basic challenge
12639 // with realm="first_realm".
12640 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312641 MockWrite(
12642 "GET / HTTP/1.1\r\n"
12643 "Host: www.example.org\r\n"
12644 "Connection: keep-alive\r\n"
12645 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712646 };
12647 MockRead data_reads1[] = {
12648 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12649 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12650 "\r\n"),
12651 };
12652
bnc691fda62016-08-12 00:43:1612653 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2712654 // for first_realm. The server will reject and provide a challenge with
12655 // second_realm.
12656 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312657 MockWrite(
12658 "GET / HTTP/1.1\r\n"
12659 "Host: www.example.org\r\n"
12660 "Connection: keep-alive\r\n"
12661 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
12662 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712663 };
12664 MockRead data_reads2[] = {
12665 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12666 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
12667 "\r\n"),
12668 };
12669
12670 // This again fails, and goes back to first_realm. Make sure that the
12671 // entry is removed from cache.
12672 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2312673 MockWrite(
12674 "GET / HTTP/1.1\r\n"
12675 "Host: www.example.org\r\n"
12676 "Connection: keep-alive\r\n"
12677 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
12678 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712679 };
12680 MockRead data_reads3[] = {
12681 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12682 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12683 "\r\n"),
12684 };
12685
12686 // Try one last time (with the correct password) and get the resource.
12687 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2312688 MockWrite(
12689 "GET / HTTP/1.1\r\n"
12690 "Host: www.example.org\r\n"
12691 "Connection: keep-alive\r\n"
12692 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
12693 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712694 };
12695 MockRead data_reads4[] = {
12696 MockRead("HTTP/1.1 200 OK\r\n"
12697 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5012698 "Content-Length: 5\r\n"
12699 "\r\n"
12700 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2712701 };
12702
Ryan Sleevib8d7ea02018-05-07 20:01:0112703 StaticSocketDataProvider data1(data_reads1, data_writes1);
12704 StaticSocketDataProvider data2(data_reads2, data_writes2);
12705 StaticSocketDataProvider data3(data_reads3, data_writes3);
12706 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0712707 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12708 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12709 session_deps_.socket_factory->AddSocketDataProvider(&data3);
12710 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2712711
[email protected]49639fa2011-12-20 23:22:4112712 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2712713
danakj1fd259a02016-04-16 03:17:0912714 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612715 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012716
[email protected]aeefc9e82010-02-19 16:18:2712717 // Issue the first request with Authorize headers. There should be a
12718 // password prompt for first_realm waiting to be filled in after the
12719 // transaction completes.
tfarina42834112016-09-22 13:38:2012720 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112721 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712722 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112723 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612724 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212725 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812726 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212727 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412728 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312729 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412730 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912731 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712732
12733 // Issue the second request with an incorrect password. There should be a
12734 // password prompt for second_realm waiting to be filled in after the
12735 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4112736 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1612737 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
12738 callback2.callback());
robpercival214763f2016-07-01 23:27:0112739 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712740 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112741 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612742 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212743 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812744 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212745 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412746 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312747 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412748 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912749 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712750
12751 // Issue the third request with another incorrect password. There should be
12752 // a password prompt for first_realm waiting to be filled in. If the password
12753 // prompt is not present, it indicates that the HttpAuthCacheEntry for
12754 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4112755 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1612756 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
12757 callback3.callback());
robpercival214763f2016-07-01 23:27:0112758 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712759 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0112760 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612761 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212762 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812763 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212764 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412765 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312766 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412767 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912768 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712769
12770 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4112771 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1612772 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
12773 callback4.callback());
robpercival214763f2016-07-01 23:27:0112774 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712775 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0112776 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612777 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212778 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812779 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2712780}
12781
Bence Béky230ac612017-08-30 19:17:0812782// Regression test for https://crbug.com/754395.
12783TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
12784 MockRead data_reads[] = {
12785 MockRead("HTTP/1.1 200 OK\r\n"),
12786 MockRead(kAlternativeServiceHttpHeader),
12787 MockRead("\r\n"),
12788 MockRead("hello world"),
12789 MockRead(SYNCHRONOUS, OK),
12790 };
12791
12792 HttpRequestInfo request;
12793 request.method = "GET";
12794 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012795 request.traffic_annotation =
12796 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0812797
Ryan Sleevib8d7ea02018-05-07 20:01:0112798 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0812799 session_deps_.socket_factory->AddSocketDataProvider(&data);
12800
12801 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912802 ssl.ssl_info.cert =
12803 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12804 ASSERT_TRUE(ssl.ssl_info.cert);
12805 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0812806 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12807
12808 TestCompletionCallback callback;
12809
12810 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12811 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12812
12813 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12814 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12815
12816 url::SchemeHostPort test_server(request.url);
12817 HttpServerProperties* http_server_properties =
12818 session->http_server_properties();
12819 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912820 http_server_properties
12821 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12822 .empty());
Bence Béky230ac612017-08-30 19:17:0812823
12824 EXPECT_THAT(callback.WaitForResult(), IsOk());
12825
12826 const HttpResponseInfo* response = trans.GetResponseInfo();
12827 ASSERT_TRUE(response);
12828 ASSERT_TRUE(response->headers);
12829 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12830 EXPECT_FALSE(response->was_fetched_via_spdy);
12831 EXPECT_FALSE(response->was_alpn_negotiated);
12832
12833 std::string response_data;
12834 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12835 EXPECT_EQ("hello world", response_data);
12836
12837 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912838 http_server_properties
12839 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12840 .empty());
Bence Béky230ac612017-08-30 19:17:0812841}
12842
bncd16676a2016-07-20 16:23:0112843TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5212844 MockRead data_reads[] = {
12845 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312846 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212847 MockRead("\r\n"),
12848 MockRead("hello world"),
12849 MockRead(SYNCHRONOUS, OK),
12850 };
12851
12852 HttpRequestInfo request;
12853 request.method = "GET";
bncb26024382016-06-29 02:39:4512854 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012855 request.traffic_annotation =
12856 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212857
Ryan Sleevib8d7ea02018-05-07 20:01:0112858 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212859 session_deps_.socket_factory->AddSocketDataProvider(&data);
12860
bncb26024382016-06-29 02:39:4512861 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912862 ssl.ssl_info.cert =
12863 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12864 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512865 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12866
bncc958faa2015-07-31 18:14:5212867 TestCompletionCallback callback;
12868
danakj1fd259a02016-04-16 03:17:0912869 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612870 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212871
tfarina42834112016-09-22 13:38:2012872 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112873 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212874
bncb26024382016-06-29 02:39:4512875 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012876 HttpServerProperties* http_server_properties =
12877 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412878 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912879 http_server_properties
12880 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12881 .empty());
bncc958faa2015-07-31 18:14:5212882
robpercival214763f2016-07-01 23:27:0112883 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212884
bnc691fda62016-08-12 00:43:1612885 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212886 ASSERT_TRUE(response);
12887 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212888 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12889 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212890 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212891
12892 std::string response_data;
bnc691fda62016-08-12 00:43:1612893 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212894 EXPECT_EQ("hello world", response_data);
12895
zhongyic4de03032017-05-19 04:07:3412896 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912897 http_server_properties->GetAlternativeServiceInfos(test_server,
12898 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412899 ASSERT_EQ(1u, alternative_service_info_vector.size());
12900 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12901 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412902 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212903}
12904
Matt Menke3233d8f22019-08-20 21:01:4912905TEST_F(HttpNetworkTransactionTest,
12906 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
12907 base::test::ScopedFeatureList feature_list;
12908 feature_list.InitWithFeatures(
12909 // enabled_features
12910 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
12911 // Need to partition connections by NetworkIsolationKey for
12912 // SpdySessionKeys to include NetworkIsolationKeys.
12913 features::kPartitionConnectionsByNetworkIsolationKey},
12914 // disabled_features
12915 {});
12916 // Since HttpServerProperties caches the feature value, have to create a new
12917 // one.
12918 session_deps_.http_server_properties =
12919 std::make_unique<HttpServerProperties>();
12920
12921 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
12922 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
12923 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
12924 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
12925
12926 MockRead data_reads[] = {
12927 MockRead("HTTP/1.1 200 OK\r\n"),
12928 MockRead(kAlternativeServiceHttpHeader),
12929 MockRead("\r\n"),
12930 MockRead("hello world"),
12931 MockRead(SYNCHRONOUS, OK),
12932 };
12933
12934 HttpRequestInfo request;
12935 request.method = "GET";
12936 request.url = GURL("https://www.example.org/");
12937 request.traffic_annotation =
12938 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12939 request.network_isolation_key = kNetworkIsolationKey1;
12940
12941 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12942 session_deps_.socket_factory->AddSocketDataProvider(&data);
12943
12944 SSLSocketDataProvider ssl(ASYNC, OK);
12945 ssl.ssl_info.cert =
12946 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12947 ASSERT_TRUE(ssl.ssl_info.cert);
12948 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12949
12950 TestCompletionCallback callback;
12951
12952 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12953 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12954
12955 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12956 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12957
12958 url::SchemeHostPort test_server(request.url);
12959 HttpServerProperties* http_server_properties =
12960 session->http_server_properties();
12961 EXPECT_TRUE(
12962 http_server_properties
12963 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
12964 .empty());
12965
12966 EXPECT_THAT(callback.WaitForResult(), IsOk());
12967
12968 const HttpResponseInfo* response = trans.GetResponseInfo();
12969 ASSERT_TRUE(response);
12970 ASSERT_TRUE(response->headers);
12971 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12972 EXPECT_FALSE(response->was_fetched_via_spdy);
12973 EXPECT_FALSE(response->was_alpn_negotiated);
12974
12975 std::string response_data;
12976 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12977 EXPECT_EQ("hello world", response_data);
12978
12979 AlternativeServiceInfoVector alternative_service_info_vector =
12980 http_server_properties->GetAlternativeServiceInfos(test_server,
12981 kNetworkIsolationKey1);
12982 ASSERT_EQ(1u, alternative_service_info_vector.size());
12983 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12984 EXPECT_EQ(alternative_service,
12985 alternative_service_info_vector[0].alternative_service());
12986
12987 // Make sure the alternative service information is only associated with
12988 // kNetworkIsolationKey1.
12989 EXPECT_TRUE(
12990 http_server_properties
12991 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12992 .empty());
12993 EXPECT_TRUE(
12994 http_server_properties
12995 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
12996 .empty());
12997}
12998
bnce3dd56f2016-06-01 10:37:1112999// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0113000TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113001 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1113002 MockRead data_reads[] = {
13003 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313004 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1113005 MockRead("\r\n"),
13006 MockRead("hello world"),
13007 MockRead(SYNCHRONOUS, OK),
13008 };
13009
13010 HttpRequestInfo request;
13011 request.method = "GET";
13012 request.url = GURL("http://www.example.org/");
13013 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013014 request.traffic_annotation =
13015 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113016
Ryan Sleevib8d7ea02018-05-07 20:01:0113017 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113018 session_deps_.socket_factory->AddSocketDataProvider(&data);
13019
13020 TestCompletionCallback callback;
13021
13022 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613023 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113024
13025 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013026 HttpServerProperties* http_server_properties =
13027 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413028 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913029 http_server_properties
13030 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13031 .empty());
bnce3dd56f2016-06-01 10:37:1113032
tfarina42834112016-09-22 13:38:2013033 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113034 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13035 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1113036
bnc691fda62016-08-12 00:43:1613037 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1113038 ASSERT_TRUE(response);
13039 ASSERT_TRUE(response->headers);
13040 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13041 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213042 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1113043
13044 std::string response_data;
bnc691fda62016-08-12 00:43:1613045 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1113046 EXPECT_EQ("hello world", response_data);
13047
zhongyic4de03032017-05-19 04:07:3413048 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913049 http_server_properties
13050 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13051 .empty());
bnce3dd56f2016-06-01 10:37:1113052}
13053
bnca86731e2017-04-17 12:31:2813054// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2513055// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0113056TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2513057 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2813058 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4513059
bnc8bef8da22016-05-30 01:28:2513060 HttpRequestInfo request;
13061 request.method = "GET";
bncb26024382016-06-29 02:39:4513062 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2513063 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013064 request.traffic_annotation =
13065 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2513066
13067 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13068 StaticSocketDataProvider first_data;
13069 first_data.set_connect_data(mock_connect);
13070 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513071 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613072 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513073 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2513074
13075 MockRead data_reads[] = {
13076 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13077 MockRead(ASYNC, OK),
13078 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113079 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2513080 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13081
13082 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13083
bnc525e175a2016-06-20 12:36:4013084 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2513085 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113086 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
13087 444);
bnc8bef8da22016-05-30 01:28:2513088 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113089 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713090 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13091 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2513092
bnc691fda62016-08-12 00:43:1613093 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2513094 TestCompletionCallback callback;
13095
tfarina42834112016-09-22 13:38:2013096 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2513097 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113098 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2513099}
13100
bnce3dd56f2016-06-01 10:37:1113101// Regression test for https://crbug.com/615497:
13102// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0113103TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113104 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1113105 HttpRequestInfo request;
13106 request.method = "GET";
13107 request.url = GURL("http://www.example.org/");
13108 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013109 request.traffic_annotation =
13110 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113111
13112 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13113 StaticSocketDataProvider first_data;
13114 first_data.set_connect_data(mock_connect);
13115 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
13116
13117 MockRead data_reads[] = {
13118 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13119 MockRead(ASYNC, OK),
13120 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113121 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113122 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13123
13124 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13125
bnc525e175a2016-06-20 12:36:4013126 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1113127 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113128 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1113129 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113130 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713131 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13132 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1113133
bnc691fda62016-08-12 00:43:1613134 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113135 TestCompletionCallback callback;
13136
tfarina42834112016-09-22 13:38:2013137 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1113138 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113139 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1113140}
13141
bncd16676a2016-07-20 16:23:0113142TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0813143 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0913144 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013145 HttpServerProperties* http_server_properties =
13146 session->http_server_properties();
bncb26024382016-06-29 02:39:4513147 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2113148 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0813149 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113150 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713151 test_server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4213152 session->params().quic_params.supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4913153 EXPECT_EQ(1u,
13154 http_server_properties
13155 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13156 .size());
bnc4f575852015-10-14 18:35:0813157
13158 // Send a clear header.
13159 MockRead data_reads[] = {
13160 MockRead("HTTP/1.1 200 OK\r\n"),
13161 MockRead("Alt-Svc: clear\r\n"),
13162 MockRead("\r\n"),
13163 MockRead("hello world"),
13164 MockRead(SYNCHRONOUS, OK),
13165 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113166 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0813167 session_deps_.socket_factory->AddSocketDataProvider(&data);
13168
bncb26024382016-06-29 02:39:4513169 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913170 ssl.ssl_info.cert =
13171 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13172 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513173 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13174
bnc4f575852015-10-14 18:35:0813175 HttpRequestInfo request;
13176 request.method = "GET";
bncb26024382016-06-29 02:39:4513177 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013178 request.traffic_annotation =
13179 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0813180
13181 TestCompletionCallback callback;
13182
bnc691fda62016-08-12 00:43:1613183 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0813184
tfarina42834112016-09-22 13:38:2013185 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113186 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0813187
bnc691fda62016-08-12 00:43:1613188 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213189 ASSERT_TRUE(response);
13190 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0813191 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13192 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213193 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0813194
13195 std::string response_data;
bnc691fda62016-08-12 00:43:1613196 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0813197 EXPECT_EQ("hello world", response_data);
13198
zhongyic4de03032017-05-19 04:07:3413199 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913200 http_server_properties
13201 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13202 .empty());
bnc4f575852015-10-14 18:35:0813203}
13204
bncd16676a2016-07-20 16:23:0113205TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5213206 MockRead data_reads[] = {
13207 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313208 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
13209 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5213210 MockRead("hello world"),
13211 MockRead(SYNCHRONOUS, OK),
13212 };
13213
13214 HttpRequestInfo request;
13215 request.method = "GET";
bncb26024382016-06-29 02:39:4513216 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013217 request.traffic_annotation =
13218 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213219
Ryan Sleevib8d7ea02018-05-07 20:01:0113220 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213221 session_deps_.socket_factory->AddSocketDataProvider(&data);
13222
bncb26024382016-06-29 02:39:4513223 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913224 ssl.ssl_info.cert =
13225 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13226 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513227 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13228
bncc958faa2015-07-31 18:14:5213229 TestCompletionCallback callback;
13230
danakj1fd259a02016-04-16 03:17:0913231 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613232 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213233
tfarina42834112016-09-22 13:38:2013234 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113235 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213236
bncb26024382016-06-29 02:39:4513237 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4013238 HttpServerProperties* http_server_properties =
13239 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413240 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913241 http_server_properties
13242 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13243 .empty());
bncc958faa2015-07-31 18:14:5213244
robpercival214763f2016-07-01 23:27:0113245 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213246
bnc691fda62016-08-12 00:43:1613247 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213248 ASSERT_TRUE(response);
13249 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213250 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13251 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213252 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213253
13254 std::string response_data;
bnc691fda62016-08-12 00:43:1613255 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213256 EXPECT_EQ("hello world", response_data);
13257
zhongyic4de03032017-05-19 04:07:3413258 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913259 http_server_properties->GetAlternativeServiceInfos(test_server,
13260 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413261 ASSERT_EQ(2u, alternative_service_info_vector.size());
13262
13263 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
13264 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413265 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3413266 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
13267 1234);
13268 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5413269 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5213270}
13271
bncd16676a2016-07-20 16:23:0113272TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613273 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213274 HostPortPair alternative("alternative.example.org", 443);
13275 std::string origin_url = "https://origin.example.org:443";
13276 std::string alternative_url = "https://alternative.example.org:443";
13277
13278 // Negotiate HTTP/1.1 with alternative.example.org.
13279 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613280 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213281 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13282
13283 // HTTP/1.1 data for request.
13284 MockWrite http_writes[] = {
13285 MockWrite("GET / HTTP/1.1\r\n"
13286 "Host: alternative.example.org\r\n"
13287 "Connection: keep-alive\r\n\r\n"),
13288 };
13289
13290 MockRead http_reads[] = {
13291 MockRead("HTTP/1.1 200 OK\r\n"
13292 "Content-Type: text/html; charset=iso-8859-1\r\n"
13293 "Content-Length: 40\r\n\r\n"
13294 "first HTTP/1.1 response from alternative"),
13295 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113296 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213297 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13298
13299 StaticSocketDataProvider data_refused;
13300 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13301 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13302
zhongyi3d4a55e72016-04-22 20:36:4613303 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0913304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013305 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213306 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113307 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0213308 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113309 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713310 server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4213311 HttpNetworkSession::Params().quic_params.supported_versions);
zhongyi48704c182015-12-07 07:52:0213312 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513313 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
13314 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0213315
zhongyi48704c182015-12-07 07:52:0213316 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613317 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213318 request.method = "GET";
13319 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1013320 request.traffic_annotation =
13321 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13322
zhongyi48704c182015-12-07 07:52:0213323 TestCompletionCallback callback;
13324 NetErrorDetails details;
13325 EXPECT_FALSE(details.quic_broken);
13326
tfarina42834112016-09-22 13:38:2013327 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613328 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213329 EXPECT_TRUE(details.quic_broken);
13330}
13331
bncd16676a2016-07-20 16:23:0113332TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613333 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213334 HostPortPair alternative1("alternative1.example.org", 443);
13335 HostPortPair alternative2("alternative2.example.org", 443);
13336 std::string origin_url = "https://origin.example.org:443";
13337 std::string alternative_url1 = "https://alternative1.example.org:443";
13338 std::string alternative_url2 = "https://alternative2.example.org:443";
13339
13340 // Negotiate HTTP/1.1 with alternative1.example.org.
13341 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613342 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213343 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13344
13345 // HTTP/1.1 data for request.
13346 MockWrite http_writes[] = {
13347 MockWrite("GET / HTTP/1.1\r\n"
13348 "Host: alternative1.example.org\r\n"
13349 "Connection: keep-alive\r\n\r\n"),
13350 };
13351
13352 MockRead http_reads[] = {
13353 MockRead("HTTP/1.1 200 OK\r\n"
13354 "Content-Type: text/html; charset=iso-8859-1\r\n"
13355 "Content-Length: 40\r\n\r\n"
13356 "first HTTP/1.1 response from alternative1"),
13357 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113358 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213359 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13360
13361 StaticSocketDataProvider data_refused;
13362 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13363 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13364
danakj1fd259a02016-04-16 03:17:0913365 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013366 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213367 session->http_server_properties();
13368
zhongyi3d4a55e72016-04-22 20:36:4613369 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0213370 AlternativeServiceInfoVector alternative_service_info_vector;
13371 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
13372
bnc3472afd2016-11-17 15:27:2113373 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2113374 alternative_service_info_vector.push_back(
13375 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13376 alternative_service1, expiration,
Nick Harper72ade192019-07-17 03:30:4213377 session->params().quic_params.supported_versions));
bnc3472afd2016-11-17 15:27:2113378 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2113379 alternative_service_info_vector.push_back(
13380 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13381 alternative_service2, expiration,
Nick Harper72ade192019-07-17 03:30:4213382 session->params().quic_params.supported_versions));
zhongyi48704c182015-12-07 07:52:0213383
13384 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4913385 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0213386
13387 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513388 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
13389 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4913390 EXPECT_EQ(2u, http_server_properties
13391 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
13392 .size());
zhongyi48704c182015-12-07 07:52:0213393
zhongyi48704c182015-12-07 07:52:0213394 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613395 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213396 request.method = "GET";
13397 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1013398 request.traffic_annotation =
13399 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13400
zhongyi48704c182015-12-07 07:52:0213401 TestCompletionCallback callback;
13402 NetErrorDetails details;
13403 EXPECT_FALSE(details.quic_broken);
13404
tfarina42834112016-09-22 13:38:2013405 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613406 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213407 EXPECT_FALSE(details.quic_broken);
13408}
13409
bncd16676a2016-07-20 16:23:0113410TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4213411 HttpRequestInfo request;
13412 request.method = "GET";
bncb26024382016-06-29 02:39:4513413 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013414 request.traffic_annotation =
13415 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4213416
[email protected]d973e99a2012-02-17 21:02:3613417 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4213418 StaticSocketDataProvider first_data;
13419 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713420 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513421 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613422 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4213424
13425 MockRead data_reads[] = {
13426 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13427 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613428 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4213429 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113430 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713431 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4213432
danakj1fd259a02016-04-16 03:17:0913433 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4213434
bnc525e175a2016-06-20 12:36:4013435 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313436 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4613437 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1113438 // Port must be < 1024, or the header will be ignored (since initial port was
13439 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2113440 // Port is ignored by MockConnect anyway.
13441 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13442 666);
bnc7dc7e1b42015-07-28 14:43:1213443 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113444 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713445 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4213446
bnc691fda62016-08-12 00:43:1613447 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113448 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4213449
tfarina42834112016-09-22 13:38:2013450 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113451 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13452 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4213453
bnc691fda62016-08-12 00:43:1613454 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213455 ASSERT_TRUE(response);
13456 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4213457 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13458
13459 std::string response_data;
bnc691fda62016-08-12 00:43:1613460 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4213461 EXPECT_EQ("hello world", response_data);
13462
zhongyic4de03032017-05-19 04:07:3413463 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913464 http_server_properties->GetAlternativeServiceInfos(server,
13465 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413466 ASSERT_EQ(1u, alternative_service_info_vector.size());
13467 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413468 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0513469 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
13470 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4213471}
13472
bnc55ff9da2015-08-19 18:42:3513473// Ensure that we are not allowed to redirect traffic via an alternate protocol
13474// to an unrestricted (port >= 1024) when the original traffic was on a
13475// restricted port (port < 1024). Ensure that we can redirect in all other
13476// cases.
bncd16676a2016-07-20 16:23:0113477TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1113478 HttpRequestInfo restricted_port_request;
13479 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513480 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113481 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013482 restricted_port_request.traffic_annotation =
13483 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113484
[email protected]d973e99a2012-02-17 21:02:3613485 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113486 StaticSocketDataProvider first_data;
13487 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713488 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113489
13490 MockRead data_reads[] = {
13491 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13492 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613493 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113494 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113495 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713496 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513497 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613498 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513499 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113500
danakj1fd259a02016-04-16 03:17:0913501 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113502
bnc525e175a2016-06-20 12:36:4013503 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313504 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113505 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113506 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13507 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213508 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113509 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713510 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13511 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113512
bnc691fda62016-08-12 00:43:1613513 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113514 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113515
tfarina42834112016-09-22 13:38:2013516 int rv = trans.Start(&restricted_port_request, callback.callback(),
13517 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113518 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113519 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0113520 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1913521}
[email protected]3912662a32011-10-04 00:51:1113522
bnc55ff9da2015-08-19 18:42:3513523// Ensure that we are allowed to redirect traffic via an alternate protocol to
13524// an unrestricted (port >= 1024) when the original traffic was on a restricted
13525// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0113526TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0713527 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1913528
13529 HttpRequestInfo restricted_port_request;
13530 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513531 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1913532 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013533 restricted_port_request.traffic_annotation =
13534 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1913535
13536 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13537 StaticSocketDataProvider first_data;
13538 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713539 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1913540
13541 MockRead data_reads[] = {
13542 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13543 MockRead("hello world"),
13544 MockRead(ASYNC, OK),
13545 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113546 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713547 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513548 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613549 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1913551
danakj1fd259a02016-04-16 03:17:0913552 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1913553
bnc525e175a2016-06-20 12:36:4013554 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1913555 session->http_server_properties();
13556 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113557 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13558 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213559 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113560 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713561 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13562 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1913563
bnc691fda62016-08-12 00:43:1613564 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1913565 TestCompletionCallback callback;
13566
tfarina42834112016-09-22 13:38:2013567 EXPECT_EQ(ERR_IO_PENDING,
13568 trans.Start(&restricted_port_request, callback.callback(),
13569 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1913570 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0113571 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113572}
13573
bnc55ff9da2015-08-19 18:42:3513574// Ensure that we are not allowed to redirect traffic via an alternate protocol
13575// to an unrestricted (port >= 1024) when the original traffic was on a
13576// restricted port (port < 1024). Ensure that we can redirect in all other
13577// cases.
bncd16676a2016-07-20 16:23:0113578TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1113579 HttpRequestInfo restricted_port_request;
13580 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513581 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113582 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013583 restricted_port_request.traffic_annotation =
13584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113585
[email protected]d973e99a2012-02-17 21:02:3613586 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113587 StaticSocketDataProvider first_data;
13588 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713589 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113590
13591 MockRead data_reads[] = {
13592 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13593 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613594 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113595 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113596 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713597 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113598
bncb26024382016-06-29 02:39:4513599 SSLSocketDataProvider ssl(ASYNC, OK);
13600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13601
danakj1fd259a02016-04-16 03:17:0913602 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113603
bnc525e175a2016-06-20 12:36:4013604 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313605 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113606 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113607 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13608 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213609 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113610 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713611 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13612 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113613
bnc691fda62016-08-12 00:43:1613614 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113615 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113616
tfarina42834112016-09-22 13:38:2013617 int rv = trans.Start(&restricted_port_request, callback.callback(),
13618 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113619 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113620 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113621 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113622}
13623
bnc55ff9da2015-08-19 18:42:3513624// Ensure that we are not allowed to redirect traffic via an alternate protocol
13625// to an unrestricted (port >= 1024) when the original traffic was on a
13626// restricted port (port < 1024). Ensure that we can redirect in all other
13627// cases.
bncd16676a2016-07-20 16:23:0113628TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1113629 HttpRequestInfo unrestricted_port_request;
13630 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513631 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113632 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013633 unrestricted_port_request.traffic_annotation =
13634 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113635
[email protected]d973e99a2012-02-17 21:02:3613636 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113637 StaticSocketDataProvider first_data;
13638 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713639 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113640
13641 MockRead data_reads[] = {
13642 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13643 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613644 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113645 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113646 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713647 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513648 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613649 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513650 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113651
danakj1fd259a02016-04-16 03:17:0913652 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113653
bnc525e175a2016-06-20 12:36:4013654 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313655 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113656 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2113657 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13658 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213659 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113660 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713661 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13662 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113663
bnc691fda62016-08-12 00:43:1613664 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113665 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113666
bnc691fda62016-08-12 00:43:1613667 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013668 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113669 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113670 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0113671 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113672}
13673
bnc55ff9da2015-08-19 18:42:3513674// Ensure that we are not allowed to redirect traffic via an alternate protocol
13675// to an unrestricted (port >= 1024) when the original traffic was on a
13676// restricted port (port < 1024). Ensure that we can redirect in all other
13677// cases.
bncd16676a2016-07-20 16:23:0113678TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1113679 HttpRequestInfo unrestricted_port_request;
13680 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513681 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113682 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013683 unrestricted_port_request.traffic_annotation =
13684 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113685
[email protected]d973e99a2012-02-17 21:02:3613686 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113687 StaticSocketDataProvider first_data;
13688 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713689 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113690
13691 MockRead data_reads[] = {
13692 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13693 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613694 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113695 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113696 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713697 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113698
bncb26024382016-06-29 02:39:4513699 SSLSocketDataProvider ssl(ASYNC, OK);
13700 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13701
danakj1fd259a02016-04-16 03:17:0913702 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113703
bnc525e175a2016-06-20 12:36:4013704 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313705 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2213706 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2113707 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13708 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213709 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113710 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713711 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13712 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113713
bnc691fda62016-08-12 00:43:1613714 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113715 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113716
bnc691fda62016-08-12 00:43:1613717 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013718 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113719 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113720 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0113721 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113722}
13723
bnc55ff9da2015-08-19 18:42:3513724// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2113725// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
13726// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0113727TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0213728 HttpRequestInfo request;
13729 request.method = "GET";
bncce36dca22015-04-21 22:11:2313730 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013731 request.traffic_annotation =
13732 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0213733
13734 // The alternate protocol request will error out before we attempt to connect,
13735 // so only the standard HTTP request will try to connect.
13736 MockRead data_reads[] = {
13737 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13738 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613739 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0213740 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113741 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713742 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0213743
danakj1fd259a02016-04-16 03:17:0913744 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0213745
bnc525e175a2016-06-20 12:36:4013746 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0213747 session->http_server_properties();
13748 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2113749 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13750 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1213751 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113752 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713753 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13754 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0213755
bnc691fda62016-08-12 00:43:1613756 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0213757 TestCompletionCallback callback;
13758
tfarina42834112016-09-22 13:38:2013759 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113760 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0213761 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0113762 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213763
bnc691fda62016-08-12 00:43:1613764 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213765 ASSERT_TRUE(response);
13766 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0213767 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13768
13769 std::string response_data;
bnc691fda62016-08-12 00:43:1613770 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213771 EXPECT_EQ("hello world", response_data);
13772}
13773
bncd16676a2016-07-20 16:23:0113774TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5413775 HttpRequestInfo request;
13776 request.method = "GET";
bncb26024382016-06-29 02:39:4513777 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013778 request.traffic_annotation =
13779 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413780
13781 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213782 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313783 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213784 MockRead("\r\n"),
13785 MockRead("hello world"),
13786 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13787 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5413788
Ryan Sleevib8d7ea02018-05-07 20:01:0113789 StaticSocketDataProvider first_transaction(data_reads,
13790 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713791 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513792 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613793 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513794 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413795
bnc032658ba2016-09-26 18:17:1513796 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413797
Ryan Hamilton0239aac2018-05-19 00:03:1313798 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513799 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113800 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413801
Raul Tambre94493c652019-03-11 17:18:3513802 spdy::SpdySerializedFrame resp(
13803 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313804 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413805 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113806 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413807 };
13808
Ryan Sleevib8d7ea02018-05-07 20:01:0113809 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713810 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413811
[email protected]d973e99a2012-02-17 21:02:3613812 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113813 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513814 hanging_non_alternate_protocol_socket.set_connect_data(
13815 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713816 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513817 &hanging_non_alternate_protocol_socket);
13818
[email protected]49639fa2011-12-20 23:22:4113819 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413820
danakj1fd259a02016-04-16 03:17:0913821 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813822 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913823 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413824
tfarina42834112016-09-22 13:38:2013825 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113826 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13827 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413828
13829 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213830 ASSERT_TRUE(response);
13831 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413832 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13833
13834 std::string response_data;
robpercival214763f2016-07-01 23:27:0113835 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413836 EXPECT_EQ("hello world", response_data);
13837
bnc87dcefc2017-05-25 12:47:5813838 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913839 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413840
tfarina42834112016-09-22 13:38:2013841 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113842 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13843 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413844
13845 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213846 ASSERT_TRUE(response);
13847 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213848 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313849 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213850 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413851
robpercival214763f2016-07-01 23:27:0113852 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413853 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5413854}
13855
bncd16676a2016-07-20 16:23:0113856TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5513857 HttpRequestInfo request;
13858 request.method = "GET";
bncb26024382016-06-29 02:39:4513859 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013860 request.traffic_annotation =
13861 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513862
bncb26024382016-06-29 02:39:4513863 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5513864 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213865 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313866 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213867 MockRead("\r\n"),
13868 MockRead("hello world"),
13869 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13870 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513871 };
13872
Ryan Sleevib8d7ea02018-05-07 20:01:0113873 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4513874 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5513875
bncb26024382016-06-29 02:39:4513876 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913877 ssl_http11.ssl_info.cert =
13878 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13879 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4513880 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
13881
13882 // Second transaction starts an alternative and a non-alternative Job.
13883 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3613884 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113885 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1813886 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1813887 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
13888
Ryan Sleevib8d7ea02018-05-07 20:01:0113889 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1813890 hanging_socket2.set_connect_data(never_finishing_connect);
13891 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5513892
bncb26024382016-06-29 02:39:4513893 // Third transaction starts an alternative and a non-alternative job.
13894 // The non-alternative job hangs, but the alternative one succeeds.
13895 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1313896 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4513897 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1313898 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4513899 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5513900 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113901 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5513902 };
Raul Tambre94493c652019-03-11 17:18:3513903 spdy::SpdySerializedFrame resp1(
13904 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313905 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3513906 spdy::SpdySerializedFrame resp2(
13907 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1313908 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5513909 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113910 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
13911 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1313912 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5513913 };
13914
Ryan Sleevib8d7ea02018-05-07 20:01:0113915 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713916 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5513917
bnc032658ba2016-09-26 18:17:1513918 AddSSLSocketData();
bncb26024382016-06-29 02:39:4513919
Ryan Sleevib8d7ea02018-05-07 20:01:0113920 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1813921 hanging_socket3.set_connect_data(never_finishing_connect);
13922 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5513923
danakj1fd259a02016-04-16 03:17:0913924 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4113925 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5013926 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513927
tfarina42834112016-09-22 13:38:2013928 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113929 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13930 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513931
13932 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5213933 ASSERT_TRUE(response);
13934 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513935 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13936
13937 std::string response_data;
robpercival214763f2016-07-01 23:27:0113938 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513939 EXPECT_EQ("hello world", response_data);
13940
[email protected]49639fa2011-12-20 23:22:4113941 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5013942 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013943 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113944 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513945
[email protected]49639fa2011-12-20 23:22:4113946 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5013947 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013948 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113949 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513950
robpercival214763f2016-07-01 23:27:0113951 EXPECT_THAT(callback2.WaitForResult(), IsOk());
13952 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513953
13954 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5213955 ASSERT_TRUE(response);
13956 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213957 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513958 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213959 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113960 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513961 EXPECT_EQ("hello!", response_data);
13962
13963 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5213964 ASSERT_TRUE(response);
13965 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213966 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513967 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213968 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113969 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513970 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5513971}
13972
bncd16676a2016-07-20 16:23:0113973TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5313974 session_deps_.host_resolver->set_synchronous_mode(true);
13975
[email protected]2d6728692011-03-12 01:39:5513976 HttpRequestInfo request;
13977 request.method = "GET";
bncb26024382016-06-29 02:39:4513978 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013979 request.traffic_annotation =
13980 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513981
13982 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213983 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313984 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213985 MockRead("\r\n"),
13986 MockRead("hello world"),
13987 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13988 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513989 };
13990
Ryan Sleevib8d7ea02018-05-07 20:01:0113991 StaticSocketDataProvider first_transaction(data_reads,
13992 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713993 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513994
[email protected]8ddf8322012-02-23 18:08:0613995 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913996 ssl.ssl_info.cert =
13997 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13998 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0713999 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514000
[email protected]d973e99a2012-02-17 21:02:3614001 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114002 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514003 hanging_alternate_protocol_socket.set_connect_data(
14004 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714005 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514006 &hanging_alternate_protocol_socket);
14007
bncb26024382016-06-29 02:39:4514008 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0114009 StaticSocketDataProvider second_transaction(data_reads,
14010 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1814011 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4514012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514013
[email protected]49639fa2011-12-20 23:22:4114014 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5514015
danakj1fd259a02016-04-16 03:17:0914016 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814017 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914018 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514019
tfarina42834112016-09-22 13:38:2014020 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114021 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14022 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514023
14024 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214025 ASSERT_TRUE(response);
14026 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514027 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14028
14029 std::string response_data;
robpercival214763f2016-07-01 23:27:0114030 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514031 EXPECT_EQ("hello world", response_data);
14032
bnc87dcefc2017-05-25 12:47:5814033 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914034 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514035
tfarina42834112016-09-22 13:38:2014036 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114037 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14038 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514039
14040 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214041 ASSERT_TRUE(response);
14042 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514043 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14044 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214045 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5514046
robpercival214763f2016-07-01 23:27:0114047 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514048 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5514049}
14050
bnc2e884782016-08-11 19:45:1914051// Test that proxy is resolved using the origin url,
14052// regardless of the alternative server.
14053TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
14054 // Configure proxy to bypass www.example.org, which is the origin URL.
14055 ProxyConfig proxy_config;
14056 proxy_config.proxy_rules().ParseFromString("myproxy:70");
14057 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4914058 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
14059 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1914060
14061 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1914062 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1914063 &capturing_proxy_resolver);
14064
14065 TestNetLog net_log;
14066
Bence Béky53a5aef2018-03-29 21:54:1214067 session_deps_.proxy_resolution_service =
14068 std::make_unique<ProxyResolutionService>(
14069 std::move(proxy_config_service), std::move(proxy_resolver_factory),
14070 &net_log);
bnc2e884782016-08-11 19:45:1914071
14072 session_deps_.net_log = &net_log;
14073
14074 // Configure alternative service with a hostname that is not bypassed by the
14075 // proxy.
14076 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14077 HttpServerProperties* http_server_properties =
14078 session->http_server_properties();
14079 url::SchemeHostPort server("https", "www.example.org", 443);
14080 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2114081 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1914082 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114083 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714084 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1914085
14086 // Non-alternative job should hang.
14087 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114088 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1914089 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
14090 session_deps_.socket_factory->AddSocketDataProvider(
14091 &hanging_alternate_protocol_socket);
14092
bnc032658ba2016-09-26 18:17:1514093 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1914094
14095 HttpRequestInfo request;
14096 request.method = "GET";
14097 request.url = GURL("https://www.example.org/");
14098 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1014099 request.traffic_annotation =
14100 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1914101
Ryan Hamilton0239aac2018-05-19 00:03:1314102 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1914103 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
14104
14105 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
14106
Ryan Hamilton0239aac2018-05-19 00:03:1314107 spdy::SpdySerializedFrame resp(
14108 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
14109 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1914110 MockRead spdy_reads[] = {
14111 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
14112 };
14113
Ryan Sleevib8d7ea02018-05-07 20:01:0114114 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1914115 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
14116
14117 TestCompletionCallback callback;
14118
14119 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14120
tfarina42834112016-09-22 13:38:2014121 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1914122 EXPECT_THAT(callback.GetResult(rv), IsOk());
14123
14124 const HttpResponseInfo* response = trans.GetResponseInfo();
14125 ASSERT_TRUE(response);
14126 ASSERT_TRUE(response->headers);
14127 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
14128 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214129 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1914130
14131 std::string response_data;
14132 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
14133 EXPECT_EQ("hello!", response_data);
14134
14135 // Origin host bypasses proxy, no resolution should have happened.
14136 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
14137}
14138
bncd16676a2016-07-20 16:23:0114139TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1114140 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4214141 proxy_config.set_auto_detect(true);
14142 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1114143
sammc5dd160c2015-04-02 02:43:1314144 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4914145 session_deps_.proxy_resolution_service =
14146 std::make_unique<ProxyResolutionService>(
14147 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
14148 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
14149 std::make_unique<CapturingProxyResolverFactory>(
14150 &capturing_proxy_resolver),
14151 nullptr);
vishal.b62985ca92015-04-17 08:45:5114152 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0714153 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1114154
14155 HttpRequestInfo request;
14156 request.method = "GET";
bncb26024382016-06-29 02:39:4514157 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014158 request.traffic_annotation =
14159 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1114160
14161 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214162 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314163 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214164 MockRead("\r\n"),
14165 MockRead("hello world"),
14166 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14167 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1114168 };
14169
Ryan Sleevib8d7ea02018-05-07 20:01:0114170 StaticSocketDataProvider first_transaction(data_reads,
14171 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714172 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514173 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614174 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514175 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1114176
bnc032658ba2016-09-26 18:17:1514177 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1114178
Ryan Hamilton0239aac2018-05-19 00:03:1314179 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514180 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1114181 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1314182 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2514183 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14184 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1314185 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4114186 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1114187 };
14188
[email protected]d911f1b2010-05-05 22:39:4214189 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
14190
Raul Tambre94493c652019-03-11 17:18:3514191 spdy::SpdySerializedFrame resp(
14192 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314193 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1114194 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114195 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
14196 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1114197 };
14198
Ryan Sleevib8d7ea02018-05-07 20:01:0114199 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714200 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1114201
[email protected]d973e99a2012-02-17 21:02:3614202 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114203 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514204 hanging_non_alternate_protocol_socket.set_connect_data(
14205 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714206 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514207 &hanging_non_alternate_protocol_socket);
14208
[email protected]49639fa2011-12-20 23:22:4114209 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1114210
danakj1fd259a02016-04-16 03:17:0914211 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814212 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914213 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114214
tfarina42834112016-09-22 13:38:2014215 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4114216 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14217 EXPECT_THAT(callback.WaitForResult(), IsOk());
14218
14219 const HttpResponseInfo* response = trans->GetResponseInfo();
14220 ASSERT_TRUE(response);
14221 ASSERT_TRUE(response->headers);
14222 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
14223 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214224 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4114225
14226 std::string response_data;
14227 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
14228 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1114229
bnc87dcefc2017-05-25 12:47:5814230 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914231 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114232
tfarina42834112016-09-22 13:38:2014233 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114234 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14235 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1114236
mmenkea2dcd3bf2016-08-16 21:49:4114237 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214238 ASSERT_TRUE(response);
14239 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214240 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314241 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214242 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1114243
robpercival214763f2016-07-01 23:27:0114244 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1114245 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4514246 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
14247 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1314248 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2314249 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1314250 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1114251
[email protected]029c83b62013-01-24 05:28:2014252 LoadTimingInfo load_timing_info;
14253 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
14254 TestLoadTimingNotReusedWithPac(load_timing_info,
14255 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1114256}
[email protected]631f1322010-04-30 17:59:1114257
bncd16676a2016-07-20 16:23:0114258TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4814259 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5414260 HttpRequestInfo request;
14261 request.method = "GET";
bncb26024382016-06-29 02:39:4514262 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014263 request.traffic_annotation =
14264 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414265
14266 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214267 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314268 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214269 MockRead("\r\n"),
14270 MockRead("hello world"),
14271 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5414272 };
14273
Ryan Sleevib8d7ea02018-05-07 20:01:0114274 StaticSocketDataProvider first_transaction(data_reads,
14275 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714276 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514277 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614278 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514279 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414280
bnc032658ba2016-09-26 18:17:1514281 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414282
Ryan Hamilton0239aac2018-05-19 00:03:1314283 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514284 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114285 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414286
Raul Tambre94493c652019-03-11 17:18:3514287 spdy::SpdySerializedFrame resp(
14288 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314289 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414290 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114291 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414292 };
14293
Ryan Sleevib8d7ea02018-05-07 20:01:0114294 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714295 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414296
[email protected]83039bb2011-12-09 18:43:5514297 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414298
danakj1fd259a02016-04-16 03:17:0914299 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5414300
bnc87dcefc2017-05-25 12:47:5814301 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914302 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414303
tfarina42834112016-09-22 13:38:2014304 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114305 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14306 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414307
14308 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214309 ASSERT_TRUE(response);
14310 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414311 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14312
14313 std::string response_data;
robpercival214763f2016-07-01 23:27:0114314 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414315 EXPECT_EQ("hello world", response_data);
14316
14317 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2514318 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4014319 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1114320 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3414321 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
14322 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2714323 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5214324 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3814325
bnc87dcefc2017-05-25 12:47:5814326 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914327 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414328
tfarina42834112016-09-22 13:38:2014329 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14331 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414332
14333 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214334 ASSERT_TRUE(response);
14335 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214336 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314337 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214338 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414339
robpercival214763f2016-07-01 23:27:0114340 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414341 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4214342}
14343
[email protected]044de0642010-06-17 10:42:1514344// GenerateAuthToken is a mighty big test.
14345// It tests all permutation of GenerateAuthToken behavior:
14346// - Synchronous and Asynchronous completion.
14347// - OK or error on completion.
14348// - Direct connection, non-authenticating proxy, and authenticating proxy.
14349// - HTTP or HTTPS backend (to include proxy tunneling).
14350// - Non-authenticating and authenticating backend.
14351//
[email protected]fe3b7dc2012-02-03 19:52:0914352// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1514353// problems generating an auth token for an authenticating proxy, we don't
14354// need to test all permutations of the backend server).
14355//
14356// The test proceeds by going over each of the configuration cases, and
14357// potentially running up to three rounds in each of the tests. The TestConfig
14358// specifies both the configuration for the test as well as the expectations
14359// for the results.
bncd16676a2016-07-20 16:23:0114360TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5014361 static const char kServer[] = "http://www.example.com";
14362 static const char kSecureServer[] = "https://www.example.com";
14363 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1514364
14365 enum AuthTiming {
14366 AUTH_NONE,
14367 AUTH_SYNC,
14368 AUTH_ASYNC,
14369 };
14370
14371 const MockWrite kGet(
14372 "GET / HTTP/1.1\r\n"
14373 "Host: www.example.com\r\n"
14374 "Connection: keep-alive\r\n\r\n");
14375 const MockWrite kGetProxy(
14376 "GET http://www.example.com/ HTTP/1.1\r\n"
14377 "Host: www.example.com\r\n"
14378 "Proxy-Connection: keep-alive\r\n\r\n");
14379 const MockWrite kGetAuth(
14380 "GET / HTTP/1.1\r\n"
14381 "Host: www.example.com\r\n"
14382 "Connection: keep-alive\r\n"
14383 "Authorization: auth_token\r\n\r\n");
14384 const MockWrite kGetProxyAuth(
14385 "GET http://www.example.com/ HTTP/1.1\r\n"
14386 "Host: www.example.com\r\n"
14387 "Proxy-Connection: keep-alive\r\n"
14388 "Proxy-Authorization: auth_token\r\n\r\n");
14389 const MockWrite kGetAuthThroughProxy(
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 "Authorization: auth_token\r\n\r\n");
14394 const MockWrite kGetAuthWithProxyAuth(
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 "Proxy-Authorization: auth_token\r\n"
14399 "Authorization: auth_token\r\n\r\n");
14400 const MockWrite kConnect(
14401 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714402 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514403 "Proxy-Connection: keep-alive\r\n\r\n");
14404 const MockWrite kConnectProxyAuth(
14405 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714406 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514407 "Proxy-Connection: keep-alive\r\n"
14408 "Proxy-Authorization: auth_token\r\n\r\n");
14409
14410 const MockRead kSuccess(
14411 "HTTP/1.1 200 OK\r\n"
14412 "Content-Type: text/html; charset=iso-8859-1\r\n"
14413 "Content-Length: 3\r\n\r\n"
14414 "Yes");
14415 const MockRead kFailure(
14416 "Should not be called.");
14417 const MockRead kServerChallenge(
14418 "HTTP/1.1 401 Unauthorized\r\n"
14419 "WWW-Authenticate: Mock realm=server\r\n"
14420 "Content-Type: text/html; charset=iso-8859-1\r\n"
14421 "Content-Length: 14\r\n\r\n"
14422 "Unauthorized\r\n");
14423 const MockRead kProxyChallenge(
14424 "HTTP/1.1 407 Unauthorized\r\n"
14425 "Proxy-Authenticate: Mock realm=proxy\r\n"
14426 "Proxy-Connection: close\r\n"
14427 "Content-Type: text/html; charset=iso-8859-1\r\n"
14428 "Content-Length: 14\r\n\r\n"
14429 "Unauthorized\r\n");
14430 const MockRead kProxyConnected(
14431 "HTTP/1.1 200 Connection Established\r\n\r\n");
14432
14433 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
14434 // no constructors, but the C++ compiler on Windows warns about
14435 // unspecified data in compound literals. So, moved to using constructors,
14436 // and TestRound's created with the default constructor should not be used.
14437 struct TestRound {
14438 TestRound()
Raul Tambre94493c652019-03-11 17:18:3514439 : expected_rv(ERR_UNEXPECTED),
14440 extra_write(nullptr),
14441 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4314442 TestRound(const MockWrite& write_arg,
14443 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1514444 int expected_rv_arg)
14445 : write(write_arg),
14446 read(read_arg),
14447 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3514448 extra_write(nullptr),
14449 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1514450 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
14451 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0114452 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1514453 : write(write_arg),
14454 read(read_arg),
14455 expected_rv(expected_rv_arg),
14456 extra_write(extra_write_arg),
14457 extra_read(extra_read_arg) {
14458 }
14459 MockWrite write;
14460 MockRead read;
14461 int expected_rv;
14462 const MockWrite* extra_write;
14463 const MockRead* extra_read;
14464 };
14465
14466 static const int kNoSSL = 500;
14467
14468 struct TestConfig {
asanka463ca4262016-11-16 02:34:3114469 int line_number;
thestig9d3bb0c2015-01-24 00:49:5114470 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1514471 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3114472 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5114473 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1514474 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3114475 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1514476 int num_auth_rounds;
14477 int first_ssl_round;
asankae2257db2016-10-11 22:03:1614478 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1514479 } test_configs[] = {
asankac93076192016-10-03 15:46:0214480 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114481 {__LINE__,
14482 nullptr,
asankac93076192016-10-03 15:46:0214483 AUTH_NONE,
14484 OK,
14485 kServer,
14486 AUTH_NONE,
14487 OK,
14488 1,
14489 kNoSSL,
14490 {TestRound(kGet, kSuccess, OK)}},
14491 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114492 {__LINE__,
14493 nullptr,
asankac93076192016-10-03 15:46:0214494 AUTH_NONE,
14495 OK,
14496 kServer,
14497 AUTH_SYNC,
14498 OK,
14499 2,
14500 kNoSSL,
14501 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514502 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114503 {__LINE__,
14504 nullptr,
asankac93076192016-10-03 15:46:0214505 AUTH_NONE,
14506 OK,
14507 kServer,
14508 AUTH_SYNC,
14509 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614510 3,
14511 kNoSSL,
14512 {TestRound(kGet, kServerChallenge, OK),
14513 TestRound(kGet, kServerChallenge, OK),
14514 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114515 {__LINE__,
14516 nullptr,
asankae2257db2016-10-11 22:03:1614517 AUTH_NONE,
14518 OK,
14519 kServer,
14520 AUTH_SYNC,
14521 ERR_UNSUPPORTED_AUTH_SCHEME,
14522 2,
14523 kNoSSL,
14524 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114525 {__LINE__,
14526 nullptr,
asankae2257db2016-10-11 22:03:1614527 AUTH_NONE,
14528 OK,
14529 kServer,
14530 AUTH_SYNC,
14531 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
14532 2,
14533 kNoSSL,
14534 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114535 {__LINE__,
14536 kProxy,
asankae2257db2016-10-11 22:03:1614537 AUTH_SYNC,
14538 ERR_FAILED,
14539 kServer,
14540 AUTH_NONE,
14541 OK,
14542 2,
14543 kNoSSL,
14544 {TestRound(kGetProxy, kProxyChallenge, OK),
14545 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114546 {__LINE__,
14547 kProxy,
asankae2257db2016-10-11 22:03:1614548 AUTH_ASYNC,
14549 ERR_FAILED,
14550 kServer,
14551 AUTH_NONE,
14552 OK,
14553 2,
14554 kNoSSL,
14555 {TestRound(kGetProxy, kProxyChallenge, OK),
14556 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114557 {__LINE__,
14558 nullptr,
asankae2257db2016-10-11 22:03:1614559 AUTH_NONE,
14560 OK,
14561 kServer,
14562 AUTH_SYNC,
14563 ERR_FAILED,
asankac93076192016-10-03 15:46:0214564 2,
14565 kNoSSL,
14566 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614567 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114568 {__LINE__,
14569 nullptr,
asankae2257db2016-10-11 22:03:1614570 AUTH_NONE,
14571 OK,
14572 kServer,
14573 AUTH_ASYNC,
14574 ERR_FAILED,
14575 2,
14576 kNoSSL,
14577 {TestRound(kGet, kServerChallenge, OK),
14578 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114579 {__LINE__,
14580 nullptr,
asankac93076192016-10-03 15:46:0214581 AUTH_NONE,
14582 OK,
14583 kServer,
14584 AUTH_ASYNC,
14585 OK,
14586 2,
14587 kNoSSL,
14588 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514589 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114590 {__LINE__,
14591 nullptr,
asankac93076192016-10-03 15:46:0214592 AUTH_NONE,
14593 OK,
14594 kServer,
14595 AUTH_ASYNC,
14596 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614597 3,
asankac93076192016-10-03 15:46:0214598 kNoSSL,
14599 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614600 // The second round uses a HttpAuthHandlerMock that always succeeds.
14601 TestRound(kGet, kServerChallenge, OK),
14602 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214603 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114604 {__LINE__,
14605 kProxy,
asankac93076192016-10-03 15:46:0214606 AUTH_NONE,
14607 OK,
14608 kServer,
14609 AUTH_NONE,
14610 OK,
14611 1,
14612 kNoSSL,
14613 {TestRound(kGetProxy, kSuccess, OK)}},
14614 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114615 {__LINE__,
14616 kProxy,
asankac93076192016-10-03 15:46:0214617 AUTH_NONE,
14618 OK,
14619 kServer,
14620 AUTH_SYNC,
14621 OK,
14622 2,
14623 kNoSSL,
14624 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514625 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114626 {__LINE__,
14627 kProxy,
asankac93076192016-10-03 15:46:0214628 AUTH_NONE,
14629 OK,
14630 kServer,
14631 AUTH_SYNC,
14632 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614633 3,
asankac93076192016-10-03 15:46:0214634 kNoSSL,
14635 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614636 TestRound(kGetProxy, kServerChallenge, OK),
14637 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114638 {__LINE__,
14639 kProxy,
asankac93076192016-10-03 15:46:0214640 AUTH_NONE,
14641 OK,
14642 kServer,
14643 AUTH_ASYNC,
14644 OK,
14645 2,
14646 kNoSSL,
14647 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514648 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114649 {__LINE__,
14650 kProxy,
asankac93076192016-10-03 15:46:0214651 AUTH_NONE,
14652 OK,
14653 kServer,
14654 AUTH_ASYNC,
14655 ERR_INVALID_AUTH_CREDENTIALS,
14656 2,
14657 kNoSSL,
14658 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614659 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214660 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114661 {__LINE__,
14662 kProxy,
asankac93076192016-10-03 15:46:0214663 AUTH_SYNC,
14664 OK,
14665 kServer,
14666 AUTH_NONE,
14667 OK,
14668 2,
14669 kNoSSL,
14670 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514671 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114672 {__LINE__,
14673 kProxy,
asankac93076192016-10-03 15:46:0214674 AUTH_SYNC,
14675 ERR_INVALID_AUTH_CREDENTIALS,
14676 kServer,
14677 AUTH_NONE,
14678 OK,
14679 2,
14680 kNoSSL,
14681 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614682 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114683 {__LINE__,
14684 kProxy,
asankac93076192016-10-03 15:46:0214685 AUTH_ASYNC,
14686 OK,
14687 kServer,
14688 AUTH_NONE,
14689 OK,
14690 2,
14691 kNoSSL,
14692 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514693 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114694 {__LINE__,
14695 kProxy,
asankac93076192016-10-03 15:46:0214696 AUTH_ASYNC,
14697 ERR_INVALID_AUTH_CREDENTIALS,
14698 kServer,
14699 AUTH_NONE,
14700 OK,
14701 2,
14702 kNoSSL,
14703 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614704 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114705 {__LINE__,
14706 kProxy,
14707 AUTH_ASYNC,
14708 ERR_INVALID_AUTH_CREDENTIALS,
14709 kServer,
14710 AUTH_NONE,
14711 OK,
14712 3,
14713 kNoSSL,
14714 {TestRound(kGetProxy, kProxyChallenge, OK),
14715 TestRound(kGetProxy, kProxyChallenge, OK),
14716 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214717 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114718 {__LINE__,
14719 kProxy,
asankac93076192016-10-03 15:46:0214720 AUTH_SYNC,
14721 OK,
14722 kServer,
14723 AUTH_SYNC,
14724 OK,
14725 3,
14726 kNoSSL,
14727 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514728 TestRound(kGetProxyAuth, kServerChallenge, OK),
14729 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114730 {__LINE__,
14731 kProxy,
asankac93076192016-10-03 15:46:0214732 AUTH_SYNC,
14733 OK,
14734 kServer,
14735 AUTH_SYNC,
14736 ERR_INVALID_AUTH_CREDENTIALS,
14737 3,
14738 kNoSSL,
14739 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514740 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614741 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114742 {__LINE__,
14743 kProxy,
asankac93076192016-10-03 15:46:0214744 AUTH_ASYNC,
14745 OK,
14746 kServer,
14747 AUTH_SYNC,
14748 OK,
14749 3,
14750 kNoSSL,
14751 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514752 TestRound(kGetProxyAuth, kServerChallenge, OK),
14753 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114754 {__LINE__,
14755 kProxy,
asankac93076192016-10-03 15:46:0214756 AUTH_ASYNC,
14757 OK,
14758 kServer,
14759 AUTH_SYNC,
14760 ERR_INVALID_AUTH_CREDENTIALS,
14761 3,
14762 kNoSSL,
14763 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514764 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614765 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114766 {__LINE__,
14767 kProxy,
asankac93076192016-10-03 15:46:0214768 AUTH_SYNC,
14769 OK,
14770 kServer,
14771 AUTH_ASYNC,
14772 OK,
14773 3,
14774 kNoSSL,
14775 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514776 TestRound(kGetProxyAuth, kServerChallenge, OK),
14777 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114778 {__LINE__,
14779 kProxy,
14780 AUTH_SYNC,
14781 ERR_INVALID_AUTH_CREDENTIALS,
14782 kServer,
14783 AUTH_ASYNC,
14784 OK,
14785 4,
14786 kNoSSL,
14787 {TestRound(kGetProxy, kProxyChallenge, OK),
14788 TestRound(kGetProxy, kProxyChallenge, OK),
14789 TestRound(kGetProxyAuth, kServerChallenge, OK),
14790 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
14791 {__LINE__,
14792 kProxy,
asankac93076192016-10-03 15:46:0214793 AUTH_SYNC,
14794 OK,
14795 kServer,
14796 AUTH_ASYNC,
14797 ERR_INVALID_AUTH_CREDENTIALS,
14798 3,
14799 kNoSSL,
14800 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514801 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614802 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114803 {__LINE__,
14804 kProxy,
asankac93076192016-10-03 15:46:0214805 AUTH_ASYNC,
14806 OK,
14807 kServer,
14808 AUTH_ASYNC,
14809 OK,
14810 3,
14811 kNoSSL,
14812 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514813 TestRound(kGetProxyAuth, kServerChallenge, OK),
14814 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114815 {__LINE__,
14816 kProxy,
asankac93076192016-10-03 15:46:0214817 AUTH_ASYNC,
14818 OK,
14819 kServer,
14820 AUTH_ASYNC,
14821 ERR_INVALID_AUTH_CREDENTIALS,
14822 3,
14823 kNoSSL,
14824 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514825 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614826 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114827 {__LINE__,
14828 kProxy,
14829 AUTH_ASYNC,
14830 ERR_INVALID_AUTH_CREDENTIALS,
14831 kServer,
14832 AUTH_ASYNC,
14833 ERR_INVALID_AUTH_CREDENTIALS,
14834 4,
14835 kNoSSL,
14836 {TestRound(kGetProxy, kProxyChallenge, OK),
14837 TestRound(kGetProxy, kProxyChallenge, OK),
14838 TestRound(kGetProxyAuth, kServerChallenge, OK),
14839 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214840 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114841 {__LINE__,
14842 nullptr,
asankac93076192016-10-03 15:46:0214843 AUTH_NONE,
14844 OK,
14845 kSecureServer,
14846 AUTH_NONE,
14847 OK,
14848 1,
14849 0,
14850 {TestRound(kGet, kSuccess, OK)}},
14851 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114852 {__LINE__,
14853 nullptr,
asankac93076192016-10-03 15:46:0214854 AUTH_NONE,
14855 OK,
14856 kSecureServer,
14857 AUTH_SYNC,
14858 OK,
14859 2,
14860 0,
14861 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514862 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114863 {__LINE__,
14864 nullptr,
asankac93076192016-10-03 15:46:0214865 AUTH_NONE,
14866 OK,
14867 kSecureServer,
14868 AUTH_SYNC,
14869 ERR_INVALID_AUTH_CREDENTIALS,
14870 2,
14871 0,
asankae2257db2016-10-11 22:03:1614872 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114873 {__LINE__,
14874 nullptr,
asankac93076192016-10-03 15:46:0214875 AUTH_NONE,
14876 OK,
14877 kSecureServer,
14878 AUTH_ASYNC,
14879 OK,
14880 2,
14881 0,
14882 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514883 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114884 {__LINE__,
14885 nullptr,
asankac93076192016-10-03 15:46:0214886 AUTH_NONE,
14887 OK,
14888 kSecureServer,
14889 AUTH_ASYNC,
14890 ERR_INVALID_AUTH_CREDENTIALS,
14891 2,
14892 0,
asankae2257db2016-10-11 22:03:1614893 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214894 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114895 {__LINE__,
14896 kProxy,
asankac93076192016-10-03 15:46:0214897 AUTH_NONE,
14898 OK,
14899 kSecureServer,
14900 AUTH_NONE,
14901 OK,
14902 1,
14903 0,
14904 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
14905 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114906 {__LINE__,
14907 kProxy,
asankac93076192016-10-03 15:46:0214908 AUTH_NONE,
14909 OK,
14910 kSecureServer,
14911 AUTH_SYNC,
14912 OK,
14913 2,
14914 0,
14915 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514916 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114917 {__LINE__,
14918 kProxy,
asankac93076192016-10-03 15:46:0214919 AUTH_NONE,
14920 OK,
14921 kSecureServer,
14922 AUTH_SYNC,
14923 ERR_INVALID_AUTH_CREDENTIALS,
14924 2,
14925 0,
14926 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614927 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114928 {__LINE__,
14929 kProxy,
asankac93076192016-10-03 15:46:0214930 AUTH_NONE,
14931 OK,
14932 kSecureServer,
14933 AUTH_ASYNC,
14934 OK,
14935 2,
14936 0,
14937 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514938 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114939 {__LINE__,
14940 kProxy,
asankac93076192016-10-03 15:46:0214941 AUTH_NONE,
14942 OK,
14943 kSecureServer,
14944 AUTH_ASYNC,
14945 ERR_INVALID_AUTH_CREDENTIALS,
14946 2,
14947 0,
14948 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614949 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214950 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114951 {__LINE__,
14952 kProxy,
asankac93076192016-10-03 15:46:0214953 AUTH_SYNC,
14954 OK,
14955 kSecureServer,
14956 AUTH_NONE,
14957 OK,
14958 2,
14959 1,
14960 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514961 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114962 {__LINE__,
14963 kProxy,
asankac93076192016-10-03 15:46:0214964 AUTH_SYNC,
14965 ERR_INVALID_AUTH_CREDENTIALS,
14966 kSecureServer,
14967 AUTH_NONE,
14968 OK,
14969 2,
14970 kNoSSL,
14971 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614972 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114973 {__LINE__,
14974 kProxy,
asankae2257db2016-10-11 22:03:1614975 AUTH_SYNC,
14976 ERR_UNSUPPORTED_AUTH_SCHEME,
14977 kSecureServer,
14978 AUTH_NONE,
14979 OK,
14980 2,
14981 kNoSSL,
14982 {TestRound(kConnect, kProxyChallenge, OK),
14983 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114984 {__LINE__,
14985 kProxy,
asankae2257db2016-10-11 22:03:1614986 AUTH_SYNC,
14987 ERR_UNEXPECTED,
14988 kSecureServer,
14989 AUTH_NONE,
14990 OK,
14991 2,
14992 kNoSSL,
14993 {TestRound(kConnect, kProxyChallenge, OK),
14994 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3114995 {__LINE__,
14996 kProxy,
asankac93076192016-10-03 15:46:0214997 AUTH_ASYNC,
14998 OK,
14999 kSecureServer,
15000 AUTH_NONE,
15001 OK,
15002 2,
15003 1,
15004 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515005 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115006 {__LINE__,
15007 kProxy,
asankac93076192016-10-03 15:46:0215008 AUTH_ASYNC,
15009 ERR_INVALID_AUTH_CREDENTIALS,
15010 kSecureServer,
15011 AUTH_NONE,
15012 OK,
15013 2,
15014 kNoSSL,
15015 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615016 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0215017 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115018 {__LINE__,
15019 kProxy,
asankac93076192016-10-03 15:46:0215020 AUTH_SYNC,
15021 OK,
15022 kSecureServer,
15023 AUTH_SYNC,
15024 OK,
15025 3,
15026 1,
15027 {TestRound(kConnect, kProxyChallenge, OK),
15028 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15029 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515030 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115031 {__LINE__,
15032 kProxy,
asankac93076192016-10-03 15:46:0215033 AUTH_SYNC,
15034 OK,
15035 kSecureServer,
15036 AUTH_SYNC,
15037 ERR_INVALID_AUTH_CREDENTIALS,
15038 3,
15039 1,
15040 {TestRound(kConnect, kProxyChallenge, OK),
15041 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15042 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615043 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115044 {__LINE__,
15045 kProxy,
asankac93076192016-10-03 15:46:0215046 AUTH_ASYNC,
15047 OK,
15048 kSecureServer,
15049 AUTH_SYNC,
15050 OK,
15051 3,
15052 1,
15053 {TestRound(kConnect, kProxyChallenge, OK),
15054 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15055 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515056 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115057 {__LINE__,
15058 kProxy,
asankac93076192016-10-03 15:46:0215059 AUTH_ASYNC,
15060 OK,
15061 kSecureServer,
15062 AUTH_SYNC,
15063 ERR_INVALID_AUTH_CREDENTIALS,
15064 3,
15065 1,
15066 {TestRound(kConnect, kProxyChallenge, OK),
15067 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15068 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615069 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115070 {__LINE__,
15071 kProxy,
asankac93076192016-10-03 15:46:0215072 AUTH_SYNC,
15073 OK,
15074 kSecureServer,
15075 AUTH_ASYNC,
15076 OK,
15077 3,
15078 1,
15079 {TestRound(kConnect, kProxyChallenge, OK),
15080 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15081 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515082 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115083 {__LINE__,
15084 kProxy,
asankac93076192016-10-03 15:46:0215085 AUTH_SYNC,
15086 OK,
15087 kSecureServer,
15088 AUTH_ASYNC,
15089 ERR_INVALID_AUTH_CREDENTIALS,
15090 3,
15091 1,
15092 {TestRound(kConnect, kProxyChallenge, OK),
15093 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15094 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615095 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115096 {__LINE__,
15097 kProxy,
asankac93076192016-10-03 15:46:0215098 AUTH_ASYNC,
15099 OK,
15100 kSecureServer,
15101 AUTH_ASYNC,
15102 OK,
15103 3,
15104 1,
15105 {TestRound(kConnect, kProxyChallenge, OK),
15106 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15107 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515108 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115109 {__LINE__,
15110 kProxy,
asankac93076192016-10-03 15:46:0215111 AUTH_ASYNC,
15112 OK,
15113 kSecureServer,
15114 AUTH_ASYNC,
15115 ERR_INVALID_AUTH_CREDENTIALS,
15116 3,
15117 1,
15118 {TestRound(kConnect, kProxyChallenge, OK),
15119 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15120 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615121 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115122 {__LINE__,
15123 kProxy,
15124 AUTH_ASYNC,
15125 ERR_INVALID_AUTH_CREDENTIALS,
15126 kSecureServer,
15127 AUTH_ASYNC,
15128 ERR_INVALID_AUTH_CREDENTIALS,
15129 4,
15130 2,
15131 {TestRound(kConnect, kProxyChallenge, OK),
15132 TestRound(kConnect, kProxyChallenge, OK),
15133 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15134 &kServerChallenge),
15135 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1515136 };
15137
asanka463ca4262016-11-16 02:34:3115138 for (const auto& test_config : test_configs) {
15139 SCOPED_TRACE(::testing::Message() << "Test config at "
15140 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0815141 HttpAuthHandlerMock::Factory* auth_factory(
15142 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715143 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4915144 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2615145
15146 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1515147 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3115148 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0815149 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15150 std::string auth_challenge = "Mock realm=proxy";
15151 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2415152 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15153 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0815154 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2015155 empty_ssl_info, origin,
15156 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815157 auth_handler->SetGenerateExpectation(
15158 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115159 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0815160 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
15161 }
[email protected]044de0642010-06-17 10:42:1515162 }
15163 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0015164 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1515165 std::string auth_challenge = "Mock realm=server";
15166 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2415167 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15168 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1515169 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2015170 empty_ssl_info, origin,
15171 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515172 auth_handler->SetGenerateExpectation(
15173 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115174 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0815175 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1615176
15177 // The second handler always succeeds. It should only be used where there
15178 // are multiple auth sessions for server auth in the same network
15179 // transaction using the same auth scheme.
15180 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1915181 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1615182 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
15183 empty_ssl_info, origin,
15184 NetLogWithSource());
15185 second_handler->SetGenerateExpectation(true, OK);
15186 auth_factory->AddMockHandler(second_handler.release(),
15187 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1515188 }
15189 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5915190 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915191 ProxyResolutionService::CreateFixed(test_config.proxy_url,
15192 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515193 } else {
Bence Béky53a5aef2018-03-29 21:54:1215194 session_deps_.proxy_resolution_service =
15195 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1515196 }
15197
15198 HttpRequestInfo request;
15199 request.method = "GET";
15200 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e62018-02-07 07:41:1015201 request.traffic_annotation =
15202 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515203
danakj1fd259a02016-04-16 03:17:0915204 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1515205
rchcb68dc62015-05-21 04:45:3615206 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
15207
15208 std::vector<std::vector<MockRead>> mock_reads(1);
15209 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1515210 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215211 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1515212 const TestRound& read_write_round = test_config.rounds[round];
15213
15214 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3615215 mock_reads.back().push_back(read_write_round.read);
15216 mock_writes.back().push_back(read_write_round.write);
15217
15218 // kProxyChallenge uses Proxy-Connection: close which means that the
15219 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5415220 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3615221 mock_reads.push_back(std::vector<MockRead>());
15222 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1515223 }
15224
rchcb68dc62015-05-21 04:45:3615225 if (read_write_round.extra_read) {
15226 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1515227 }
rchcb68dc62015-05-21 04:45:3615228 if (read_write_round.extra_write) {
15229 mock_writes.back().push_back(*read_write_round.extra_write);
15230 }
[email protected]044de0642010-06-17 10:42:1515231
15232 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1515233 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0715234 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1515235 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3615236 }
[email protected]044de0642010-06-17 10:42:1515237
danakj1fd259a02016-04-16 03:17:0915238 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3615239 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1915240 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0115241 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3615242 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3215243 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3615244 }
15245
mmenkecc2298e2015-12-07 18:20:1815246 // Transaction must be created after DataProviders, so it's destroyed before
15247 // they are as well.
15248 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15249
rchcb68dc62015-05-21 04:45:3615250 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215251 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3615252 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1515253 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4115254 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1515255 int rv;
15256 if (round == 0) {
tfarina42834112016-09-22 13:38:2015257 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515258 } else {
[email protected]49639fa2011-12-20 23:22:4115259 rv = trans.RestartWithAuth(
15260 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1515261 }
15262 if (rv == ERR_IO_PENDING)
15263 rv = callback.WaitForResult();
15264
15265 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1615266 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5015267 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5515268 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1515269 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
15270 continue;
15271 }
15272 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5815273 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1515274 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5815275 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1615276 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1515277 }
15278 }
[email protected]e5ae96a2010-04-14 20:12:4515279 }
15280}
15281
bncd16676a2016-07-20 16:23:0115282TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1415283 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1415284 HttpAuthHandlerMock::Factory* auth_factory(
15285 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715286 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1215287 session_deps_.proxy_resolution_service =
15288 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0715289 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1415290
15291 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15292 auth_handler->set_connection_based(true);
15293 std::string auth_challenge = "Mock realm=server";
15294 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2415295 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15296 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4915297 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1415298 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2015299 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815300 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1415301
[email protected]c871bce92010-07-15 21:51:1415302 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3515303 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1415304 HttpRequestInfo request;
15305 request.method = "GET";
15306 request.url = origin;
Ramin Halavatib5e433e62018-02-07 07:41:1015307 request.traffic_annotation =
15308 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715309
danakj1fd259a02016-04-16 03:17:0915310 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1015311
15312 // Use a TCP Socket Pool with only one connection per group. This is used
15313 // to validate that the TCP socket is not released to the pool between
15314 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4215315 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3615316 CommonConnectJobParams common_connect_job_params(
15317 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2815318 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5915319 50, // Max sockets for pool
15320 1, // Max sockets per group
15321 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3615322 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5215323 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1915324 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4015325 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
15326 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4815327 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1015328
bnc691fda62016-08-12 00:43:1615329 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115330 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1415331
15332 const MockWrite kGet(
15333 "GET / HTTP/1.1\r\n"
15334 "Host: www.example.com\r\n"
15335 "Connection: keep-alive\r\n\r\n");
15336 const MockWrite kGetAuth(
15337 "GET / HTTP/1.1\r\n"
15338 "Host: www.example.com\r\n"
15339 "Connection: keep-alive\r\n"
15340 "Authorization: auth_token\r\n\r\n");
15341
15342 const MockRead kServerChallenge(
15343 "HTTP/1.1 401 Unauthorized\r\n"
15344 "WWW-Authenticate: Mock realm=server\r\n"
15345 "Content-Type: text/html; charset=iso-8859-1\r\n"
15346 "Content-Length: 14\r\n\r\n"
15347 "Unauthorized\r\n");
15348 const MockRead kSuccess(
15349 "HTTP/1.1 200 OK\r\n"
15350 "Content-Type: text/html; charset=iso-8859-1\r\n"
15351 "Content-Length: 3\r\n\r\n"
15352 "Yes");
15353
15354 MockWrite writes[] = {
15355 // First round
15356 kGet,
15357 // Second round
15358 kGetAuth,
15359 // Third round
15360 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3015361 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1015362 kGetAuth,
15363 // Competing request
15364 kGet,
[email protected]c871bce92010-07-15 21:51:1415365 };
15366 MockRead reads[] = {
15367 // First round
15368 kServerChallenge,
15369 // Second round
15370 kServerChallenge,
15371 // Third round
[email protected]eca50e122010-09-11 14:03:3015372 kServerChallenge,
15373 // Fourth round
[email protected]c871bce92010-07-15 21:51:1415374 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1015375 // Competing response
15376 kSuccess,
[email protected]c871bce92010-07-15 21:51:1415377 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115378 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0715379 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1415380
Matt Menkef6edce752019-03-19 17:21:5615381 const ClientSocketPool::GroupId kSocketGroup(
15382 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3415383 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
15384 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1015385
15386 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1415387 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2015388 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1415389 if (rv == ERR_IO_PENDING)
15390 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115391 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615392 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215393 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815394 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315395 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115396 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15397 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415398
[email protected]7ef4cbbb2011-02-06 11:19:1015399 // In between rounds, another request comes in for the same domain.
15400 // It should not be able to grab the TCP socket that trans has already
15401 // claimed.
bnc691fda62016-08-12 00:43:1615402 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115403 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2015404 rv = trans_compete.Start(&request, callback_compete.callback(),
15405 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115406 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1015407 // callback_compete.WaitForResult at this point would stall forever,
15408 // since the HttpNetworkTransaction does not release the request back to
15409 // the pool until after authentication completes.
15410
15411 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1415412 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615413 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415414 if (rv == ERR_IO_PENDING)
15415 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115416 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615417 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215418 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815419 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315420 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115421 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15422 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415423
[email protected]7ef4cbbb2011-02-06 11:19:1015424 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1415425 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615426 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415427 if (rv == ERR_IO_PENDING)
15428 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115429 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615430 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215431 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815432 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315433 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115434 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15435 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3015436
[email protected]7ef4cbbb2011-02-06 11:19:1015437 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3015438 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615439 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3015440 if (rv == ERR_IO_PENDING)
15441 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115442 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615443 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215444 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815445 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315446 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015447
asanka463ca4262016-11-16 02:34:3115448 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
15449 // auth handler should transition to a DONE state in concert with the remote
15450 // server. But that's not something we can test here with a mock handler.
15451 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
15452 auth_handler->state());
15453
[email protected]7ef4cbbb2011-02-06 11:19:1015454 // Read the body since the fourth round was successful. This will also
15455 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4415456 scoped_refptr<IOBufferWithSize> io_buf =
15457 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1615458 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015459 if (rv == ERR_IO_PENDING)
15460 rv = callback.WaitForResult();
15461 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615462 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015463 EXPECT_EQ(0, rv);
15464 // There are still 0 idle sockets, since the trans_compete transaction
15465 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315466 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015467
15468 // The competing request can now finish. Wait for the headers and then
15469 // read the body.
15470 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0115471 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615472 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015473 if (rv == ERR_IO_PENDING)
15474 rv = callback.WaitForResult();
15475 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615476 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015477 EXPECT_EQ(0, rv);
15478
15479 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315480 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1415481}
15482
[email protected]65041fa2010-05-21 06:56:5315483// This tests the case that a request is issued via http instead of spdy after
15484// npn is negotiated.
bncd16676a2016-07-20 16:23:0115485TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5315486 HttpRequestInfo request;
15487 request.method = "GET";
bncce36dca22015-04-21 22:11:2315488 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015489 request.traffic_annotation =
15490 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5315491
15492 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2315493 MockWrite(
15494 "GET / HTTP/1.1\r\n"
15495 "Host: www.example.org\r\n"
15496 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5315497 };
15498
15499 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5215500 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4315501 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5215502 MockRead("\r\n"),
15503 MockRead("hello world"),
15504 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5315505 };
15506
[email protected]8ddf8322012-02-23 18:08:0615507 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615508 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5315509
[email protected]bb88e1d32013-05-03 23:11:0715510 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5315511
Ryan Sleevib8d7ea02018-05-07 20:01:0115512 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715513 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5315514
[email protected]49639fa2011-12-20 23:22:4115515 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5315516
danakj1fd259a02016-04-16 03:17:0915517 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615518 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5315519
tfarina42834112016-09-22 13:38:2015520 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5315521
robpercival214763f2016-07-01 23:27:0115522 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15523 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5315524
bnc691fda62016-08-12 00:43:1615525 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215526 ASSERT_TRUE(response);
15527 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5315528 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15529
15530 std::string response_data;
bnc691fda62016-08-12 00:43:1615531 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5315532 EXPECT_EQ("hello world", response_data);
15533
15534 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215535 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5315536}
[email protected]26ef6582010-06-24 02:30:4715537
bnc55ff9da2015-08-19 18:42:3515538// Simulate the SSL handshake completing with an NPN negotiation followed by an
15539// immediate server closing of the socket.
15540// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0115541TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4715542 HttpRequestInfo request;
15543 request.method = "GET";
bncce36dca22015-04-21 22:11:2315544 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015545 request.traffic_annotation =
15546 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4715547
[email protected]8ddf8322012-02-23 18:08:0615548 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615549 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4715551
Ryan Hamilton0239aac2018-05-19 00:03:1315552 spdy::SpdySerializedFrame req(
15553 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115554 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4715555
15556 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615557 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4715558 };
15559
Ryan Sleevib8d7ea02018-05-07 20:01:0115560 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715561 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4715562
[email protected]49639fa2011-12-20 23:22:4115563 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4715564
danakj1fd259a02016-04-16 03:17:0915565 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615566 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4715567
tfarina42834112016-09-22 13:38:2015568 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115569 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15570 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4715571}
[email protected]65d34382010-07-01 18:12:2615572
[email protected]795cbf82013-07-22 09:37:2715573// A subclass of HttpAuthHandlerMock that records the request URL when
15574// it gets it. This is needed since the auth handler may get destroyed
15575// before we get a chance to query it.
15576class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
15577 public:
15578 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
15579
Chris Watkins7a41d3552017-12-01 02:13:2715580 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2715581
15582 protected:
dchengb03027d2014-10-21 12:00:2015583 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
15584 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0915585 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2015586 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2715587 *url_ = request->url;
15588 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0915589 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2715590 }
15591
15592 private:
15593 GURL* url_;
15594};
15595
[email protected]8e6441ca2010-08-19 05:56:3815596// Test that if we cancel the transaction as the connection is completing, that
15597// everything tears down correctly.
bncd16676a2016-07-20 16:23:0115598TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3815599 // Setup everything about the connection to complete synchronously, so that
15600 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
15601 // for is the callback from the HttpStreamRequest.
15602 // Then cancel the transaction.
15603 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3615604 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3815605 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615606 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
15607 MockRead(SYNCHRONOUS, "hello world"),
15608 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3815609 };
15610
[email protected]8e6441ca2010-08-19 05:56:3815611 HttpRequestInfo request;
15612 request.method = "GET";
bncce36dca22015-04-21 22:11:2315613 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015614 request.traffic_annotation =
15615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3815616
danakj1fd259a02016-04-16 03:17:0915617 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5815618 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1915619 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2715620
Ryan Sleevib8d7ea02018-05-07 20:01:0115621 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3815622 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0715623 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3815624
[email protected]49639fa2011-12-20 23:22:4115625 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3815626
vishal.b62985ca92015-04-17 08:45:5115627 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4115628 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115629 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3815630 trans.reset(); // Cancel the transaction here.
15631
fdoray92e35a72016-06-10 15:54:5515632 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3015633}
15634
[email protected]ecab6e052014-05-16 14:58:1215635// Test that if a transaction is cancelled after receiving the headers, the
15636// stream is drained properly and added back to the socket pool. The main
15637// purpose of this test is to make sure that an HttpStreamParser can be read
15638// from after the HttpNetworkTransaction and the objects it owns have been
15639// deleted.
15640// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0115641TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1215642 MockRead data_reads[] = {
15643 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
15644 MockRead(ASYNC, "Content-Length: 2\r\n"),
15645 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
15646 MockRead(ASYNC, "1"),
15647 // 2 async reads are necessary to trigger a ReadResponseBody call after the
15648 // HttpNetworkTransaction has been deleted.
15649 MockRead(ASYNC, "2"),
15650 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
15651 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115652 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1215653 session_deps_.socket_factory->AddSocketDataProvider(&data);
15654
danakj1fd259a02016-04-16 03:17:0915655 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1215656
15657 {
15658 HttpRequestInfo request;
15659 request.method = "GET";
bncce36dca22015-04-21 22:11:2315660 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015661 request.traffic_annotation =
15662 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1215663
dcheng48459ac22014-08-26 00:46:4115664 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1215665 TestCompletionCallback callback;
15666
tfarina42834112016-09-22 13:38:2015667 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115668 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1215669 callback.WaitForResult();
15670
15671 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215672 ASSERT_TRUE(response);
15673 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1215674 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15675
15676 // The transaction and HttpRequestInfo are deleted.
15677 }
15678
15679 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5515680 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1215681
15682 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4115683 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1215684}
15685
[email protected]76a505b2010-08-25 06:23:0015686// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0115687TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915688 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915689 ProxyResolutionService::CreateFixedFromPacResult(
15690 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115691 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715692 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915693 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015694
[email protected]76a505b2010-08-25 06:23:0015695 HttpRequestInfo request;
15696 request.method = "GET";
bncce36dca22015-04-21 22:11:2315697 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015698 request.traffic_annotation =
15699 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015700
15701 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2315702 MockWrite(
15703 "GET http://www.example.org/ HTTP/1.1\r\n"
15704 "Host: www.example.org\r\n"
15705 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015706 };
15707
15708 MockRead data_reads1[] = {
15709 MockRead("HTTP/1.1 200 OK\r\n"),
15710 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15711 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615712 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015713 };
15714
Ryan Sleevib8d7ea02018-05-07 20:01:0115715 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715716 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0015717
[email protected]49639fa2011-12-20 23:22:4115718 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015719
bnc691fda62016-08-12 00:43:1615720 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915721 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615722 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915723 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15724 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015725
bnc691fda62016-08-12 00:43:1615726 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115727 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015728
15729 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115730 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0015731
bnc691fda62016-08-12 00:43:1615732 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215733 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015734
15735 EXPECT_TRUE(response->headers->IsKeepAlive());
15736 EXPECT_EQ(200, response->headers->response_code());
15737 EXPECT_EQ(100, response->headers->GetContentLength());
15738 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715739 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15740 HostPortPair::FromString("myproxy:70")),
15741 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915742 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15743 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15744 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0015745 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2015746
15747 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615748 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015749 TestLoadTimingNotReusedWithPac(load_timing_info,
15750 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0015751}
15752
15753// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0115754TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915755 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915756 ProxyResolutionService::CreateFixedFromPacResult(
15757 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115758 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715759 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915760 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015761
[email protected]76a505b2010-08-25 06:23:0015762 HttpRequestInfo request;
15763 request.method = "GET";
bncce36dca22015-04-21 22:11:2315764 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015765 request.traffic_annotation =
15766 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015767
15768 // Since we have proxy, should try to establish tunnel.
15769 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715770 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15771 "Host: www.example.org:443\r\n"
15772 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015773
rsleevidb16bb02015-11-12 23:47:1715774 MockWrite("GET / HTTP/1.1\r\n"
15775 "Host: www.example.org\r\n"
15776 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015777 };
15778
15779 MockRead data_reads1[] = {
15780 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15781
15782 MockRead("HTTP/1.1 200 OK\r\n"),
15783 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15784 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615785 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015786 };
15787
Ryan Sleevib8d7ea02018-05-07 20:01:0115788 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715789 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615790 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015792
[email protected]49639fa2011-12-20 23:22:4115793 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015794
bnc691fda62016-08-12 00:43:1615795 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915796 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615797 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915798 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15799 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015800
bnc691fda62016-08-12 00:43:1615801 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115802 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015803
15804 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115805 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415806 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015807 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015808 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15809 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015810 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015811 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015812 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15813 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015814
bnc691fda62016-08-12 00:43:1615815 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215816 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015817
15818 EXPECT_TRUE(response->headers->IsKeepAlive());
15819 EXPECT_EQ(200, response->headers->response_code());
15820 EXPECT_EQ(100, response->headers->GetContentLength());
15821 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15822 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715823 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15824 HostPortPair::FromString("myproxy:70")),
15825 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915826 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15827 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15828 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2015829
15830 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615831 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015832 TestLoadTimingNotReusedWithPac(load_timing_info,
15833 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0015834}
15835
rsleevidb16bb02015-11-12 23:47:1715836// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
15837// literal host.
bncd16676a2016-07-20 16:23:0115838TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5915839 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915840 ProxyResolutionService::CreateFixedFromPacResult(
15841 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715842 BoundTestNetLog log;
15843 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915844 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1715845
15846 HttpRequestInfo request;
15847 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1515848 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e62018-02-07 07:41:1015849 request.traffic_annotation =
15850 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715851
15852 // Since we have proxy, should try to establish tunnel.
15853 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1515854 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
15855 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1715856 "Proxy-Connection: keep-alive\r\n\r\n"),
15857
15858 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1515859 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1715860 "Connection: keep-alive\r\n\r\n"),
15861 };
15862
15863 MockRead data_reads1[] = {
15864 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15865
15866 MockRead("HTTP/1.1 200 OK\r\n"),
15867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15868 MockRead("Content-Length: 100\r\n\r\n"),
15869 MockRead(SYNCHRONOUS, OK),
15870 };
15871
Ryan Sleevib8d7ea02018-05-07 20:01:0115872 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1715873 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15874 SSLSocketDataProvider ssl(ASYNC, OK);
15875 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15876
15877 TestCompletionCallback callback1;
15878
bnc691fda62016-08-12 00:43:1615879 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1715880
bnc691fda62016-08-12 00:43:1615881 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115882 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1715883
15884 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115885 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415886 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1715887 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015888 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15889 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715890 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015891 entries, pos,
15892 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15893 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715894
bnc691fda62016-08-12 00:43:1615895 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215896 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1715897
15898 EXPECT_TRUE(response->headers->IsKeepAlive());
15899 EXPECT_EQ(200, response->headers->response_code());
15900 EXPECT_EQ(100, response->headers->GetContentLength());
15901 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15902 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715903 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15904 HostPortPair::FromString("myproxy:70")),
15905 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1715906
15907 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615908 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1715909 TestLoadTimingNotReusedWithPac(load_timing_info,
15910 CONNECT_TIMING_HAS_SSL_TIMES);
15911}
15912
[email protected]76a505b2010-08-25 06:23:0015913// Test a basic HTTPS GET request through a proxy, but the server hangs up
15914// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0115915TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4915916 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15917 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115918 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715919 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915920 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015921
[email protected]76a505b2010-08-25 06:23:0015922 HttpRequestInfo request;
15923 request.method = "GET";
bncce36dca22015-04-21 22:11:2315924 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015925 request.traffic_annotation =
15926 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015927
15928 // Since we have proxy, should try to establish tunnel.
15929 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715930 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15931 "Host: www.example.org:443\r\n"
15932 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015933
rsleevidb16bb02015-11-12 23:47:1715934 MockWrite("GET / HTTP/1.1\r\n"
15935 "Host: www.example.org\r\n"
15936 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015937 };
15938
15939 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0015940 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615941 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0015942 };
15943
Ryan Sleevib8d7ea02018-05-07 20:01:0115944 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715945 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615946 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715947 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015948
[email protected]49639fa2011-12-20 23:22:4115949 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015950
bnc691fda62016-08-12 00:43:1615951 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5015952
bnc691fda62016-08-12 00:43:1615953 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115954 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015955
15956 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115957 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5415958 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015959 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015960 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15961 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015962 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015963 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015964 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15965 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015966}
15967
[email protected]749eefa82010-09-13 22:14:0315968// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0115969TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1315970 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4915971 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115972 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0315973
Raul Tambre94493c652019-03-11 17:18:3515974 spdy::SpdySerializedFrame resp(
15975 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315976 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0315977 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115978 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0315979 };
15980
Ryan Sleevib8d7ea02018-05-07 20:01:0115981 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715982 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0315983
[email protected]8ddf8322012-02-23 18:08:0615984 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615985 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715986 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0315987
danakj1fd259a02016-04-16 03:17:0915988 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315989
15990 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315991 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015992 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115993 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3415994 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
15995 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2715996 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5215997 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0315998
15999 HttpRequestInfo request;
16000 request.method = "GET";
bncce36dca22015-04-21 22:11:2316001 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016002 request.traffic_annotation =
16003 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0316004
bnc691fda62016-08-12 00:43:1616005 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0316006
[email protected]41d64e82013-07-03 22:44:2616007 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016008 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116009 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16010 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0316011}
16012
[email protected]73b8dd222010-11-11 19:55:2416013// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1616014// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0216015void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0716016 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2916017 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716018 request_info.url = GURL("https://www.example.com/");
16019 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916020 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016021 request_info.traffic_annotation =
16022 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716023
[email protected]8ddf8322012-02-23 18:08:0616024 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2916025 MockWrite data_writes[] = {
16026 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2416027 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116028 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0716029 session_deps_.socket_factory->AddSocketDataProvider(&data);
16030 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2416031
danakj1fd259a02016-04-16 03:17:0916032 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616033 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2416034
[email protected]49639fa2011-12-20 23:22:4116035 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016036 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2916037 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2416038 rv = callback.WaitForResult();
16039 ASSERT_EQ(error, rv);
16040}
16041
bncd16676a2016-07-20 16:23:0116042TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2416043 // Just check a grab bag of cert errors.
16044 static const int kErrors[] = {
16045 ERR_CERT_COMMON_NAME_INVALID,
16046 ERR_CERT_AUTHORITY_INVALID,
16047 ERR_CERT_DATE_INVALID,
16048 };
Avi Drissman4365a4782018-12-28 19:26:2416049 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0616050 CheckErrorIsPassedBack(kErrors[i], ASYNC);
16051 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2416052 }
16053}
16054
[email protected]bd0b6772011-01-11 19:59:3016055// Ensure that a client certificate is removed from the SSL client auth
16056// cache when:
16057// 1) No proxy is involved.
16058// 2) TLS False Start is disabled.
16059// 3) The initial TLS handshake requests a client certificate.
16060// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116061TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916062 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716063 request_info.url = GURL("https://www.example.com/");
16064 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916065 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016066 request_info.traffic_annotation =
16067 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716068
David Benjamin1c4b6d012019-07-08 17:12:5716069 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116070 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016071
16072 // [ssl_]data1 contains the data for the first SSL handshake. When a
16073 // CertificateRequest is received for the first time, the handshake will
16074 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2916075 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016076 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716077 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116078 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716079 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016080
16081 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
16082 // False Start is not being used, the result of the SSL handshake will be
16083 // returned as part of the SSLClientSocket::Connect() call. This test
16084 // matches the result of a server sending a handshake_failure alert,
16085 // rather than a Finished message, because it requires a client
16086 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2916087 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3016088 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716089 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0116090 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0716091 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016092
16093 // [ssl_]data3 contains the data for the third SSL handshake. When a
16094 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1316095 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
16096 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3016097 // of the HttpNetworkTransaction. Because this test failure is due to
16098 // requiring a client certificate, this fallback handshake should also
16099 // fail.
ttuttle859dc7a2015-04-23 19:42:2916100 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1316101 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3016102 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716103 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116104 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0716105 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016106
[email protected]80c75f682012-05-26 16:22:1716107 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
16108 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4216109 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
16110 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1716111 // of the HttpNetworkTransaction. Because this test failure is due to
16112 // requiring a client certificate, this fallback handshake should also
16113 // fail.
ttuttle859dc7a2015-04-23 19:42:2916114 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1716115 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716116 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116117 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0716118 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716119
danakj1fd259a02016-04-16 03:17:0916120 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616121 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016122
[email protected]bd0b6772011-01-11 19:59:3016123 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4116124 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016125 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116126 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016127
16128 // Complete the SSL handshake, which should abort due to requiring a
16129 // client certificate.
16130 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116131 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016132
16133 // Indicate that no certificate should be supplied. From the perspective
16134 // of SSLClientCertCache, NULL is just as meaningful as a real
16135 // certificate, so this is the same as supply a
16136 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516137 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116138 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016139
16140 // Ensure the certificate was added to the client auth cache before
16141 // allowing the connection to continue restarting.
16142 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416143 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116144 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416145 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216146 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016147
16148 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716149 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16150 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016151 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116152 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016153
16154 // Ensure that the client certificate is removed from the cache on a
16155 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116156 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416157 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016158}
16159
16160// Ensure that a client certificate is removed from the SSL client auth
16161// cache when:
16162// 1) No proxy is involved.
16163// 2) TLS False Start is enabled.
16164// 3) The initial TLS handshake requests a client certificate.
16165// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116166TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916167 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716168 request_info.url = GURL("https://www.example.com/");
16169 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916170 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016171 request_info.traffic_annotation =
16172 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716173
David Benjamin1c4b6d012019-07-08 17:12:5716174 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116175 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016176
16177 // When TLS False Start is used, SSLClientSocket::Connect() calls will
16178 // return successfully after reading up to the peer's Certificate message.
16179 // This is to allow the caller to call SSLClientSocket::Write(), which can
16180 // enqueue application data to be sent in the same packet as the
16181 // ChangeCipherSpec and Finished messages.
16182 // The actual handshake will be finished when SSLClientSocket::Read() is
16183 // called, which expects to process the peer's ChangeCipherSpec and
16184 // Finished messages. If there was an error negotiating with the peer,
16185 // such as due to the peer requiring a client certificate when none was
16186 // supplied, the alert sent by the peer won't be processed until Read() is
16187 // called.
16188
16189 // Like the non-False Start case, when a client certificate is requested by
16190 // the peer, the handshake is aborted during the Connect() call.
16191 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2916192 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016193 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116195 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716196 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016197
16198 // When a client certificate is supplied, Connect() will not be aborted
16199 // when the peer requests the certificate. Instead, the handshake will
16200 // artificially succeed, allowing the caller to write the HTTP request to
16201 // the socket. The handshake messages are not processed until Read() is
16202 // called, which then detects that the handshake was aborted, due to the
16203 // peer sending a handshake_failure because it requires a client
16204 // certificate.
ttuttle859dc7a2015-04-23 19:42:2916205 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016206 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716207 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2916208 MockRead data2_reads[] = {
16209 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3016210 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116211 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716212 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016213
16214 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1716215 // the data for the SSL handshake once the TLSv1.1 connection falls back to
16216 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916217 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016218 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716219 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116220 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716221 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016222
[email protected]80c75f682012-05-26 16:22:1716223 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
16224 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916225 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1716226 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716227 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116228 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716229 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716230
[email protected]7799de12013-05-30 05:52:5116231 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2916232 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5116233 ssl_data5.cert_request_info = cert_request.get();
16234 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0116235 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5116236 session_deps_.socket_factory->AddSocketDataProvider(&data5);
16237
danakj1fd259a02016-04-16 03:17:0916238 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616239 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016240
[email protected]bd0b6772011-01-11 19:59:3016241 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4116242 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016243 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116244 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016245
16246 // Complete the SSL handshake, which should abort due to requiring a
16247 // client certificate.
16248 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116249 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016250
16251 // Indicate that no certificate should be supplied. From the perspective
16252 // of SSLClientCertCache, NULL is just as meaningful as a real
16253 // certificate, so this is the same as supply a
16254 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516255 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116256 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016257
16258 // Ensure the certificate was added to the client auth cache before
16259 // allowing the connection to continue restarting.
16260 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416261 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116262 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416263 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216264 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016265
[email protected]bd0b6772011-01-11 19:59:3016266 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716267 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16268 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016269 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116270 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016271
16272 // Ensure that the client certificate is removed from the cache on a
16273 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116274 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416275 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016276}
16277
[email protected]8c405132011-01-11 22:03:1816278// Ensure that a client certificate is removed from the SSL client auth
16279// cache when:
16280// 1) An HTTPS proxy is involved.
16281// 3) The HTTPS proxy requests a client certificate.
16282// 4) The client supplies an invalid/unacceptable certificate for the
16283// proxy.
bncd16676a2016-07-20 16:23:0116284TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4916285 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
16286 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116287 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716288 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1816289
David Benjamin3b94b0f2019-04-25 23:07:5216290 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116291 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1816292
David Benjamin3b94b0f2019-04-25 23:07:5216293 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
16294 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2916295 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1816296 requests[0].url = GURL("https://www.example.com/");
16297 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916298 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016299 requests[0].traffic_annotation =
16300 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816301
David Benjamin3b94b0f2019-04-25 23:07:5216302 // HTTPS requests are tunneled.
16303 MockWrite https_writes[] = {
16304 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
16305 "Host: www.example.com:443\r\n"
16306 "Proxy-Connection: keep-alive\r\n\r\n"),
16307 };
16308
[email protected]8c405132011-01-11 22:03:1816309 requests[1].url = GURL("http://www.example.com/");
16310 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916311 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016312 requests[1].traffic_annotation =
16313 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816314
David Benjamin3b94b0f2019-04-25 23:07:5216315 // HTTP requests are not.
16316 MockWrite http_writes[] = {
16317 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
16318 "Host: www.example.com\r\n"
16319 "Proxy-Connection: keep-alive\r\n\r\n"),
16320 };
[email protected]8c405132011-01-11 22:03:1816321
David Benjamin3b94b0f2019-04-25 23:07:5216322 // When the server rejects the client certificate, it will close the
16323 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
16324 // TLS 1.2 with False Start), the error is returned out of the first Read().
16325 for (bool reject_in_connect : {true, false}) {
16326 SCOPED_TRACE(reject_in_connect);
16327 // Client certificate errors are typically signaled with
16328 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
16329 // protocol error.
16330 for (Error reject_error :
16331 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
16332 SCOPED_TRACE(reject_error);
16333 // Tunneled and non-tunneled requests are handled differently. Test both.
16334 for (const HttpRequestInfo& request : requests) {
16335 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1816336
David Benjamin3b94b0f2019-04-25 23:07:5216337 session_deps_.socket_factory =
16338 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1816339
David Benjamin3b94b0f2019-04-25 23:07:5216340 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
16341 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
16342 // for proxies. Rather than represending the endpoint
16343 // (www.example.com:443), they represent failures with the HTTPS proxy
16344 // (proxy:70).
16345 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
16346 ssl_data1.cert_request_info = cert_request.get();
16347 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16348 StaticSocketDataProvider data1;
16349 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1816350
David Benjamin3b94b0f2019-04-25 23:07:5216351 base::Optional<SSLSocketDataProvider> ssl_data2;
16352 base::Optional<StaticSocketDataProvider> data2;
16353 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
16354 if (reject_in_connect) {
16355 ssl_data2.emplace(ASYNC, reject_error);
16356 // There are no reads or writes.
16357 data2.emplace();
16358 } else {
16359 ssl_data2.emplace(ASYNC, OK);
16360 // We will get one Write() in before observing the error in Read().
16361 if (request.url.SchemeIsCryptographic()) {
16362 data2.emplace(error_in_read, https_writes);
16363 } else {
16364 data2.emplace(error_in_read, http_writes);
16365 }
16366 }
16367 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1816368
David Benjamin3b94b0f2019-04-25 23:07:5216369 session_deps_.socket_factory->AddSSLSocketDataProvider(
16370 &ssl_data2.value());
16371 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1816372
David Benjamin3b94b0f2019-04-25 23:07:5216373 std::unique_ptr<HttpNetworkSession> session =
16374 CreateSession(&session_deps_);
16375 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16376
16377 // Begin the SSL handshake with the proxy.
16378 TestCompletionCallback callback;
16379 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16380 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16381
16382 // Complete the SSL handshake, which should abort due to requiring a
16383 // client certificate.
16384 rv = callback.WaitForResult();
16385 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16386
16387 // Indicate that no certificate should be supplied. From the
16388 // perspective of SSLClientCertCache, NULL is just as meaningful as a
16389 // real certificate, so this is the same as supply a
16390 // legitimate-but-unacceptable certificate.
16391 rv =
16392 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
16393 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16394
16395 // Ensure the certificate was added to the client auth cache before
16396 // allowing the connection to continue restarting.
16397 scoped_refptr<X509Certificate> client_cert;
16398 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116399 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216400 HostPortPair("proxy", 70), &client_cert, &client_private_key));
16401 ASSERT_FALSE(client_cert);
16402 // Ensure the certificate was NOT cached for the endpoint. This only
16403 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4116404 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216405 HostPortPair("www.example.com", 443), &client_cert,
16406 &client_private_key));
16407
16408 // Restart the handshake. This will consume ssl_data2. The result code
16409 // is checked against what ssl_data2 should return.
16410 rv = callback.WaitForResult();
16411 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
16412 IsError(reject_error)));
16413
16414 // Now that the new handshake has failed, ensure that the client
16415 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4116416 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216417 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4116418 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216419 HostPortPair("www.example.com", 443), &client_cert,
16420 &client_private_key));
16421 }
16422 }
[email protected]8c405132011-01-11 22:03:1816423 }
16424}
16425
David Benjamin1a0566082019-04-30 07:36:1916426// Test that HttpNetworkTransaction correctly handles (mocked) certificate
16427// requests during a TLS renegotiation.
16428TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
16429 HttpRequestInfo request_info;
16430 request_info.url = GURL("https://www.example.com/");
16431 request_info.method = "GET";
16432 request_info.load_flags = LOAD_NORMAL;
16433 request_info.traffic_annotation =
16434 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16435
16436 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
16437 cert_request->host_and_port = HostPortPair("www.example.com", 443);
16438
16439 std::unique_ptr<FakeClientCertIdentity> identity =
16440 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
16441 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
16442 ASSERT_TRUE(identity);
16443
16444 // The first connection's handshake succeeds, but we get
16445 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
16446 SSLSocketDataProvider ssl_data1(ASYNC, OK);
16447 ssl_data1.cert_request_info = cert_request.get();
16448 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16449 MockWrite data1_writes[] = {
16450 MockWrite("GET / HTTP/1.1\r\n"
16451 "Host: www.example.com\r\n"
16452 "Connection: keep-alive\r\n\r\n"),
16453 };
16454 MockRead data1_reads[] = {
16455 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
16456 };
16457 StaticSocketDataProvider data1(data1_reads, data1_writes);
16458 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16459
16460 // After supplying with certificate, we restart the request from the top,
16461 // which succeeds this time.
16462 SSLSocketDataProvider ssl_data2(ASYNC, OK);
16463 ssl_data2.expected_send_client_cert = true;
16464 ssl_data2.expected_client_cert = identity->certificate();
16465 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
16466 MockWrite data2_writes[] = {
16467 MockWrite("GET / HTTP/1.1\r\n"
16468 "Host: www.example.com\r\n"
16469 "Connection: keep-alive\r\n\r\n"),
16470 };
16471 MockRead data2_reads[] = {
16472 MockRead("HTTP/1.1 200 OK\r\n"
16473 "Content-Length: 0\r\n\r\n"),
16474 };
16475 StaticSocketDataProvider data2(data2_reads, data2_writes);
16476 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16477
16478 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
16479 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16480
16481 TestCompletionCallback callback;
16482 int rv = callback.GetResult(
16483 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
16484 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16485
16486 rv = trans.RestartWithCertificate(identity->certificate(),
16487 identity->ssl_private_key(),
16488 callback.callback());
16489 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16490
16491 // Ensure the certificate was added to the client auth cache
16492 // allowing the connection to continue restarting.
16493 scoped_refptr<X509Certificate> client_cert;
16494 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116495 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916496 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16497 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16498
16499 // Complete the handshake. The request now succeeds.
16500 rv = callback.WaitForResult();
16501 ASSERT_THAT(rv, IsError(OK));
16502 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
16503
16504 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4116505 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916506 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16507 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16508}
16509
bncd16676a2016-07-20 16:23:0116510TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4616511 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916512 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916513 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616514
bnc032658ba2016-09-26 18:17:1516515 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616516
Ryan Hamilton0239aac2018-05-19 00:03:1316517 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916518 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816519 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316520 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716521 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616522 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116523 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616524 };
Ryan Hamilton0239aac2018-05-19 00:03:1316525 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516526 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316527 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116528 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316529 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516530 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316531 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116532 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616533 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116534 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16535 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316536 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616537 };
16538
eroman36d84e54432016-03-17 03:23:0216539 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216540 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116541 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716542 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616543
[email protected]aa22b242011-11-16 18:58:2916544 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616545 HttpRequestInfo request1;
16546 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316547 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616548 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016549 request1.traffic_annotation =
16550 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016551 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616552
tfarina42834112016-09-22 13:38:2016553 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116554 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16555 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616556
16557 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216558 ASSERT_TRUE(response);
16559 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216560 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616561
16562 std::string response_data;
robpercival214763f2016-07-01 23:27:0116563 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616564 EXPECT_EQ("hello!", response_data);
16565
bnca4d611d2016-09-22 19:55:3716566 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316567 rv = session_deps_.host_resolver->LoadIntoCache(
16568 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116569 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616570
16571 HttpRequestInfo request2;
16572 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716573 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616574 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016575 request2.traffic_annotation =
16576 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016577 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616578
tfarina42834112016-09-22 13:38:2016579 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116580 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16581 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616582
16583 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216584 ASSERT_TRUE(response);
16585 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216586 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616587 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216588 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116589 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616590 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616591}
16592
bncd16676a2016-07-20 16:23:0116593TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0216594 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916595 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916596 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0216597
bnc032658ba2016-09-26 18:17:1516598 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0216599
Ryan Hamilton0239aac2018-05-19 00:03:1316600 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916601 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816602 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316603 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716604 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0216605 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116606 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0216607 };
Ryan Hamilton0239aac2018-05-19 00:03:1316608 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516609 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316610 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116611 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316612 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516613 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316614 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116615 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0216616 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116617 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16618 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316619 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0216620 };
16621
eroman36d84e54432016-03-17 03:23:0216622 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216623 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116624 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716625 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0216626
16627 TestCompletionCallback callback;
16628 HttpRequestInfo request1;
16629 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316630 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0216631 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016632 request1.traffic_annotation =
16633 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016634 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216635
tfarina42834112016-09-22 13:38:2016636 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116637 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16638 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216639
16640 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216641 ASSERT_TRUE(response);
16642 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216643 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216644
16645 std::string response_data;
robpercival214763f2016-07-01 23:27:0116646 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216647 EXPECT_EQ("hello!", response_data);
16648
16649 HttpRequestInfo request2;
16650 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716651 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0216652 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016653 request2.traffic_annotation =
16654 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016655 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0216656
tfarina42834112016-09-22 13:38:2016657 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116658 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16659 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216660
16661 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216662 ASSERT_TRUE(response);
16663 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216664 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0216665 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216666 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116667 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0216668 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0216669}
16670
bnc8016c1f2017-03-31 02:11:2916671// Regression test for https://crbug.com/546991.
16672// The server might not be able to serve an IP pooled request, and might send a
16673// 421 Misdirected Request response status to indicate this.
16674// HttpNetworkTransaction should reset the request and retry without IP pooling.
16675TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
16676 // Two hosts resolve to the same IP address.
16677 const std::string ip_addr = "1.2.3.4";
16678 IPAddress ip;
16679 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16680 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16681
Jeremy Roman0579ed62017-08-29 15:56:1916682 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2916683 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16684 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16685
16686 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16687
16688 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316689 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2916690 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16691 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316692 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2916693 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316694 spdy::SpdySerializedFrame rst(
16695 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2916696 MockWrite writes1[] = {
16697 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16698 CreateMockWrite(rst, 6),
16699 };
16700
16701 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316702 spdy::SpdySerializedFrame resp1(
16703 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16704 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16705 spdy::SpdyHeaderBlock response_headers;
16706 response_headers[spdy::kHttp2StatusHeader] = "421";
16707 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2916708 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
16709 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16710 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16711
16712 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116713 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2916714 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16715
16716 AddSSLSocketData();
16717
16718 // Retry the second request on a second connection.
16719 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316720 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2916721 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16722 MockWrite writes2[] = {
16723 CreateMockWrite(req3, 0),
16724 };
16725
Ryan Hamilton0239aac2018-05-19 00:03:1316726 spdy::SpdySerializedFrame resp3(
16727 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
16728 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2916729 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16730 MockRead(ASYNC, 0, 3)};
16731
16732 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116733 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2916734 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16735
16736 AddSSLSocketData();
16737
16738 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316739 int rv = session_deps_.host_resolver->LoadIntoCache(
16740 HostPortPair("mail.example.com", 443), base::nullopt);
bnc8016c1f2017-03-31 02:11:2916741 EXPECT_THAT(rv, IsOk());
16742
16743 HttpRequestInfo request1;
16744 request1.method = "GET";
16745 request1.url = GURL("https://www.example.org/");
16746 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016747 request1.traffic_annotation =
16748 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916749 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16750
Eric Orthf4db66a2019-02-19 21:35:3316751 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2916752 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16753 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16754 rv = callback.WaitForResult();
16755 EXPECT_THAT(rv, IsOk());
16756
16757 const HttpResponseInfo* response = trans1.GetResponseInfo();
16758 ASSERT_TRUE(response);
16759 ASSERT_TRUE(response->headers);
16760 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16761 EXPECT_TRUE(response->was_fetched_via_spdy);
16762 EXPECT_TRUE(response->was_alpn_negotiated);
16763 std::string response_data;
16764 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16765 EXPECT_EQ("hello!", response_data);
16766
16767 HttpRequestInfo request2;
16768 request2.method = "GET";
16769 request2.url = GURL("https://mail.example.org/");
16770 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016771 request2.traffic_annotation =
16772 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916773 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16774
16775 BoundTestNetLog log;
16776 rv = trans2.Start(&request2, callback.callback(), log.bound());
16777 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16778 rv = callback.WaitForResult();
16779 EXPECT_THAT(rv, IsOk());
16780
16781 response = trans2.GetResponseInfo();
16782 ASSERT_TRUE(response);
16783 ASSERT_TRUE(response->headers);
16784 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16785 EXPECT_TRUE(response->was_fetched_via_spdy);
16786 EXPECT_TRUE(response->was_alpn_negotiated);
16787 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16788 EXPECT_EQ("hello!", response_data);
16789
Eric Roman79cc7552019-07-19 02:17:5416790 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5916791 ExpectLogContainsSomewhere(
16792 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2916793 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5916794}
16795
16796// Test that HTTP 421 responses are properly returned to the caller if received
16797// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
16798// portions of the response.
16799TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
16800 // Two hosts resolve to the same IP address.
16801 const std::string ip_addr = "1.2.3.4";
16802 IPAddress ip;
16803 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16804 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16805
Jeremy Roman0579ed62017-08-29 15:56:1916806 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5916807 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16808 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16809
16810 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16811
16812 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316813 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5916814 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16815 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316816 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5916817 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316818 spdy::SpdySerializedFrame rst(
16819 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5916820 MockWrite writes1[] = {
16821 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16822 CreateMockWrite(rst, 6),
16823 };
16824
16825 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316826 spdy::SpdySerializedFrame resp1(
16827 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16828 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16829 spdy::SpdyHeaderBlock response_headers;
16830 response_headers[spdy::kHttp2StatusHeader] = "421";
16831 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5916832 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
16833 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16834 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16835
16836 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116837 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5916838 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16839
16840 AddSSLSocketData();
16841
16842 // Retry the second request on a second connection. It returns 421 Misdirected
16843 // Retry again.
16844 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316845 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5916846 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16847 MockWrite writes2[] = {
16848 CreateMockWrite(req3, 0),
16849 };
16850
Ryan Hamilton0239aac2018-05-19 00:03:1316851 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5916852 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1316853 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5916854 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16855 MockRead(ASYNC, 0, 3)};
16856
16857 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116858 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5916859 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16860
16861 AddSSLSocketData();
16862
16863 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316864 int rv = session_deps_.host_resolver->LoadIntoCache(
16865 HostPortPair("mail.example.com", 443), base::nullopt);
davidbence688ae2017-05-04 15:12:5916866 EXPECT_THAT(rv, IsOk());
16867
16868 HttpRequestInfo request1;
16869 request1.method = "GET";
16870 request1.url = GURL("https://www.example.org/");
16871 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016872 request1.traffic_annotation =
16873 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916874 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16875
Eric Orthf4db66a2019-02-19 21:35:3316876 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5916877 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16878 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16879 rv = callback.WaitForResult();
16880 EXPECT_THAT(rv, IsOk());
16881
16882 const HttpResponseInfo* response = trans1.GetResponseInfo();
16883 ASSERT_TRUE(response);
16884 ASSERT_TRUE(response->headers);
16885 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16886 EXPECT_TRUE(response->was_fetched_via_spdy);
16887 EXPECT_TRUE(response->was_alpn_negotiated);
16888 std::string response_data;
16889 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16890 EXPECT_EQ("hello!", response_data);
16891
16892 HttpRequestInfo request2;
16893 request2.method = "GET";
16894 request2.url = GURL("https://mail.example.org/");
16895 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016896 request2.traffic_annotation =
16897 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916898 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16899
16900 BoundTestNetLog log;
16901 rv = trans2.Start(&request2, callback.callback(), log.bound());
16902 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16903 rv = callback.WaitForResult();
16904 EXPECT_THAT(rv, IsOk());
16905
16906 // After a retry, the 421 Misdirected Request is reported back up to the
16907 // caller.
16908 response = trans2.GetResponseInfo();
16909 ASSERT_TRUE(response);
16910 ASSERT_TRUE(response->headers);
16911 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
16912 EXPECT_TRUE(response->was_fetched_via_spdy);
16913 EXPECT_TRUE(response->was_alpn_negotiated);
16914 EXPECT_TRUE(response->ssl_info.cert);
16915 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16916 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2916917}
16918
bncd16676a2016-07-20 16:23:0116919TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1316920 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3416921 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
16922 session_deps_.host_resolver =
16923 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0916924 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616925
bnc032658ba2016-09-26 18:17:1516926 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616927
Ryan Hamilton0239aac2018-05-19 00:03:1316928 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916929 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816930 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316931 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716932 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616933 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116934 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616935 };
Ryan Hamilton0239aac2018-05-19 00:03:1316936 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516937 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316938 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116939 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316940 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516941 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316942 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116943 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616944 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116945 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16946 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316947 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616948 };
16949
eroman36d84e54432016-03-17 03:23:0216950 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216951 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116952 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716953 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616954
[email protected]aa22b242011-11-16 18:58:2916955 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616956 HttpRequestInfo request1;
16957 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316958 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616959 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016960 request1.traffic_annotation =
16961 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016962 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616963
tfarina42834112016-09-22 13:38:2016964 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116965 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16966 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616967
16968 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216969 ASSERT_TRUE(response);
16970 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216971 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616972
16973 std::string response_data;
robpercival214763f2016-07-01 23:27:0116974 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616975 EXPECT_EQ("hello!", response_data);
16976
16977 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316978 rv = session_deps_.host_resolver->LoadIntoCache(
16979 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116980 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616981
16982 HttpRequestInfo request2;
16983 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716984 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616985 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016986 request2.traffic_annotation =
16987 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016988 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616989
tfarina42834112016-09-22 13:38:2016990 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116991 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16992 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616993
16994 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216995 ASSERT_TRUE(response);
16996 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216997 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616998 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216999 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117000 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617001 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617002}
17003
bncd16676a2016-07-20 16:23:0117004TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2317005 const std::string https_url = "https://www.example.org:8080/";
17006 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417007
17008 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1317009 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917010 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0417011
17012 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117013 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0417014 };
17015
Raul Tambre94493c652019-03-11 17:18:3517016 spdy::SpdySerializedFrame resp1(
17017 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317018 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117019 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5917020 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0417021
Ryan Sleevib8d7ea02018-05-07 20:01:0117022 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417023 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717024 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417025
17026 // HTTP GET for the HTTP URL
17027 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1317028 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3417029 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2317030 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3417031 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0417032 };
17033
17034 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1317035 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
17036 MockRead(ASYNC, 2, "hello"),
17037 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0417038 };
17039
Ryan Sleevib8d7ea02018-05-07 20:01:0117040 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0417041
[email protected]8450d722012-07-02 19:14:0417042 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617043 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0717044 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17045 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17046 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0417047
danakj1fd259a02016-04-16 03:17:0917048 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0417049
17050 // Start the first transaction to set up the SpdySession
17051 HttpRequestInfo request1;
17052 request1.method = "GET";
17053 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417054 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017055 request1.traffic_annotation =
17056 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017057 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417058 TestCompletionCallback callback1;
17059 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017060 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517061 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417062
robpercival214763f2016-07-01 23:27:0117063 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417064 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17065
17066 // Now, start the HTTP request
17067 HttpRequestInfo request2;
17068 request2.method = "GET";
17069 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417070 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017071 request2.traffic_annotation =
17072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017073 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417074 TestCompletionCallback callback2;
17075 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017076 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517077 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417078
robpercival214763f2016-07-01 23:27:0117079 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417080 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17081}
17082
bnc5452e2a2015-05-08 16:27:4217083// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
17084// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0117085TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2517086 url::SchemeHostPort server("https", "www.example.org", 443);
17087 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4217088
bnc8bef8da22016-05-30 01:28:2517089 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4217090 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617091 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217092 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17093
17094 // No data should be read from the alternative, because HTTP/1.1 is
17095 // negotiated.
17096 StaticSocketDataProvider data;
17097 session_deps_.socket_factory->AddSocketDataProvider(&data);
17098
17099 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4617100 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4217101 // mocked. This way the request relies on the alternate Job.
17102 StaticSocketDataProvider data_refused;
17103 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17104 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17105
zhongyi3d4a55e72016-04-22 20:36:4617106 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917107 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017108 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217109 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117110 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217111 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117112 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717113 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217114
bnc5452e2a2015-05-08 16:27:4217115 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4617116 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217117 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2517118 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e62018-02-07 07:41:1017119 request.traffic_annotation =
17120 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217121 TestCompletionCallback callback;
17122
17123 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5217124 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2017125 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5217126 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4217127}
17128
bnc40448a532015-05-11 19:13:1417129// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4617130// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1417131// succeeds, the request should succeed, even if the latter fails because
17132// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0117133TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2517134 url::SchemeHostPort server("https", "www.example.org", 443);
17135 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1417136
17137 // Negotiate HTTP/1.1 with alternative.
17138 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617139 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417140 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
17141
17142 // No data should be read from the alternative, because HTTP/1.1 is
17143 // negotiated.
17144 StaticSocketDataProvider data;
17145 session_deps_.socket_factory->AddSocketDataProvider(&data);
17146
zhongyi3d4a55e72016-04-22 20:36:4617147 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1417148 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617149 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417150 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
17151
17152 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2517153 MockWrite("GET / HTTP/1.1\r\n"
17154 "Host: www.example.org\r\n"
17155 "Connection: keep-alive\r\n\r\n"),
17156 MockWrite("GET /second HTTP/1.1\r\n"
17157 "Host: www.example.org\r\n"
17158 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1417159 };
17160
17161 MockRead http_reads[] = {
17162 MockRead("HTTP/1.1 200 OK\r\n"),
17163 MockRead("Content-Type: text/html\r\n"),
17164 MockRead("Content-Length: 6\r\n\r\n"),
17165 MockRead("foobar"),
17166 MockRead("HTTP/1.1 200 OK\r\n"),
17167 MockRead("Content-Type: text/html\r\n"),
17168 MockRead("Content-Length: 7\r\n\r\n"),
17169 MockRead("another"),
17170 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117171 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1417172 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17173
zhongyi3d4a55e72016-04-22 20:36:4617174 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917175 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017176 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1417177 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117178 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217179 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117180 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717181 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1417182
17183 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17184 HttpRequestInfo request1;
17185 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2517186 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1417187 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017188 request1.traffic_annotation =
17189 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417190 TestCompletionCallback callback1;
17191
tfarina42834112016-09-22 13:38:2017192 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417193 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117194 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417195
17196 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217197 ASSERT_TRUE(response1);
17198 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1417199 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
17200
17201 std::string response_data1;
robpercival214763f2016-07-01 23:27:0117202 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1417203 EXPECT_EQ("foobar", response_data1);
17204
17205 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
17206 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0517207 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
17208 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1417209
zhongyi3d4a55e72016-04-22 20:36:4617210 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1417211 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4617212 // to server.
bnc40448a532015-05-11 19:13:1417213 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17214 HttpRequestInfo request2;
17215 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2517216 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1417217 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017218 request2.traffic_annotation =
17219 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417220 TestCompletionCallback callback2;
17221
tfarina42834112016-09-22 13:38:2017222 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417223 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117224 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417225
17226 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217227 ASSERT_TRUE(response2);
17228 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1417229 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
17230
17231 std::string response_data2;
robpercival214763f2016-07-01 23:27:0117232 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1417233 EXPECT_EQ("another", response_data2);
17234}
17235
bnc5452e2a2015-05-08 16:27:4217236// Alternative service requires HTTP/2 (or SPDY), but there is already a
17237// HTTP/1.1 socket open to the alternative server. That socket should not be
17238// used.
bncd16676a2016-07-20 16:23:0117239TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4617240 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4217241 HostPortPair alternative("alternative.example.org", 443);
17242 std::string origin_url = "https://origin.example.org:443";
17243 std::string alternative_url = "https://alternative.example.org:443";
17244
17245 // Negotiate HTTP/1.1 with alternative.example.org.
17246 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617247 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217248 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17249
17250 // HTTP/1.1 data for |request1| and |request2|.
17251 MockWrite http_writes[] = {
17252 MockWrite(
17253 "GET / HTTP/1.1\r\n"
17254 "Host: alternative.example.org\r\n"
17255 "Connection: keep-alive\r\n\r\n"),
17256 MockWrite(
17257 "GET / HTTP/1.1\r\n"
17258 "Host: alternative.example.org\r\n"
17259 "Connection: keep-alive\r\n\r\n"),
17260 };
17261
17262 MockRead http_reads[] = {
17263 MockRead(
17264 "HTTP/1.1 200 OK\r\n"
17265 "Content-Type: text/html; charset=iso-8859-1\r\n"
17266 "Content-Length: 40\r\n\r\n"
17267 "first HTTP/1.1 response from alternative"),
17268 MockRead(
17269 "HTTP/1.1 200 OK\r\n"
17270 "Content-Type: text/html; charset=iso-8859-1\r\n"
17271 "Content-Length: 41\r\n\r\n"
17272 "second HTTP/1.1 response from alternative"),
17273 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117274 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4217275 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17276
17277 // This test documents that an alternate Job should not pool to an already
17278 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4617279 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4217280 StaticSocketDataProvider data_refused;
17281 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17282 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17283
zhongyi3d4a55e72016-04-22 20:36:4617284 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917285 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017286 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217287 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117288 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217289 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117290 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717291 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217292
17293 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4217294 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4617295 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217296 request1.method = "GET";
17297 request1.url = GURL(alternative_url);
17298 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017299 request1.traffic_annotation =
17300 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217301 TestCompletionCallback callback1;
17302
tfarina42834112016-09-22 13:38:2017303 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117304 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617305 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217306 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5217307 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4217308 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217309 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217310 EXPECT_FALSE(response1->was_fetched_via_spdy);
17311 std::string response_data1;
bnc691fda62016-08-12 00:43:1617312 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4217313 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
17314
17315 // Request for origin.example.org, which has an alternative service. This
17316 // will start two Jobs: the alternative looks for connections to pool to,
17317 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4617318 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4217319 // this request fails.
bnc5452e2a2015-05-08 16:27:4217320 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4617321 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217322 request2.method = "GET";
17323 request2.url = GURL(origin_url);
17324 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017325 request2.traffic_annotation =
17326 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217327 TestCompletionCallback callback2;
17328
tfarina42834112016-09-22 13:38:2017329 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117330 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4217331
17332 // Another transaction to alternative. This is to test that the HTTP/1.1
17333 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4217334 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4617335 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217336 request3.method = "GET";
17337 request3.url = GURL(alternative_url);
17338 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017339 request3.traffic_annotation =
17340 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217341 TestCompletionCallback callback3;
17342
tfarina42834112016-09-22 13:38:2017343 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117344 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617345 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217346 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5217347 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4217348 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217349 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217350 EXPECT_FALSE(response3->was_fetched_via_spdy);
17351 std::string response_data3;
bnc691fda62016-08-12 00:43:1617352 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4217353 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
17354}
17355
bncd16676a2016-07-20 16:23:0117356TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2317357 const std::string https_url = "https://www.example.org:8080/";
17358 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417359
rdsmithebb50aa2015-11-12 03:44:3817360 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0117361 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3817362
[email protected]8450d722012-07-02 19:14:0417363 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2317364 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0417365 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
17366 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
17367 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1317368 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917369 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317370 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0217371 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3917372
17373 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1317374 spdy::SpdyHeaderBlock req2_block;
17375 req2_block[spdy::kHttp2MethodHeader] = "GET";
17376 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
17377 req2_block[spdy::kHttp2SchemeHeader] = "http";
17378 req2_block[spdy::kHttp2PathHeader] = "/";
17379 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1517380 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0417381
17382 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117383 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
17384 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0417385 };
17386
Ryan Hamilton0239aac2018-05-19 00:03:1317387 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1517388 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317389 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1517390 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317391 spdy::SpdySerializedFrame body1(
17392 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
17393 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3817394 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317395 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3817396 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3517397 spdy::SpdySerializedFrame resp2(
17398 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317399 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3317400 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117401 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3317402 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4117403 CreateMockRead(wrapped_resp1, 4),
17404 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3317405 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4117406 CreateMockRead(resp2, 8),
17407 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3317408 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
17409 };
[email protected]8450d722012-07-02 19:14:0417410
Ryan Sleevib8d7ea02018-05-07 20:01:0117411 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417412 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717413 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417414
Lily Houghton8c2f97d2018-01-22 05:06:5917415 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917416 ProxyResolutionService::CreateFixedFromPacResult(
17417 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5117418 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0717419 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0417420 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617421 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0417423 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617424 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317425 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17426 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0417427
danakj1fd259a02016-04-16 03:17:0917428 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0417429
17430 // Start the first transaction to set up the SpdySession
17431 HttpRequestInfo request1;
17432 request1.method = "GET";
17433 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417434 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017435 request1.traffic_annotation =
17436 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017437 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417438 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2017439 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417440
mmenke666a6fea2015-12-19 04:16:3317441 // This pause is a hack to avoid running into https://crbug.com/497228.
17442 data1.RunUntilPaused();
17443 base::RunLoop().RunUntilIdle();
17444 data1.Resume();
robpercival214763f2016-07-01 23:27:0117445 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0417446 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17447
[email protected]f6c63db52013-02-02 00:35:2217448 LoadTimingInfo load_timing_info1;
17449 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
17450 TestLoadTimingNotReusedWithPac(load_timing_info1,
17451 CONNECT_TIMING_HAS_SSL_TIMES);
17452
mmenke666a6fea2015-12-19 04:16:3317453 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0417454 HttpRequestInfo request2;
17455 request2.method = "GET";
17456 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417457 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017458 request2.traffic_annotation =
17459 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017460 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417461 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2017462 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417463
mmenke666a6fea2015-12-19 04:16:3317464 // This pause is a hack to avoid running into https://crbug.com/497228.
17465 data1.RunUntilPaused();
17466 base::RunLoop().RunUntilIdle();
17467 data1.Resume();
robpercival214763f2016-07-01 23:27:0117468 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3317469
[email protected]8450d722012-07-02 19:14:0417470 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2217471
17472 LoadTimingInfo load_timing_info2;
17473 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
17474 // The established SPDY sessions is considered reused by the HTTP request.
17475 TestLoadTimingReusedWithPac(load_timing_info2);
17476 // HTTP requests over a SPDY session should have a different connection
17477 // socket_log_id than requests over a tunnel.
17478 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0417479}
17480
[email protected]2d88e7d2012-07-19 17:55:1717481// Test that in the case where we have a SPDY session to a SPDY proxy
17482// that we do not pool other origins that resolve to the same IP when
17483// the certificate does not match the new origin.
17484// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0117485TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2317486 const std::string url1 = "http://www.example.org/";
17487 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1717488 const std::string ip_addr = "1.2.3.4";
17489
rdsmithebb50aa2015-11-12 03:44:3817490 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0117491 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3817492
[email protected]2d88e7d2012-07-19 17:55:1717493 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1317494 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2317495 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1317496 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1517497 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1717498
17499 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117500 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1717501 };
17502
Raul Tambre94493c652019-03-11 17:18:3517503 spdy::SpdySerializedFrame resp1(
17504 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317505 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1717506 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117507 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
17508 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1717509 };
17510
Ryan Sleevib8d7ea02018-05-07 20:01:0117511 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3217512 IPAddress ip;
martijn654c8c42016-02-10 22:10:5917513 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1717514 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17515 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3317516 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1717517
17518 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1317519 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917520 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1717521
17522 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117523 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1717524 };
17525
Ryan Hamilton0239aac2018-05-19 00:03:1317526 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3517527 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317528 spdy::SpdySerializedFrame body2(
17529 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117530 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3317531 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1717532
Ryan Sleevib8d7ea02018-05-07 20:01:0117533 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1717534 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3317535 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1717536
17537 // Set up a proxy config that sends HTTP requests to a proxy, and
17538 // all others direct.
17539 ProxyConfig proxy_config;
17540 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4917541 session_deps_.proxy_resolution_service =
17542 std::make_unique<ProxyResolutionService>(
17543 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
17544 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
17545 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1717546
bncce36dca22015-04-21 22:11:2317547 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617548 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1717549 // Load a valid cert. Note, that this does not need to
17550 // be valid for proxy because the MockSSLClientSocket does
17551 // not actually verify it. But SpdySession will use this
17552 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4917553 ssl1.ssl_info.cert =
17554 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
17555 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3317556 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17557 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1717558
17559 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617560 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317561 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17562 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1717563
Jeremy Roman0579ed62017-08-29 15:56:1917564 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2317565 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0717566 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1717567
danakj1fd259a02016-04-16 03:17:0917568 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1717569
17570 // Start the first transaction to set up the SpdySession
17571 HttpRequestInfo request1;
17572 request1.method = "GET";
17573 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1717574 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017575 request1.traffic_annotation =
17576 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017577 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717578 TestCompletionCallback callback1;
17579 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017580 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3317581 // This pause is a hack to avoid running into https://crbug.com/497228.
17582 data1.RunUntilPaused();
17583 base::RunLoop().RunUntilIdle();
17584 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1717585
robpercival214763f2016-07-01 23:27:0117586 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717587 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17588
17589 // Now, start the HTTP request
17590 HttpRequestInfo request2;
17591 request2.method = "GET";
17592 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1717593 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017594 request2.traffic_annotation =
17595 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017596 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1717597 TestCompletionCallback callback2;
17598 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017599 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517600 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1717601
17602 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0117603 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1717604 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17605}
17606
[email protected]85f97342013-04-17 06:12:2417607// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
17608// error) in SPDY session, removes the socket from pool and closes the SPDY
17609// session. Verify that new url's from the same HttpNetworkSession (and a new
17610// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0117611TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2317612 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2417613
17614 MockRead reads1[] = {
17615 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
17616 };
17617
Ryan Sleevib8d7ea02018-05-07 20:01:0117618 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2417619
Ryan Hamilton0239aac2018-05-19 00:03:1317620 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917621 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2417622 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117623 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2417624 };
17625
Raul Tambre94493c652019-03-11 17:18:3517626 spdy::SpdySerializedFrame resp2(
17627 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317628 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2417629 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4117630 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
17631 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2417632 };
17633
Ryan Sleevib8d7ea02018-05-07 20:01:0117634 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2417635
[email protected]85f97342013-04-17 06:12:2417636 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617637 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17639 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2417640
17641 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617642 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5017643 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17644 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2417645
danakj1fd259a02016-04-16 03:17:0917646 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5017647 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2417648
17649 // Start the first transaction to set up the SpdySession and verify that
17650 // connection was closed.
17651 HttpRequestInfo request1;
17652 request1.method = "GET";
17653 request1.url = GURL(https_url);
17654 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017655 request1.traffic_annotation =
17656 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017657 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417658 TestCompletionCallback callback1;
17659 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017660 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0117661 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2417662
17663 // Now, start the second request and make sure it succeeds.
17664 HttpRequestInfo request2;
17665 request2.method = "GET";
17666 request2.url = GURL(https_url);
17667 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017668 request2.traffic_annotation =
17669 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017670 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2417671 TestCompletionCallback callback2;
17672 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017673 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2417674
robpercival214763f2016-07-01 23:27:0117675 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2417676 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17677}
17678
bncd16676a2016-07-20 16:23:0117679TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0317680 ClientSocketPoolManager::set_max_sockets_per_group(
17681 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17682 ClientSocketPoolManager::set_max_sockets_per_pool(
17683 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17684
17685 // Use two different hosts with different IPs so they don't get pooled.
17686 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
17687 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0917688 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0317689
17690 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617691 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317692 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617693 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317694 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17695 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17696
Ryan Hamilton0239aac2018-05-19 00:03:1317697 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917698 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317699 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117700 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0317701 };
Ryan Hamilton0239aac2018-05-19 00:03:1317702 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517703 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317704 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117705 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317706 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117707 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917708 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317709 };
17710
rdsmithebb50aa2015-11-12 03:44:3817711 // Use a separate test instance for the separate SpdySession that will be
17712 // created.
bncd16676a2016-07-20 16:23:0117713 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0117714 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1217715 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0317716
Ryan Hamilton0239aac2018-05-19 00:03:1317717 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4917718 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317719 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117720 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0317721 };
Ryan Hamilton0239aac2018-05-19 00:03:1317722 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517723 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317724 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117725 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317726 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117727 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917728 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317729 };
17730
Ryan Sleevib8d7ea02018-05-07 20:01:0117731 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1217732 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0317733
17734 MockWrite http_write[] = {
17735 MockWrite("GET / HTTP/1.1\r\n"
17736 "Host: www.a.com\r\n"
17737 "Connection: keep-alive\r\n\r\n"),
17738 };
17739
17740 MockRead http_read[] = {
17741 MockRead("HTTP/1.1 200 OK\r\n"),
17742 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
17743 MockRead("Content-Length: 6\r\n\r\n"),
17744 MockRead("hello!"),
17745 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117746 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0317747 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17748
17749 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117750 SpdySessionKey spdy_session_key_a(
17751 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417752 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17753 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317754 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617755 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317756
17757 TestCompletionCallback callback;
17758 HttpRequestInfo request1;
17759 request1.method = "GET";
17760 request1.url = GURL("https://www.a.com/");
17761 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017762 request1.traffic_annotation =
17763 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817764 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917765 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317766
tfarina42834112016-09-22 13:38:2017767 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117768 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17769 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317770
17771 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217772 ASSERT_TRUE(response);
17773 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217774 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317775 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217776 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0317777
17778 std::string response_data;
robpercival214763f2016-07-01 23:27:0117779 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317780 EXPECT_EQ("hello!", response_data);
17781 trans.reset();
17782 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617783 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317784
17785 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117786 SpdySessionKey spdy_session_key_b(
17787 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417788 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17789 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317790 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617791 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317792 HttpRequestInfo request2;
17793 request2.method = "GET";
17794 request2.url = GURL("https://www.b.com/");
17795 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017796 request2.traffic_annotation =
17797 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817798 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917799 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317800
tfarina42834112016-09-22 13:38:2017801 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117802 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17803 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317804
17805 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217806 ASSERT_TRUE(response);
17807 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217808 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317809 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217810 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117811 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317812 EXPECT_EQ("hello!", response_data);
17813 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617814 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317815 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617816 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317817
17818 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1117819 SpdySessionKey spdy_session_key_a1(
17820 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417821 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17822 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317823 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617824 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0317825 HttpRequestInfo request3;
17826 request3.method = "GET";
17827 request3.url = GURL("http://www.a.com/");
17828 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017829 request3.traffic_annotation =
17830 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817831 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917832 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317833
tfarina42834112016-09-22 13:38:2017834 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117835 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17836 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317837
17838 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217839 ASSERT_TRUE(response);
17840 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0317841 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17842 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217843 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117844 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317845 EXPECT_EQ("hello!", response_data);
17846 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617847 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317848 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617849 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317850}
17851
bncd16676a2016-07-20 16:23:0117852TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417853 HttpRequestInfo request;
17854 request.method = "GET";
bncce36dca22015-04-21 22:11:2317855 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017856 request.traffic_annotation =
17857 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417858
danakj1fd259a02016-04-16 03:17:0917859 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617860 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417861
ttuttled9dbc652015-09-29 20:00:5917862 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417863 StaticSocketDataProvider data;
17864 data.set_connect_data(mock_connect);
17865 session_deps_.socket_factory->AddSocketDataProvider(&data);
17866
17867 TestCompletionCallback callback;
17868
tfarina42834112016-09-22 13:38:2017869 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117870 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417871
17872 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117873 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417874
ttuttle1f2d7e92015-04-28 16:17:4717875 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617876 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717877 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117878 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917879
17880 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617881 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917882 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417883}
17884
bncd16676a2016-07-20 16:23:0117885TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417886 HttpRequestInfo request;
17887 request.method = "GET";
bncce36dca22015-04-21 22:11:2317888 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017889 request.traffic_annotation =
17890 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417891
danakj1fd259a02016-04-16 03:17:0917892 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617893 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417894
ttuttled9dbc652015-09-29 20:00:5917895 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417896 StaticSocketDataProvider data;
17897 data.set_connect_data(mock_connect);
17898 session_deps_.socket_factory->AddSocketDataProvider(&data);
17899
17900 TestCompletionCallback callback;
17901
tfarina42834112016-09-22 13:38:2017902 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117903 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417904
17905 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117906 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417907
ttuttle1f2d7e92015-04-28 16:17:4717908 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617909 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717910 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117911 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917912
17913 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617914 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917915 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417916}
17917
bncd16676a2016-07-20 16:23:0117918TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417919 HttpRequestInfo request;
17920 request.method = "GET";
bncce36dca22015-04-21 22:11:2317921 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017922 request.traffic_annotation =
17923 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417924
danakj1fd259a02016-04-16 03:17:0917925 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617926 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417927
17928 MockWrite data_writes[] = {
17929 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17930 };
17931 MockRead data_reads[] = {
17932 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17933 };
17934
Ryan Sleevib8d7ea02018-05-07 20:01:0117935 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417936 session_deps_.socket_factory->AddSocketDataProvider(&data);
17937
17938 TestCompletionCallback callback;
17939
tfarina42834112016-09-22 13:38:2017940 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117941 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417942
17943 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117944 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417945}
17946
bncd16676a2016-07-20 16:23:0117947TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417948 HttpRequestInfo request;
17949 request.method = "GET";
bncce36dca22015-04-21 22:11:2317950 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017951 request.traffic_annotation =
17952 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417953
danakj1fd259a02016-04-16 03:17:0917954 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617955 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417956
17957 MockWrite data_writes[] = {
17958 MockWrite(ASYNC, ERR_CONNECTION_RESET),
17959 };
17960 MockRead data_reads[] = {
17961 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17962 };
17963
Ryan Sleevib8d7ea02018-05-07 20:01:0117964 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417965 session_deps_.socket_factory->AddSocketDataProvider(&data);
17966
17967 TestCompletionCallback callback;
17968
tfarina42834112016-09-22 13:38:2017969 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117970 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417971
17972 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117973 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417974}
17975
bncd16676a2016-07-20 16:23:0117976TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417977 HttpRequestInfo request;
17978 request.method = "GET";
bncce36dca22015-04-21 22:11:2317979 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017980 request.traffic_annotation =
17981 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417982
danakj1fd259a02016-04-16 03:17:0917983 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617984 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417985
17986 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317987 MockWrite(
17988 "GET / HTTP/1.1\r\n"
17989 "Host: www.example.org\r\n"
17990 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417991 };
17992 MockRead data_reads[] = {
17993 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
17994 };
17995
Ryan Sleevib8d7ea02018-05-07 20:01:0117996 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417997 session_deps_.socket_factory->AddSocketDataProvider(&data);
17998
17999 TestCompletionCallback callback;
18000
tfarina42834112016-09-22 13:38:2018001 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118002 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418003
18004 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118005 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418006}
18007
bncd16676a2016-07-20 16:23:0118008TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418009 HttpRequestInfo request;
18010 request.method = "GET";
bncce36dca22015-04-21 22:11:2318011 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018012 request.traffic_annotation =
18013 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418014
danakj1fd259a02016-04-16 03:17:0918015 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618016 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418017
18018 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318019 MockWrite(
18020 "GET / HTTP/1.1\r\n"
18021 "Host: www.example.org\r\n"
18022 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418023 };
18024 MockRead data_reads[] = {
18025 MockRead(ASYNC, ERR_CONNECTION_RESET),
18026 };
18027
Ryan Sleevib8d7ea02018-05-07 20:01:0118028 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418029 session_deps_.socket_factory->AddSocketDataProvider(&data);
18030
18031 TestCompletionCallback callback;
18032
tfarina42834112016-09-22 13:38:2018033 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118034 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418035
18036 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118037 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418038}
18039
[email protected]043b68c82013-08-22 23:41:5218040// Tests that when a used socket is returned to the SSL socket pool, it's closed
18041// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118042TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5218043 ClientSocketPoolManager::set_max_sockets_per_group(
18044 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18045 ClientSocketPoolManager::set_max_sockets_per_pool(
18046 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18047
18048 // Set up SSL request.
18049
18050 HttpRequestInfo ssl_request;
18051 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2318052 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018053 ssl_request.traffic_annotation =
18054 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218055
18056 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2318057 MockWrite(
18058 "GET / HTTP/1.1\r\n"
18059 "Host: www.example.org\r\n"
18060 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218061 };
18062 MockRead ssl_reads[] = {
18063 MockRead("HTTP/1.1 200 OK\r\n"),
18064 MockRead("Content-Length: 11\r\n\r\n"),
18065 MockRead("hello world"),
18066 MockRead(SYNCHRONOUS, OK),
18067 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118068 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5218069 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18070
18071 SSLSocketDataProvider ssl(ASYNC, OK);
18072 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18073
18074 // Set up HTTP request.
18075
18076 HttpRequestInfo http_request;
18077 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318078 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018079 http_request.traffic_annotation =
18080 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218081
18082 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318083 MockWrite(
18084 "GET / HTTP/1.1\r\n"
18085 "Host: www.example.org\r\n"
18086 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218087 };
18088 MockRead http_reads[] = {
18089 MockRead("HTTP/1.1 200 OK\r\n"),
18090 MockRead("Content-Length: 7\r\n\r\n"),
18091 MockRead("falafel"),
18092 MockRead(SYNCHRONOUS, OK),
18093 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118094 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218095 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18096
danakj1fd259a02016-04-16 03:17:0918097 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218098
18099 // Start the SSL request.
18100 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1618101 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018102 ASSERT_EQ(ERR_IO_PENDING,
18103 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
18104 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5218105
18106 // Start the HTTP request. Pool should stall.
18107 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618108 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018109 ASSERT_EQ(ERR_IO_PENDING,
18110 http_trans.Start(&http_request, http_callback.callback(),
18111 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118112 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218113
18114 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0118115 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218116 std::string response_data;
bnc691fda62016-08-12 00:43:1618117 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218118 EXPECT_EQ("hello world", response_data);
18119
18120 // The SSL socket should automatically be closed, so the HTTP request can
18121 // start.
Matt Menke9d5e2c92019-02-05 01:42:2318122 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4118123 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218124
18125 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0118126 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1618127 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218128 EXPECT_EQ("falafel", response_data);
18129
dcheng48459ac22014-08-26 00:46:4118130 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218131}
18132
18133// Tests that when a SSL connection is established but there's no corresponding
18134// request that needs it, the new socket is closed if the transport socket pool
18135// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118136TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5218137 ClientSocketPoolManager::set_max_sockets_per_group(
18138 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18139 ClientSocketPoolManager::set_max_sockets_per_pool(
18140 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18141
18142 // Set up an ssl request.
18143
18144 HttpRequestInfo ssl_request;
18145 ssl_request.method = "GET";
18146 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1018147 ssl_request.traffic_annotation =
18148 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218149
18150 // No data will be sent on the SSL socket.
18151 StaticSocketDataProvider ssl_data;
18152 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18153
18154 SSLSocketDataProvider ssl(ASYNC, OK);
18155 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18156
18157 // Set up HTTP request.
18158
18159 HttpRequestInfo http_request;
18160 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318161 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018162 http_request.traffic_annotation =
18163 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218164
18165 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318166 MockWrite(
18167 "GET / HTTP/1.1\r\n"
18168 "Host: www.example.org\r\n"
18169 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218170 };
18171 MockRead http_reads[] = {
18172 MockRead("HTTP/1.1 200 OK\r\n"),
18173 MockRead("Content-Length: 7\r\n\r\n"),
18174 MockRead("falafel"),
18175 MockRead(SYNCHRONOUS, OK),
18176 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118177 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218178 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18179
danakj1fd259a02016-04-16 03:17:0918180 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218181
18182 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
18183 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2918184 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5918185 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2318186 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218187
18188 // Start the HTTP request. Pool should stall.
18189 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618190 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018191 ASSERT_EQ(ERR_IO_PENDING,
18192 http_trans.Start(&http_request, http_callback.callback(),
18193 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118194 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218195
18196 // The SSL connection will automatically be closed once the connection is
18197 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0118198 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218199 std::string response_data;
bnc691fda62016-08-12 00:43:1618200 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218201 EXPECT_EQ("falafel", response_data);
18202
dcheng48459ac22014-08-26 00:46:4118203 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218204}
18205
bncd16676a2016-07-20 16:23:0118206TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918207 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218208 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918209 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218210 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418211
18212 HttpRequestInfo request;
18213 request.method = "POST";
18214 request.url = GURL("http://www.foo.com/");
18215 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018216 request.traffic_annotation =
18217 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418218
danakj1fd259a02016-04-16 03:17:0918219 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618220 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418221 // Send headers successfully, but get an error while sending the body.
18222 MockWrite data_writes[] = {
18223 MockWrite("POST / HTTP/1.1\r\n"
18224 "Host: www.foo.com\r\n"
18225 "Connection: keep-alive\r\n"
18226 "Content-Length: 3\r\n\r\n"),
18227 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18228 };
18229
18230 MockRead data_reads[] = {
18231 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18232 MockRead("hello world"),
18233 MockRead(SYNCHRONOUS, OK),
18234 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118235 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418236 session_deps_.socket_factory->AddSocketDataProvider(&data);
18237
18238 TestCompletionCallback callback;
18239
tfarina42834112016-09-22 13:38:2018240 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118241 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418242
18243 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118244 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418245
bnc691fda62016-08-12 00:43:1618246 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218247 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418248
wezca1070932016-05-26 20:30:5218249 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418250 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18251
18252 std::string response_data;
bnc691fda62016-08-12 00:43:1618253 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118254 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418255 EXPECT_EQ("hello world", response_data);
18256}
18257
18258// This test makes sure the retry logic doesn't trigger when reading an error
18259// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0118260TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418261 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0918262 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5418263 MockWrite data_writes[] = {
18264 MockWrite("GET / HTTP/1.1\r\n"
18265 "Host: www.foo.com\r\n"
18266 "Connection: keep-alive\r\n\r\n"),
18267 MockWrite("POST / HTTP/1.1\r\n"
18268 "Host: www.foo.com\r\n"
18269 "Connection: keep-alive\r\n"
18270 "Content-Length: 3\r\n\r\n"),
18271 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18272 };
18273
18274 MockRead data_reads[] = {
18275 MockRead("HTTP/1.1 200 Peachy\r\n"
18276 "Content-Length: 14\r\n\r\n"),
18277 MockRead("first response"),
18278 MockRead("HTTP/1.1 400 Not OK\r\n"
18279 "Content-Length: 15\r\n\r\n"),
18280 MockRead("second response"),
18281 MockRead(SYNCHRONOUS, OK),
18282 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118283 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418284 session_deps_.socket_factory->AddSocketDataProvider(&data);
18285
18286 TestCompletionCallback callback;
18287 HttpRequestInfo request1;
18288 request1.method = "GET";
18289 request1.url = GURL("http://www.foo.com/");
18290 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018291 request1.traffic_annotation =
18292 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418293
bnc87dcefc2017-05-25 12:47:5818294 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1918295 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018296 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118297 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418298
18299 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118300 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418301
18302 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5218303 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5418304
wezca1070932016-05-26 20:30:5218305 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5418306 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
18307
18308 std::string response_data1;
18309 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0118310 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418311 EXPECT_EQ("first response", response_data1);
18312 // Delete the transaction to release the socket back into the socket pool.
18313 trans1.reset();
18314
danakj1fd259a02016-04-16 03:17:0918315 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218316 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918317 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218318 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418319
18320 HttpRequestInfo request2;
18321 request2.method = "POST";
18322 request2.url = GURL("http://www.foo.com/");
18323 request2.upload_data_stream = &upload_data_stream;
18324 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018325 request2.traffic_annotation =
18326 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418327
bnc691fda62016-08-12 00:43:1618328 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018329 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418331
18332 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118333 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418334
bnc691fda62016-08-12 00:43:1618335 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5218336 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5418337
wezca1070932016-05-26 20:30:5218338 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5418339 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
18340
18341 std::string response_data2;
bnc691fda62016-08-12 00:43:1618342 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0118343 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418344 EXPECT_EQ("second response", response_data2);
18345}
18346
bncd16676a2016-07-20 16:23:0118347TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418348 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0918349 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218350 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918351 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218352 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418353
18354 HttpRequestInfo request;
18355 request.method = "POST";
18356 request.url = GURL("http://www.foo.com/");
18357 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018358 request.traffic_annotation =
18359 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418360
danakj1fd259a02016-04-16 03:17:0918361 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618362 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418363 // Send headers successfully, but get an error while sending the body.
18364 MockWrite data_writes[] = {
18365 MockWrite("POST / HTTP/1.1\r\n"
18366 "Host: www.foo.com\r\n"
18367 "Connection: keep-alive\r\n"
18368 "Content-Length: 3\r\n\r\n"
18369 "fo"),
18370 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18371 };
18372
18373 MockRead data_reads[] = {
18374 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18375 MockRead("hello world"),
18376 MockRead(SYNCHRONOUS, OK),
18377 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118378 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418379 session_deps_.socket_factory->AddSocketDataProvider(&data);
18380
18381 TestCompletionCallback callback;
18382
tfarina42834112016-09-22 13:38:2018383 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118384 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418385
18386 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118387 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418388
bnc691fda62016-08-12 00:43:1618389 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218390 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418391
wezca1070932016-05-26 20:30:5218392 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418393 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18394
18395 std::string response_data;
bnc691fda62016-08-12 00:43:1618396 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118397 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418398 EXPECT_EQ("hello world", response_data);
18399}
18400
18401// This tests the more common case than the previous test, where headers and
18402// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0118403TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0718404 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5418405
18406 HttpRequestInfo request;
18407 request.method = "POST";
18408 request.url = GURL("http://www.foo.com/");
18409 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018410 request.traffic_annotation =
18411 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418412
danakj1fd259a02016-04-16 03:17:0918413 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618414 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418415 // Send headers successfully, but get an error while sending the body.
18416 MockWrite data_writes[] = {
18417 MockWrite("POST / HTTP/1.1\r\n"
18418 "Host: www.foo.com\r\n"
18419 "Connection: keep-alive\r\n"
18420 "Transfer-Encoding: chunked\r\n\r\n"),
18421 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18422 };
18423
18424 MockRead data_reads[] = {
18425 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18426 MockRead("hello world"),
18427 MockRead(SYNCHRONOUS, OK),
18428 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118429 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418430 session_deps_.socket_factory->AddSocketDataProvider(&data);
18431
18432 TestCompletionCallback callback;
18433
tfarina42834112016-09-22 13:38:2018434 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118435 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418436 // Make sure the headers are sent before adding a chunk. This ensures that
18437 // they can't be merged with the body in a single send. Not currently
18438 // necessary since a chunked body is never merged with headers, but this makes
18439 // the test more future proof.
18440 base::RunLoop().RunUntilIdle();
18441
mmenkecbc2b712014-10-09 20:29:0718442 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5418443
18444 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118445 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418446
bnc691fda62016-08-12 00:43:1618447 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218448 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418449
wezca1070932016-05-26 20:30:5218450 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418451 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18452
18453 std::string response_data;
bnc691fda62016-08-12 00:43:1618454 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118455 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418456 EXPECT_EQ("hello world", response_data);
18457}
18458
bncd16676a2016-07-20 16:23:0118459TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918460 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218461 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918462 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218463 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418464
18465 HttpRequestInfo request;
18466 request.method = "POST";
18467 request.url = GURL("http://www.foo.com/");
18468 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018469 request.traffic_annotation =
18470 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418471
danakj1fd259a02016-04-16 03:17:0918472 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618473 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418474
18475 MockWrite data_writes[] = {
18476 MockWrite("POST / HTTP/1.1\r\n"
18477 "Host: www.foo.com\r\n"
18478 "Connection: keep-alive\r\n"
18479 "Content-Length: 3\r\n\r\n"),
18480 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18481 };
18482
18483 MockRead data_reads[] = {
18484 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18485 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18486 MockRead("hello world"),
18487 MockRead(SYNCHRONOUS, OK),
18488 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118489 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418490 session_deps_.socket_factory->AddSocketDataProvider(&data);
18491
18492 TestCompletionCallback callback;
18493
tfarina42834112016-09-22 13:38:2018494 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118495 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418496
18497 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118498 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418499
bnc691fda62016-08-12 00:43:1618500 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218501 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418502
wezca1070932016-05-26 20:30:5218503 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418504 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18505
18506 std::string response_data;
bnc691fda62016-08-12 00:43:1618507 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118508 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418509 EXPECT_EQ("hello world", response_data);
18510}
18511
bncd16676a2016-07-20 16:23:0118512TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918513 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218514 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918515 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218516 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418517
18518 HttpRequestInfo request;
18519 request.method = "POST";
18520 request.url = GURL("http://www.foo.com/");
18521 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018522 request.traffic_annotation =
18523 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418524
danakj1fd259a02016-04-16 03:17:0918525 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618526 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418527 // Send headers successfully, but get an error while sending the body.
18528 MockWrite data_writes[] = {
18529 MockWrite("POST / HTTP/1.1\r\n"
18530 "Host: www.foo.com\r\n"
18531 "Connection: keep-alive\r\n"
18532 "Content-Length: 3\r\n\r\n"),
18533 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18534 };
18535
18536 MockRead data_reads[] = {
18537 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
18538 MockRead("hello world"),
18539 MockRead(SYNCHRONOUS, OK),
18540 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118541 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418542 session_deps_.socket_factory->AddSocketDataProvider(&data);
18543
18544 TestCompletionCallback callback;
18545
tfarina42834112016-09-22 13:38:2018546 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118547 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418548
18549 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118550 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418551}
18552
bncd16676a2016-07-20 16:23:0118553TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418554 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918555 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218556 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918557 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218558 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418559
18560 HttpRequestInfo request;
18561 request.method = "POST";
18562 request.url = GURL("http://www.foo.com/");
18563 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018564 request.traffic_annotation =
18565 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418566
danakj1fd259a02016-04-16 03:17:0918567 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618568 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418569 // Send headers successfully, but get an error while sending the body.
18570 MockWrite data_writes[] = {
18571 MockWrite("POST / HTTP/1.1\r\n"
18572 "Host: www.foo.com\r\n"
18573 "Connection: keep-alive\r\n"
18574 "Content-Length: 3\r\n\r\n"),
18575 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18576 };
18577
18578 MockRead data_reads[] = {
18579 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18580 MockRead("HTTP/1.0 302 Redirect\r\n"),
18581 MockRead("Location: http://somewhere-else.com/\r\n"),
18582 MockRead("Content-Length: 0\r\n\r\n"),
18583 MockRead(SYNCHRONOUS, OK),
18584 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118585 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418586 session_deps_.socket_factory->AddSocketDataProvider(&data);
18587
18588 TestCompletionCallback callback;
18589
tfarina42834112016-09-22 13:38:2018590 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118591 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418592
18593 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118594 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418595}
18596
bncd16676a2016-07-20 16:23:0118597TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918598 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218599 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918600 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218601 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418602
18603 HttpRequestInfo request;
18604 request.method = "POST";
18605 request.url = GURL("http://www.foo.com/");
18606 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018607 request.traffic_annotation =
18608 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418609
danakj1fd259a02016-04-16 03:17:0918610 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618611 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418612 // Send headers successfully, but get an error while sending the body.
18613 MockWrite data_writes[] = {
18614 MockWrite("POST / HTTP/1.1\r\n"
18615 "Host: www.foo.com\r\n"
18616 "Connection: keep-alive\r\n"
18617 "Content-Length: 3\r\n\r\n"),
18618 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18619 };
18620
18621 MockRead data_reads[] = {
18622 MockRead("HTTP 0.9 rocks!"),
18623 MockRead(SYNCHRONOUS, OK),
18624 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118625 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418626 session_deps_.socket_factory->AddSocketDataProvider(&data);
18627
18628 TestCompletionCallback callback;
18629
tfarina42834112016-09-22 13:38:2018630 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118631 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418632
18633 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118634 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418635}
18636
bncd16676a2016-07-20 16:23:0118637TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0918638 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218639 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918640 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218641 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418642
18643 HttpRequestInfo request;
18644 request.method = "POST";
18645 request.url = GURL("http://www.foo.com/");
18646 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018647 request.traffic_annotation =
18648 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418649
danakj1fd259a02016-04-16 03:17:0918650 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618651 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418652 // Send headers successfully, but get an error while sending the body.
18653 MockWrite data_writes[] = {
18654 MockWrite("POST / HTTP/1.1\r\n"
18655 "Host: www.foo.com\r\n"
18656 "Connection: keep-alive\r\n"
18657 "Content-Length: 3\r\n\r\n"),
18658 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18659 };
18660
18661 MockRead data_reads[] = {
18662 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
18663 MockRead(SYNCHRONOUS, OK),
18664 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118665 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418666 session_deps_.socket_factory->AddSocketDataProvider(&data);
18667
18668 TestCompletionCallback callback;
18669
tfarina42834112016-09-22 13:38:2018670 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118671 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418672
18673 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118674 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418675}
18676
Bence Békydca6bd92018-01-30 13:43:0618677#if BUILDFLAG(ENABLE_WEBSOCKETS)
18678
18679namespace {
18680
18681void AddWebSocketHeaders(HttpRequestHeaders* headers) {
18682 headers->SetHeader("Connection", "Upgrade");
18683 headers->SetHeader("Upgrade", "websocket");
18684 headers->SetHeader("Origin", "http://www.example.org");
18685 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0618686}
18687
18688} // namespace
18689
18690TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0118691 for (bool secure : {true, false}) {
18692 MockWrite data_writes[] = {
18693 MockWrite("GET / HTTP/1.1\r\n"
18694 "Host: www.example.org\r\n"
18695 "Connection: Upgrade\r\n"
18696 "Upgrade: websocket\r\n"
18697 "Origin: http://www.example.org\r\n"
18698 "Sec-WebSocket-Version: 13\r\n"
18699 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18700 "Sec-WebSocket-Extensions: permessage-deflate; "
18701 "client_max_window_bits\r\n\r\n")};
18702
18703 MockRead data_reads[] = {
18704 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18705 "Upgrade: websocket\r\n"
18706 "Connection: Upgrade\r\n"
18707 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
18708
Ryan Sleevib8d7ea02018-05-07 20:01:0118709 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0118710 session_deps_.socket_factory->AddSocketDataProvider(&data);
18711 SSLSocketDataProvider ssl(ASYNC, OK);
18712 if (secure)
18713 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0618714
18715 HttpRequestInfo request;
18716 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0118717 request.url =
18718 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18719 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e62018-02-07 07:41:1018720 request.traffic_annotation =
18721 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0618722
Bence Béky2fcf4fa2018-04-06 20:06:0118723 TestWebSocketHandshakeStreamCreateHelper
18724 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1518725
Bence Béky2fcf4fa2018-04-06 20:06:0118726 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0618727 HttpNetworkTransaction trans(LOW, session.get());
18728 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0118729 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0618730
18731 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0118732 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18733 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0618734
Bence Béky2fcf4fa2018-04-06 20:06:0118735 const HttpStreamRequest* stream_request = trans.stream_request_.get();
18736 ASSERT_TRUE(stream_request);
18737 EXPECT_EQ(&websocket_handshake_stream_create_helper,
18738 stream_request->websocket_handshake_stream_create_helper());
18739
18740 rv = callback.WaitForResult();
18741 EXPECT_THAT(rv, IsOk());
18742
18743 EXPECT_TRUE(data.AllReadDataConsumed());
18744 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0618745 }
18746}
18747
Adam Rice425cf122015-01-19 06:18:2418748// Verify that proxy headers are not sent to the destination server when
18749// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0118750TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2418751 HttpRequestInfo request;
18752 request.method = "GET";
bncce36dca22015-04-21 22:11:2318753 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018754 request.traffic_annotation =
18755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418756 AddWebSocketHeaders(&request.extra_headers);
18757
18758 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918759 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918760 ProxyResolutionService::CreateFixedFromPacResult(
18761 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418762
danakj1fd259a02016-04-16 03:17:0918763 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418764
18765 // Since a proxy is configured, try to establish a tunnel.
18766 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1718767 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18768 "Host: www.example.org:443\r\n"
18769 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418770
18771 // After calling trans->RestartWithAuth(), this is the request we should
18772 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1718773 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18774 "Host: www.example.org:443\r\n"
18775 "Proxy-Connection: keep-alive\r\n"
18776 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418777
rsleevidb16bb02015-11-12 23:47:1718778 MockWrite("GET / HTTP/1.1\r\n"
18779 "Host: www.example.org\r\n"
18780 "Connection: Upgrade\r\n"
18781 "Upgrade: websocket\r\n"
18782 "Origin: http://www.example.org\r\n"
18783 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1518784 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18785 "Sec-WebSocket-Extensions: permessage-deflate; "
18786 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418787
18788 // The proxy responds to the connect with a 407, using a persistent
18789 // connection.
18790 MockRead data_reads[] = {
18791 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1518792 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
18793 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
18794 "Content-Length: 0\r\n"
18795 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418796
18797 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18798
Bence Béky8d1c6052018-02-07 12:48:1518799 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18800 "Upgrade: websocket\r\n"
18801 "Connection: Upgrade\r\n"
18802 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418803
Ryan Sleevib8d7ea02018-05-07 20:01:0118804 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418805 session_deps_.socket_factory->AddSocketDataProvider(&data);
18806 SSLSocketDataProvider ssl(ASYNC, OK);
18807 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18808
Bence Béky8d1c6052018-02-07 12:48:1518809 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18810
bnc87dcefc2017-05-25 12:47:5818811 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918812 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418813 trans->SetWebSocketHandshakeStreamCreateHelper(
18814 &websocket_stream_create_helper);
18815
18816 {
18817 TestCompletionCallback callback;
18818
tfarina42834112016-09-22 13:38:2018819 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118820 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418821
18822 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118823 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418824 }
18825
18826 const HttpResponseInfo* response = trans->GetResponseInfo();
18827 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218828 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418829 EXPECT_EQ(407, response->headers->response_code());
18830
18831 {
18832 TestCompletionCallback callback;
18833
18834 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
18835 callback.callback());
robpercival214763f2016-07-01 23:27:0118836 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418837
18838 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118839 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418840 }
18841
18842 response = trans->GetResponseInfo();
18843 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218844 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418845
18846 EXPECT_EQ(101, response->headers->response_code());
18847
18848 trans.reset();
18849 session->CloseAllConnections();
18850}
18851
18852// Verify that proxy headers are not sent to the destination server when
18853// establishing a tunnel for an insecure WebSocket connection.
18854// This requires the authentication info to be injected into the auth cache
18855// due to crbug.com/395064
18856// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0118857TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2418858 HttpRequestInfo request;
18859 request.method = "GET";
bncce36dca22015-04-21 22:11:2318860 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018861 request.traffic_annotation =
18862 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418863 AddWebSocketHeaders(&request.extra_headers);
18864
18865 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918866 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918867 ProxyResolutionService::CreateFixedFromPacResult(
18868 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418869
danakj1fd259a02016-04-16 03:17:0918870 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418871
18872 MockWrite data_writes[] = {
18873 // Try to establish a tunnel for the WebSocket connection, with
18874 // credentials. Because WebSockets have a separate set of socket pools,
18875 // they cannot and will not use the same TCP/IP connection as the
18876 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1518877 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
18878 "Host: www.example.org:80\r\n"
18879 "Proxy-Connection: keep-alive\r\n"
18880 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418881
Bence Béky8d1c6052018-02-07 12:48:1518882 MockWrite("GET / HTTP/1.1\r\n"
18883 "Host: www.example.org\r\n"
18884 "Connection: Upgrade\r\n"
18885 "Upgrade: websocket\r\n"
18886 "Origin: http://www.example.org\r\n"
18887 "Sec-WebSocket-Version: 13\r\n"
18888 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18889 "Sec-WebSocket-Extensions: permessage-deflate; "
18890 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418891
18892 MockRead data_reads[] = {
18893 // HTTP CONNECT with credentials.
18894 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18895
18896 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1518897 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18898 "Upgrade: websocket\r\n"
18899 "Connection: Upgrade\r\n"
18900 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418901
Ryan Sleevib8d7ea02018-05-07 20:01:0118902 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418903 session_deps_.socket_factory->AddSocketDataProvider(&data);
18904
18905 session->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:3318906 GURL("http://myproxy:70/"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:2618907 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
18908 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Adam Rice425cf122015-01-19 06:18:2418909
Bence Béky8d1c6052018-02-07 12:48:1518910 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18911
bnc87dcefc2017-05-25 12:47:5818912 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918913 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418914 trans->SetWebSocketHandshakeStreamCreateHelper(
18915 &websocket_stream_create_helper);
18916
18917 TestCompletionCallback callback;
18918
tfarina42834112016-09-22 13:38:2018919 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118920 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418921
18922 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118923 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418924
18925 const HttpResponseInfo* response = trans->GetResponseInfo();
18926 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218927 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418928
18929 EXPECT_EQ(101, response->headers->response_code());
18930
18931 trans.reset();
18932 session->CloseAllConnections();
18933}
18934
Matt Menke1d6093e32019-03-22 17:33:4318935// WebSockets over QUIC is not supported, including over QUIC proxies.
18936TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
18937 for (bool secure : {true, false}) {
18938 SCOPED_TRACE(secure);
18939 session_deps_.proxy_resolution_service =
18940 ProxyResolutionService::CreateFixedFromPacResult(
18941 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
18942 session_deps_.enable_quic = true;
18943
18944 HttpRequestInfo request;
18945 request.url =
18946 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18947 AddWebSocketHeaders(&request.extra_headers);
18948 request.traffic_annotation =
18949 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18950
18951 TestWebSocketHandshakeStreamCreateHelper
18952 websocket_handshake_stream_create_helper;
18953
18954 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18955 HttpNetworkTransaction trans(LOW, session.get());
18956 trans.SetWebSocketHandshakeStreamCreateHelper(
18957 &websocket_handshake_stream_create_helper);
18958
18959 TestCompletionCallback callback;
18960 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18961 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18962
18963 rv = callback.WaitForResult();
18964 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
18965 }
18966}
18967
Bence Békydca6bd92018-01-30 13:43:0618968#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
18969
bncd16676a2016-07-20 16:23:0118970TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0918971 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218972 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918973 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218974 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218975
18976 HttpRequestInfo request;
18977 request.method = "POST";
18978 request.url = GURL("http://www.foo.com/");
18979 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018980 request.traffic_annotation =
18981 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218982
danakj1fd259a02016-04-16 03:17:0918983 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618984 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218985 MockWrite data_writes[] = {
18986 MockWrite("POST / HTTP/1.1\r\n"
18987 "Host: www.foo.com\r\n"
18988 "Connection: keep-alive\r\n"
18989 "Content-Length: 3\r\n\r\n"),
18990 MockWrite("foo"),
18991 };
18992
18993 MockRead data_reads[] = {
18994 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18995 MockRead(SYNCHRONOUS, OK),
18996 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118997 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218998 session_deps_.socket_factory->AddSocketDataProvider(&data);
18999
19000 TestCompletionCallback callback;
19001
19002 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019003 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119004 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219005
19006 std::string response_data;
bnc691fda62016-08-12 00:43:1619007 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219008
Ryan Sleevib8d7ea02018-05-07 20:01:0119009 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19010 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219011}
19012
bncd16676a2016-07-20 16:23:0119013TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0919014 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219015 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919016 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219017 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219018
19019 HttpRequestInfo request;
19020 request.method = "POST";
19021 request.url = GURL("http://www.foo.com/");
19022 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019023 request.traffic_annotation =
19024 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219025
danakj1fd259a02016-04-16 03:17:0919026 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619027 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219028 MockWrite data_writes[] = {
19029 MockWrite("POST / HTTP/1.1\r\n"
19030 "Host: www.foo.com\r\n"
19031 "Connection: keep-alive\r\n"
19032 "Content-Length: 3\r\n\r\n"),
19033 MockWrite("foo"),
19034 };
19035
19036 MockRead data_reads[] = {
19037 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
19038 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19039 MockRead(SYNCHRONOUS, OK),
19040 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119041 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219042 session_deps_.socket_factory->AddSocketDataProvider(&data);
19043
19044 TestCompletionCallback callback;
19045
19046 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019047 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119048 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219049
19050 std::string response_data;
bnc691fda62016-08-12 00:43:1619051 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219052
Ryan Sleevib8d7ea02018-05-07 20:01:0119053 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19054 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219055}
19056
bncd16676a2016-07-20 16:23:0119057TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2219058 ChunkedUploadDataStream upload_data_stream(0);
19059
19060 HttpRequestInfo request;
19061 request.method = "POST";
19062 request.url = GURL("http://www.foo.com/");
19063 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019064 request.traffic_annotation =
19065 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219066
danakj1fd259a02016-04-16 03:17:0919067 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619068 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219069 // Send headers successfully, but get an error while sending the body.
19070 MockWrite data_writes[] = {
19071 MockWrite("POST / HTTP/1.1\r\n"
19072 "Host: www.foo.com\r\n"
19073 "Connection: keep-alive\r\n"
19074 "Transfer-Encoding: chunked\r\n\r\n"),
19075 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
19076 };
19077
19078 MockRead data_reads[] = {
19079 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19080 MockRead(SYNCHRONOUS, OK),
19081 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119082 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219083 session_deps_.socket_factory->AddSocketDataProvider(&data);
19084
19085 TestCompletionCallback callback;
19086
19087 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019088 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2219089
19090 base::RunLoop().RunUntilIdle();
19091 upload_data_stream.AppendData("f", 1, false);
19092
19093 base::RunLoop().RunUntilIdle();
19094 upload_data_stream.AppendData("oo", 2, true);
19095
robpercival214763f2016-07-01 23:27:0119096 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219097
19098 std::string response_data;
bnc691fda62016-08-12 00:43:1619099 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219100
Ryan Sleevib8d7ea02018-05-07 20:01:0119101 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19102 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219103}
19104
eustasc7d27da2017-04-06 10:33:2019105void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
19106 const std::string& accept_encoding,
19107 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0319108 const std::string& location,
eustasc7d27da2017-04-06 10:33:2019109 bool should_match) {
19110 HttpRequestInfo request;
19111 request.method = "GET";
19112 request.url = GURL("http://www.foo.com/");
19113 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
19114 accept_encoding);
Ramin Halavatib5e433e62018-02-07 07:41:1019115 request.traffic_annotation =
19116 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2019117
19118 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
19119 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19120 // Send headers successfully, but get an error while sending the body.
19121 MockWrite data_writes[] = {
19122 MockWrite("GET / HTTP/1.1\r\n"
19123 "Host: www.foo.com\r\n"
19124 "Connection: keep-alive\r\n"
19125 "Accept-Encoding: "),
19126 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
19127 };
19128
sky50576f32017-05-01 19:28:0319129 std::string response_code = "200 OK";
19130 std::string extra;
19131 if (!location.empty()) {
19132 response_code = "301 Redirect\r\nLocation: ";
19133 response_code.append(location);
19134 }
19135
eustasc7d27da2017-04-06 10:33:2019136 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0319137 MockRead("HTTP/1.0 "),
19138 MockRead(response_code.data()),
19139 MockRead("\r\nContent-Encoding: "),
19140 MockRead(content_encoding.data()),
19141 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2019142 MockRead(SYNCHRONOUS, OK),
19143 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119144 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2019145 session_deps->socket_factory->AddSocketDataProvider(&data);
19146
19147 TestCompletionCallback callback;
19148
19149 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19150 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19151
19152 rv = callback.WaitForResult();
19153 if (should_match) {
19154 EXPECT_THAT(rv, IsOk());
19155 } else {
19156 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
19157 }
19158}
19159
19160TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0319161 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2019162}
19163
19164TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0319165 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
19166 true);
eustasc7d27da2017-04-06 10:33:2019167}
19168
19169TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
19170 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0319171 "", false);
19172}
19173
19174TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
19175 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
19176 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2019177}
19178
xunjieli96f2a402017-06-05 17:24:2719179TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
19180 ProxyConfig proxy_config;
19181 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19182 proxy_config.set_pac_mandatory(true);
19183 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5919184 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4919185 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19186 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0419187 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2719188
19189 HttpRequestInfo request;
19190 request.method = "GET";
19191 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019192 request.traffic_annotation =
19193 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719194
19195 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19196 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19197
19198 TestCompletionCallback callback;
19199
19200 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19201 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19202 EXPECT_THAT(callback.WaitForResult(),
19203 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19204}
19205
19206TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
19207 ProxyConfig proxy_config;
19208 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19209 proxy_config.set_pac_mandatory(true);
19210 MockAsyncProxyResolverFactory* proxy_resolver_factory =
19211 new MockAsyncProxyResolverFactory(false);
19212 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5919213 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4919214 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19215 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5919216 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2719217 HttpRequestInfo request;
19218 request.method = "GET";
19219 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019220 request.traffic_annotation =
19221 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719222
19223 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19224 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19225
19226 TestCompletionCallback callback;
19227 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19228 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19229
19230 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
19231 ERR_FAILED, &resolver);
19232 EXPECT_THAT(callback.WaitForResult(),
19233 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19234}
19235
19236TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5919237 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4919238 ProxyResolutionService::CreateFixedFromPacResult(
19239 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719240 session_deps_.enable_quic = false;
19241 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19242
19243 HttpRequestInfo request;
19244 request.method = "GET";
19245 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019246 request.traffic_annotation =
19247 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719248
19249 TestCompletionCallback callback;
19250 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19251 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19252 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19253
19254 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
19255}
19256
Douglas Creager3cb042052018-11-06 23:08:5219257//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1419258// Reporting tests
19259
19260#if BUILDFLAG(ENABLE_REPORTING)
19261class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
19262 protected:
19263 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619264 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1419265 auto test_reporting_context = std::make_unique<TestReportingContext>(
19266 &clock_, &tick_clock_, ReportingPolicy());
19267 test_reporting_context_ = test_reporting_context.get();
19268 session_deps_.reporting_service =
19269 ReportingService::CreateForTesting(std::move(test_reporting_context));
19270 }
19271
19272 TestReportingContext* reporting_context() const {
19273 return test_reporting_context_;
19274 }
19275
19276 void clear_reporting_service() {
19277 session_deps_.reporting_service.reset();
19278 test_reporting_context_ = nullptr;
19279 }
19280
19281 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4219282 void RequestPolicy(CertStatus cert_status = 0) {
19283 HttpRequestInfo request;
19284 request.method = "GET";
19285 request.url = GURL(url_);
19286 request.traffic_annotation =
19287 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19288
Lily Chend3930e72019-03-01 19:31:1119289 MockWrite data_writes[] = {
19290 MockWrite("GET / HTTP/1.1\r\n"
19291 "Host: www.example.org\r\n"
19292 "Connection: keep-alive\r\n\r\n"),
19293 };
Douglas Creager134b52e2018-11-09 18:00:1419294 MockRead data_reads[] = {
19295 MockRead("HTTP/1.0 200 OK\r\n"),
19296 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
19297 "\"endpoints\": [{\"url\": "
19298 "\"https://www.example.org/upload/\"}]}\r\n"),
19299 MockRead("\r\n"),
19300 MockRead("hello world"),
19301 MockRead(SYNCHRONOUS, OK),
19302 };
Douglas Creager134b52e2018-11-09 18:00:1419303
Lily Chenfec60d92019-01-24 01:16:4219304 StaticSocketDataProvider reads(data_reads, data_writes);
19305 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1419306
19307 SSLSocketDataProvider ssl(ASYNC, OK);
19308 if (request.url.SchemeIsCryptographic()) {
19309 ssl.ssl_info.cert =
19310 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19311 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219312 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1419313 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19314 }
19315
Douglas Creager134b52e2018-11-09 18:00:1419316 TestCompletionCallback callback;
19317 auto session = CreateSession(&session_deps_);
19318 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19319 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4219320 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1419321 }
19322
19323 protected:
19324 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1419325
19326 private:
19327 TestReportingContext* test_reporting_context_;
19328};
19329
19330TEST_F(HttpNetworkTransactionReportingTest,
19331 DontProcessReportToHeaderNoService) {
19332 base::HistogramTester histograms;
19333 clear_reporting_service();
19334 RequestPolicy();
19335 histograms.ExpectBucketCount(
19336 ReportingHeaderParser::kHeaderOutcomeHistogram,
19337 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
19338}
19339
19340TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
19341 base::HistogramTester histograms;
19342 url_ = "http://www.example.org/";
19343 RequestPolicy();
19344 histograms.ExpectBucketCount(
19345 ReportingHeaderParser::kHeaderOutcomeHistogram,
19346 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
19347}
19348
19349TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
19350 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5419351 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1019352 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5419353 reporting_context()->cache()->GetEndpointForTesting(
19354 url::Origin::Create(GURL("https://www.example.org/")), "nel",
19355 GURL("https://www.example.org/upload/"));
19356 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1419357}
19358
19359TEST_F(HttpNetworkTransactionReportingTest,
19360 DontProcessReportToHeaderInvalidHttps) {
19361 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219362 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19363 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1419364 histograms.ExpectBucketCount(
19365 ReportingHeaderParser::kHeaderOutcomeHistogram,
19366 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
19367}
19368#endif // BUILDFLAG(ENABLE_REPORTING)
19369
19370//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5219371// Network Error Logging tests
19372
19373#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4219374namespace {
19375
19376const char kUserAgent[] = "Mozilla/1.0";
19377const char kReferrer[] = "https://www.referrer.org/";
19378
19379} // namespace
19380
Douglas Creager3cb042052018-11-06 23:08:5219381class HttpNetworkTransactionNetworkErrorLoggingTest
19382 : public HttpNetworkTransactionTest {
19383 protected:
19384 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619385 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5219386 auto network_error_logging_service =
19387 std::make_unique<TestNetworkErrorLoggingService>();
19388 test_network_error_logging_service_ = network_error_logging_service.get();
19389 session_deps_.network_error_logging_service =
19390 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4219391
19392 extra_headers_.SetHeader("User-Agent", kUserAgent);
19393 extra_headers_.SetHeader("Referer", kReferrer);
19394
19395 request_.method = "GET";
19396 request_.url = GURL(url_);
19397 request_.extra_headers = extra_headers_;
19398 request_.reporting_upload_depth = reporting_upload_depth_;
19399 request_.traffic_annotation =
19400 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5219401 }
19402
19403 TestNetworkErrorLoggingService* network_error_logging_service() const {
19404 return test_network_error_logging_service_;
19405 }
19406
19407 void clear_network_error_logging_service() {
19408 session_deps_.network_error_logging_service.reset();
19409 test_network_error_logging_service_ = nullptr;
19410 }
19411
19412 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4219413 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3619414 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319415 MockWrite data_writes[] = {
19416 MockWrite("GET / HTTP/1.1\r\n"
19417 "Host: www.example.org\r\n"
19418 "Connection: keep-alive\r\n"),
19419 MockWrite(ASYNC, extra_header_string.data(),
19420 extra_header_string.size()),
19421 };
Lily Chend3930e72019-03-01 19:31:1119422 MockRead data_reads[] = {
19423 MockRead("HTTP/1.0 200 OK\r\n"),
19424 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19425 MockRead("\r\n"),
19426 MockRead("hello world"),
19427 MockRead(SYNCHRONOUS, OK),
19428 };
Douglas Creager3cb042052018-11-06 23:08:5219429
Lily Chenfec60d92019-01-24 01:16:4219430 StaticSocketDataProvider reads(data_reads, data_writes);
19431 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5219432
19433 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4219434 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5219435 ssl.ssl_info.cert =
19436 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19437 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219438 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5219439 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19440 }
19441
Douglas Creager3cb042052018-11-06 23:08:5219442 TestCompletionCallback callback;
19443 auto session = CreateSession(&session_deps_);
19444 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4219445 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
19446 EXPECT_THAT(callback.GetResult(rv), IsOk());
19447
19448 std::string response_data;
19449 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
19450 EXPECT_EQ("hello world", response_data);
19451 }
19452
19453 void CheckReport(size_t index,
19454 int status_code,
19455 int error_type,
19456 IPAddress server_ip = IPAddress::IPv4Localhost()) {
19457 ASSERT_LT(index, network_error_logging_service()->errors().size());
19458
19459 const NetworkErrorLoggingService::RequestDetails& error =
19460 network_error_logging_service()->errors()[index];
19461 EXPECT_EQ(url_, error.uri);
19462 EXPECT_EQ(kReferrer, error.referrer);
19463 EXPECT_EQ(kUserAgent, error.user_agent);
19464 EXPECT_EQ(server_ip, error.server_ip);
19465 EXPECT_EQ("http/1.1", error.protocol);
19466 EXPECT_EQ("GET", error.method);
19467 EXPECT_EQ(status_code, error.status_code);
19468 EXPECT_EQ(error_type, error.type);
19469 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5219470 }
19471
19472 protected:
19473 std::string url_ = "https://www.example.org/";
19474 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4219475 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3619476 HttpRequestHeaders extra_headers_;
19477 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5219478
19479 private:
19480 TestNetworkErrorLoggingService* test_network_error_logging_service_;
19481};
19482
19483TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19484 DontProcessNelHeaderNoService) {
19485 base::HistogramTester histograms;
19486 clear_network_error_logging_service();
19487 RequestPolicy();
19488 histograms.ExpectBucketCount(
19489 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19490 NetworkErrorLoggingService::HeaderOutcome::
19491 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
19492 1);
19493}
19494
19495TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19496 DontProcessNelHeaderHttp) {
19497 base::HistogramTester histograms;
19498 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4219499 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5219500 RequestPolicy();
19501 histograms.ExpectBucketCount(
19502 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19503 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
19504}
19505
Lily Chen90ae93cc2019-02-14 01:15:3919506// Don't set NEL policies received on a proxied connection.
19507TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19508 DontProcessNelHeaderProxy) {
19509 session_deps_.proxy_resolution_service =
19510 ProxyResolutionService::CreateFixedFromPacResult(
19511 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19512 BoundTestNetLog log;
19513 session_deps_.net_log = log.bound().net_log();
19514 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19515
19516 HttpRequestInfo request;
19517 request.method = "GET";
19518 request.url = GURL("https://www.example.org/");
19519 request.traffic_annotation =
19520 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19521
19522 // Since we have proxy, should try to establish tunnel.
19523 MockWrite data_writes1[] = {
19524 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19525 "Host: www.example.org:443\r\n"
19526 "Proxy-Connection: keep-alive\r\n\r\n"),
19527
19528 MockWrite("GET / HTTP/1.1\r\n"
19529 "Host: www.example.org\r\n"
19530 "Connection: keep-alive\r\n\r\n"),
19531 };
19532
19533 MockRead data_reads1[] = {
19534 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19535
19536 MockRead("HTTP/1.1 200 OK\r\n"),
19537 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19538 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19539 MockRead("Content-Length: 100\r\n\r\n"),
19540 MockRead(SYNCHRONOUS, OK),
19541 };
19542
19543 StaticSocketDataProvider data1(data_reads1, data_writes1);
19544 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19545 SSLSocketDataProvider ssl(ASYNC, OK);
19546 ssl.ssl_info.cert =
19547 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19548 ASSERT_TRUE(ssl.ssl_info.cert);
19549 ssl.ssl_info.cert_status = 0;
19550 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19551
19552 TestCompletionCallback callback1;
19553 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19554
19555 int rv = trans.Start(&request, callback1.callback(), log.bound());
19556 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19557
19558 rv = callback1.WaitForResult();
19559 EXPECT_THAT(rv, IsOk());
19560
19561 const HttpResponseInfo* response = trans.GetResponseInfo();
19562 ASSERT_TRUE(response);
19563 EXPECT_EQ(200, response->headers->response_code());
19564 EXPECT_TRUE(response->was_fetched_via_proxy);
19565
19566 // No NEL header was set.
19567 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
19568}
19569
Douglas Creager3cb042052018-11-06 23:08:5219570TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
19571 RequestPolicy();
19572 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
19573 const auto& header = network_error_logging_service()->headers()[0];
19574 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
19575 header.origin);
19576 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
19577 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
19578}
19579
19580TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19581 DontProcessNelHeaderInvalidHttps) {
19582 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4219583 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19584 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5219585 histograms.ExpectBucketCount(
19586 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
19587 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
19588 1);
19589}
Douglas Creageref5eecdc2018-11-09 20:50:3619590
Lily Chenfec60d92019-01-24 01:16:4219591TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3619592 RequestPolicy();
19593 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219594 CheckReport(0 /* index */, 200 /* status_code */, OK);
19595}
19596
19597TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19598 CreateReportErrorAfterStart) {
19599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19600 auto trans =
19601 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19602
19603 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
19604 StaticSocketDataProvider data;
19605 data.set_connect_data(mock_connect);
19606 session_deps_.socket_factory->AddSocketDataProvider(&data);
19607
19608 TestCompletionCallback callback;
19609
19610 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19611 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19612
19613 trans.reset();
19614
19615 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19616 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19617 IPAddress() /* server_ip */);
19618}
19619
19620// Same as above except the error is ASYNC
19621TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19622 CreateReportErrorAfterStartAsync) {
19623 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19624 auto trans =
19625 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19626
19627 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
19628 StaticSocketDataProvider data;
19629 data.set_connect_data(mock_connect);
19630 session_deps_.socket_factory->AddSocketDataProvider(&data);
19631
19632 TestCompletionCallback callback;
19633
19634 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19635 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
19636
19637 trans.reset();
19638
19639 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19640 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
19641 IPAddress() /* server_ip */);
19642}
19643
19644TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19645 CreateReportReadBodyError) {
19646 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319647 MockWrite data_writes[] = {
19648 MockWrite("GET / HTTP/1.1\r\n"
19649 "Host: www.example.org\r\n"
19650 "Connection: keep-alive\r\n"),
19651 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19652 };
Lily Chend3930e72019-03-01 19:31:1119653 MockRead data_reads[] = {
19654 MockRead("HTTP/1.0 200 OK\r\n"),
19655 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19656 MockRead("hello world"),
19657 MockRead(SYNCHRONOUS, OK),
19658 };
Lily Chenfec60d92019-01-24 01:16:4219659
19660 StaticSocketDataProvider reads(data_reads, data_writes);
19661 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19662
19663 SSLSocketDataProvider ssl(ASYNC, OK);
19664 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19665
19666 // Log start time
19667 base::TimeTicks start_time = base::TimeTicks::Now();
19668
19669 TestCompletionCallback callback;
19670 auto session = CreateSession(&session_deps_);
19671 auto trans =
19672 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19673 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19674 EXPECT_THAT(callback.GetResult(rv), IsOk());
19675
19676 const HttpResponseInfo* response = trans->GetResponseInfo();
19677 ASSERT_TRUE(response);
19678
19679 EXPECT_TRUE(response->headers);
19680 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19681
19682 std::string response_data;
19683 rv = ReadTransaction(trans.get(), &response_data);
19684 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19685
19686 trans.reset();
19687
19688 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19689
19690 CheckReport(0 /* index */, 200 /* status_code */,
19691 ERR_CONTENT_LENGTH_MISMATCH);
19692 const NetworkErrorLoggingService::RequestDetails& error =
19693 network_error_logging_service()->errors()[0];
19694 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19695}
19696
19697// Same as above except the final read is ASYNC.
19698TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19699 CreateReportReadBodyErrorAsync) {
19700 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319701 MockWrite data_writes[] = {
19702 MockWrite("GET / HTTP/1.1\r\n"
19703 "Host: www.example.org\r\n"
19704 "Connection: keep-alive\r\n"),
19705 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19706 };
Lily Chend3930e72019-03-01 19:31:1119707 MockRead data_reads[] = {
19708 MockRead("HTTP/1.0 200 OK\r\n"),
19709 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19710 MockRead("hello world"),
19711 MockRead(ASYNC, OK),
19712 };
Lily Chenfec60d92019-01-24 01:16:4219713
19714 StaticSocketDataProvider reads(data_reads, data_writes);
19715 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19716
19717 SSLSocketDataProvider ssl(ASYNC, OK);
19718 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19719
19720 // Log start time
19721 base::TimeTicks start_time = base::TimeTicks::Now();
19722
19723 TestCompletionCallback callback;
19724 auto session = CreateSession(&session_deps_);
19725 auto trans =
19726 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19727 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19728 EXPECT_THAT(callback.GetResult(rv), IsOk());
19729
19730 const HttpResponseInfo* response = trans->GetResponseInfo();
19731 ASSERT_TRUE(response);
19732
19733 EXPECT_TRUE(response->headers);
19734 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19735
19736 std::string response_data;
19737 rv = ReadTransaction(trans.get(), &response_data);
19738 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19739
19740 trans.reset();
19741
19742 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19743
19744 CheckReport(0 /* index */, 200 /* status_code */,
19745 ERR_CONTENT_LENGTH_MISMATCH);
19746 const NetworkErrorLoggingService::RequestDetails& error =
19747 network_error_logging_service()->errors()[0];
19748 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19749}
19750
19751TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19752 CreateReportRestartWithAuth) {
19753 std::string extra_header_string = extra_headers_.ToString();
19754 static const base::TimeDelta kSleepDuration =
19755 base::TimeDelta::FromMilliseconds(10);
19756
19757 MockWrite data_writes1[] = {
19758 MockWrite("GET / HTTP/1.1\r\n"
19759 "Host: www.example.org\r\n"
19760 "Connection: keep-alive\r\n"),
19761 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19762 };
19763
19764 MockRead data_reads1[] = {
19765 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19766 // Give a couple authenticate options (only the middle one is actually
19767 // supported).
19768 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19769 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19770 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19771 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19772 // Large content-length -- won't matter, as connection will be reset.
19773 MockRead("Content-Length: 10000\r\n\r\n"),
19774 MockRead(SYNCHRONOUS, ERR_FAILED),
19775 };
19776
19777 // After calling trans->RestartWithAuth(), this is the request we should
19778 // be issuing -- the final header line contains the credentials.
19779 MockWrite data_writes2[] = {
19780 MockWrite("GET / HTTP/1.1\r\n"
19781 "Host: www.example.org\r\n"
19782 "Connection: keep-alive\r\n"
19783 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19784 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19785 };
19786
19787 // Lastly, the server responds with the actual content.
19788 MockRead data_reads2[] = {
19789 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19790 MockRead("hello world"),
19791 MockRead(SYNCHRONOUS, OK),
19792 };
19793
19794 StaticSocketDataProvider data1(data_reads1, data_writes1);
19795 StaticSocketDataProvider data2(data_reads2, data_writes2);
19796 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19797 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19798
19799 SSLSocketDataProvider ssl1(ASYNC, OK);
19800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19801 SSLSocketDataProvider ssl2(ASYNC, OK);
19802 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19803
19804 base::TimeTicks start_time = base::TimeTicks::Now();
19805 base::TimeTicks restart_time;
19806
19807 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19808 auto trans =
19809 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19810
19811 TestCompletionCallback callback1;
19812
19813 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19814 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19815
19816 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19817
19818 TestCompletionCallback callback2;
19819
19820 // Wait 10 ms then restart with auth
19821 FastForwardBy(kSleepDuration);
19822 restart_time = base::TimeTicks::Now();
19823 rv =
19824 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19825 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19826
19827 std::string response_data;
19828 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19829 EXPECT_EQ("hello world", response_data);
19830
19831 trans.reset();
19832
19833 // One 401 report for the auth challenge, then a 200 report for the successful
19834 // retry. Note that we don't report the error draining the body, as the first
19835 // request already generated a report for the auth challenge.
19836 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19837
19838 // Check error report contents
19839 CheckReport(0 /* index */, 401 /* status_code */, OK);
19840 CheckReport(1 /* index */, 200 /* status_code */, OK);
19841
19842 const NetworkErrorLoggingService::RequestDetails& error1 =
19843 network_error_logging_service()->errors()[0];
19844 const NetworkErrorLoggingService::RequestDetails& error2 =
19845 network_error_logging_service()->errors()[1];
19846
19847 // Sanity-check elapsed time values
19848 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19849 // Check that the start time is refreshed when restarting with auth.
19850 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19851}
19852
19853// Same as above, except draining the body before restarting fails
19854// asynchronously.
19855TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19856 CreateReportRestartWithAuthAsync) {
19857 std::string extra_header_string = extra_headers_.ToString();
19858 static const base::TimeDelta kSleepDuration =
19859 base::TimeDelta::FromMilliseconds(10);
19860
19861 MockWrite data_writes1[] = {
19862 MockWrite("GET / HTTP/1.1\r\n"
19863 "Host: www.example.org\r\n"
19864 "Connection: keep-alive\r\n"),
19865 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19866 };
19867
19868 MockRead data_reads1[] = {
19869 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19870 // Give a couple authenticate options (only the middle one is actually
19871 // supported).
19872 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19873 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19874 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19875 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19876 // Large content-length -- won't matter, as connection will be reset.
19877 MockRead("Content-Length: 10000\r\n\r\n"),
19878 MockRead(ASYNC, ERR_FAILED),
19879 };
19880
19881 // After calling trans->RestartWithAuth(), this is the request we should
19882 // be issuing -- the final header line contains the credentials.
19883 MockWrite data_writes2[] = {
19884 MockWrite("GET / HTTP/1.1\r\n"
19885 "Host: www.example.org\r\n"
19886 "Connection: keep-alive\r\n"
19887 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19888 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19889 };
19890
19891 // Lastly, the server responds with the actual content.
19892 MockRead data_reads2[] = {
19893 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19894 MockRead("hello world"),
19895 MockRead(SYNCHRONOUS, OK),
19896 };
19897
19898 StaticSocketDataProvider data1(data_reads1, data_writes1);
19899 StaticSocketDataProvider data2(data_reads2, data_writes2);
19900 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19901 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19902
19903 SSLSocketDataProvider ssl1(ASYNC, OK);
19904 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19905 SSLSocketDataProvider ssl2(ASYNC, OK);
19906 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19907
19908 base::TimeTicks start_time = base::TimeTicks::Now();
19909 base::TimeTicks restart_time;
19910
19911 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19912 auto trans =
19913 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19914
19915 TestCompletionCallback callback1;
19916
19917 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19918 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19919
19920 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19921
19922 TestCompletionCallback callback2;
19923
19924 // Wait 10 ms then restart with auth
19925 FastForwardBy(kSleepDuration);
19926 restart_time = base::TimeTicks::Now();
19927 rv =
19928 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19929 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19930
19931 std::string response_data;
19932 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19933 EXPECT_EQ("hello world", response_data);
19934
19935 trans.reset();
19936
19937 // One 401 report for the auth challenge, then a 200 report for the successful
19938 // retry. Note that we don't report the error draining the body, as the first
19939 // request already generated a report for the auth challenge.
19940 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19941
19942 // Check error report contents
19943 CheckReport(0 /* index */, 401 /* status_code */, OK);
19944 CheckReport(1 /* index */, 200 /* status_code */, OK);
19945
19946 const NetworkErrorLoggingService::RequestDetails& error1 =
19947 network_error_logging_service()->errors()[0];
19948 const NetworkErrorLoggingService::RequestDetails& error2 =
19949 network_error_logging_service()->errors()[1];
19950
19951 // Sanity-check elapsed time values
19952 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19953 // Check that the start time is refreshed when restarting with auth.
19954 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19955}
19956
19957TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19958 CreateReportRetryKeepAliveConnectionReset) {
19959 std::string extra_header_string = extra_headers_.ToString();
19960 MockWrite data_writes1[] = {
19961 MockWrite("GET / HTTP/1.1\r\n"
19962 "Host: www.example.org\r\n"
19963 "Connection: keep-alive\r\n"),
19964 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19965 MockWrite("GET / HTTP/1.1\r\n"
19966 "Host: www.example.org\r\n"
19967 "Connection: keep-alive\r\n"),
19968 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19969 };
19970
19971 MockRead data_reads1[] = {
19972 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19973 MockRead("hello"),
19974 // Connection is reset
19975 MockRead(ASYNC, ERR_CONNECTION_RESET),
19976 };
19977
19978 // Successful retry
19979 MockRead data_reads2[] = {
19980 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19981 MockRead("world"),
19982 MockRead(ASYNC, OK),
19983 };
19984
19985 StaticSocketDataProvider data1(data_reads1, data_writes1);
19986 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19987 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19988 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19989
19990 SSLSocketDataProvider ssl1(ASYNC, OK);
19991 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19992 SSLSocketDataProvider ssl2(ASYNC, OK);
19993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19994
19995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19996 auto trans1 =
19997 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19998
19999 TestCompletionCallback callback1;
20000
20001 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20002 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20003
20004 std::string response_data;
20005 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20006 EXPECT_EQ("hello", response_data);
20007
20008 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20009
20010 auto trans2 =
20011 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20012
20013 TestCompletionCallback callback2;
20014
20015 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20016 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20017
20018 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20019 EXPECT_EQ("world", response_data);
20020
20021 trans1.reset();
20022 trans2.reset();
20023
20024 // One OK report from first request, then a ERR_CONNECTION_RESET report from
20025 // the second request, then an OK report from the successful retry.
20026 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20027
20028 // Check error report contents
20029 CheckReport(0 /* index */, 200 /* status_code */, OK);
20030 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
20031 CheckReport(2 /* index */, 200 /* status_code */, OK);
20032}
20033
20034TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20035 CreateReportRetryKeepAlive408) {
20036 std::string extra_header_string = extra_headers_.ToString();
20037 MockWrite data_writes1[] = {
20038 MockWrite("GET / HTTP/1.1\r\n"
20039 "Host: www.example.org\r\n"
20040 "Connection: keep-alive\r\n"),
20041 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20042 MockWrite("GET / HTTP/1.1\r\n"
20043 "Host: www.example.org\r\n"
20044 "Connection: keep-alive\r\n"),
20045 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20046 };
20047
20048 MockRead data_reads1[] = {
20049 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20050 MockRead("hello"),
20051 // 408 Request Timeout
20052 MockRead(SYNCHRONOUS,
20053 "HTTP/1.1 408 Request Timeout\r\n"
20054 "Connection: Keep-Alive\r\n"
20055 "Content-Length: 6\r\n\r\n"
20056 "Pickle"),
20057 };
20058
20059 // Successful retry
20060 MockRead data_reads2[] = {
20061 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20062 MockRead("world"),
20063 MockRead(ASYNC, OK),
20064 };
20065
20066 StaticSocketDataProvider data1(data_reads1, data_writes1);
20067 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20068 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20069 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20070
20071 SSLSocketDataProvider ssl1(ASYNC, OK);
20072 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20073 SSLSocketDataProvider ssl2(ASYNC, OK);
20074 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20075
20076 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20077 auto trans1 =
20078 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20079
20080 TestCompletionCallback callback1;
20081
20082 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20083 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20084
20085 std::string response_data;
20086 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20087 EXPECT_EQ("hello", response_data);
20088
20089 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20090
20091 auto trans2 =
20092 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20093
20094 TestCompletionCallback callback2;
20095
20096 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20097 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20098
20099 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20100 EXPECT_EQ("world", response_data);
20101
20102 trans1.reset();
20103 trans2.reset();
20104
20105 // One 200 report from first request, then a 408 report from
20106 // the second request, then a 200 report from the successful retry.
20107 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20108
20109 // Check error report contents
20110 CheckReport(0 /* index */, 200 /* status_code */, OK);
20111 CheckReport(1 /* index */, 408 /* status_code */, OK);
20112 CheckReport(2 /* index */, 200 /* status_code */, OK);
20113}
20114
20115TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20116 CreateReportRetry421WithoutConnectionPooling) {
20117 // Two hosts resolve to the same IP address.
20118 const std::string ip_addr = "1.2.3.4";
20119 IPAddress ip;
20120 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20121 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20122
20123 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20124 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20125 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20126
20127 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20128
20129 // Two requests on the first connection.
20130 spdy::SpdySerializedFrame req1(
20131 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20132 spdy_util_.UpdateWithStreamDestruction(1);
20133 spdy::SpdySerializedFrame req2(
20134 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20135 spdy::SpdySerializedFrame rst(
20136 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20137 MockWrite writes1[] = {
20138 CreateMockWrite(req1, 0),
20139 CreateMockWrite(req2, 3),
20140 CreateMockWrite(rst, 6),
20141 };
20142
20143 // The first one succeeds, the second gets error 421 Misdirected Request.
20144 spdy::SpdySerializedFrame resp1(
20145 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20146 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
20147 spdy::SpdyHeaderBlock response_headers;
20148 response_headers[spdy::kHttp2StatusHeader] = "421";
20149 spdy::SpdySerializedFrame resp2(
20150 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
20151 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20152 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20153
20154 MockConnect connect1(ASYNC, OK, peer_addr);
20155 SequencedSocketData data1(connect1, reads1, writes1);
20156 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20157
20158 AddSSLSocketData();
20159
20160 // Retry the second request on a second connection.
20161 SpdyTestUtil spdy_util2;
20162 spdy::SpdySerializedFrame req3(
20163 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20164 MockWrite writes2[] = {
20165 CreateMockWrite(req3, 0),
20166 };
20167
20168 spdy::SpdySerializedFrame resp3(
20169 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20170 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20171 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20172 MockRead(ASYNC, 0, 3)};
20173
20174 MockConnect connect2(ASYNC, OK, peer_addr);
20175 SequencedSocketData data2(connect2, reads2, writes2);
20176 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20177
20178 AddSSLSocketData();
20179
20180 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3320181 int rv = session_deps_.host_resolver->LoadIntoCache(
20182 HostPortPair("mail.example.com", 443), base::nullopt);
20183 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4220184
20185 HttpRequestInfo request1;
20186 request1.method = "GET";
20187 request1.url = GURL("https://www.example.org/");
20188 request1.load_flags = 0;
20189 request1.traffic_annotation =
20190 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20191 auto trans1 =
20192 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20193
Eric Orthf4db66a2019-02-19 21:35:3320194 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220195 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20196 EXPECT_THAT(callback.GetResult(rv), IsOk());
20197
20198 const HttpResponseInfo* response = trans1->GetResponseInfo();
20199 ASSERT_TRUE(response);
20200 ASSERT_TRUE(response->headers);
20201 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20202 EXPECT_TRUE(response->was_fetched_via_spdy);
20203 EXPECT_TRUE(response->was_alpn_negotiated);
20204 std::string response_data;
20205 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20206 EXPECT_EQ("hello!", response_data);
20207
20208 trans1.reset();
20209
20210 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20211
20212 HttpRequestInfo request2;
20213 request2.method = "GET";
20214 request2.url = GURL("https://mail.example.org/");
20215 request2.load_flags = 0;
20216 request2.traffic_annotation =
20217 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20218 auto trans2 =
20219 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20220
20221 BoundTestNetLog log;
20222 rv = trans2->Start(&request2, callback.callback(), log.bound());
20223 EXPECT_THAT(callback.GetResult(rv), IsOk());
20224
20225 response = trans2->GetResponseInfo();
20226 ASSERT_TRUE(response);
20227 ASSERT_TRUE(response->headers);
20228 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20229 EXPECT_TRUE(response->was_fetched_via_spdy);
20230 EXPECT_TRUE(response->was_alpn_negotiated);
20231 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20232 EXPECT_EQ("hello!", response_data);
20233
20234 trans2.reset();
20235
20236 // One 200 report from the first request, then a 421 report from the
20237 // second request, then a 200 report from the successful retry.
20238 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20239
20240 // Check error report contents
20241 const NetworkErrorLoggingService::RequestDetails& error1 =
20242 network_error_logging_service()->errors()[0];
20243 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
20244 EXPECT_TRUE(error1.referrer.is_empty());
20245 EXPECT_EQ("", error1.user_agent);
20246 EXPECT_EQ(ip, error1.server_ip);
20247 EXPECT_EQ("h2", error1.protocol);
20248 EXPECT_EQ("GET", error1.method);
20249 EXPECT_EQ(200, error1.status_code);
20250 EXPECT_EQ(OK, error1.type);
20251 EXPECT_EQ(0, error1.reporting_upload_depth);
20252
20253 const NetworkErrorLoggingService::RequestDetails& error2 =
20254 network_error_logging_service()->errors()[1];
20255 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
20256 EXPECT_TRUE(error2.referrer.is_empty());
20257 EXPECT_EQ("", error2.user_agent);
20258 EXPECT_EQ(ip, error2.server_ip);
20259 EXPECT_EQ("h2", error2.protocol);
20260 EXPECT_EQ("GET", error2.method);
20261 EXPECT_EQ(421, error2.status_code);
20262 EXPECT_EQ(OK, error2.type);
20263 EXPECT_EQ(0, error2.reporting_upload_depth);
20264
20265 const NetworkErrorLoggingService::RequestDetails& error3 =
20266 network_error_logging_service()->errors()[2];
20267 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
20268 EXPECT_TRUE(error3.referrer.is_empty());
20269 EXPECT_EQ("", error3.user_agent);
20270 EXPECT_EQ(ip, error3.server_ip);
20271 EXPECT_EQ("h2", error3.protocol);
20272 EXPECT_EQ("GET", error3.method);
20273 EXPECT_EQ(200, error3.status_code);
20274 EXPECT_EQ(OK, error3.type);
20275 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3620276}
20277
Lily Chend3930e72019-03-01 19:31:1120278TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20279 CreateReportCancelAfterStart) {
20280 StaticSocketDataProvider data;
20281 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
20282 session_deps_.socket_factory->AddSocketDataProvider(&data);
20283
20284 TestCompletionCallback callback;
20285 auto session = CreateSession(&session_deps_);
20286 auto trans =
20287 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20288 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20289 EXPECT_EQ(rv, ERR_IO_PENDING);
20290
20291 // Cancel after start.
20292 trans.reset();
20293
20294 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20295 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
20296 IPAddress() /* server_ip */);
20297}
20298
20299TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20300 CreateReportCancelBeforeReadingBody) {
20301 std::string extra_header_string = extra_headers_.ToString();
20302 MockWrite data_writes[] = {
20303 MockWrite("GET / HTTP/1.1\r\n"
20304 "Host: www.example.org\r\n"
20305 "Connection: keep-alive\r\n"),
20306 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20307 };
20308 MockRead data_reads[] = {
20309 MockRead("HTTP/1.0 200 OK\r\n"),
20310 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
20311 };
20312
20313 StaticSocketDataProvider data(data_reads, data_writes);
20314 session_deps_.socket_factory->AddSocketDataProvider(&data);
20315
20316 SSLSocketDataProvider ssl(ASYNC, OK);
20317 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20318
20319 TestCompletionCallback callback;
20320 auto session = CreateSession(&session_deps_);
20321 auto trans =
20322 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20323 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20324 EXPECT_THAT(callback.GetResult(rv), IsOk());
20325
20326 const HttpResponseInfo* response = trans->GetResponseInfo();
20327 ASSERT_TRUE(response);
20328
20329 EXPECT_TRUE(response->headers);
20330 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20331
20332 // Cancel before reading the body.
20333 trans.reset();
20334
20335 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20336 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
20337}
20338
Lily Chen00196ab62018-12-04 19:52:2920339TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
20340 base::HistogramTester histograms;
20341 RequestPolicy();
20342 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20343 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20344
20345 // Make HTTP request
20346 std::string extra_header_string = extra_headers_.ToString();
20347 MockRead data_reads[] = {
20348 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20349 MockRead("hello world"),
20350 MockRead(SYNCHRONOUS, OK),
20351 };
20352 MockWrite data_writes[] = {
20353 MockWrite("GET / HTTP/1.1\r\n"
20354 "Host: www.example.org\r\n"
20355 "Connection: keep-alive\r\n"),
20356 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20357 };
20358
Lily Chend3930e72019-03-01 19:31:1120359 StaticSocketDataProvider data(data_reads, data_writes);
20360 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2920361
Lily Chenfec60d92019-01-24 01:16:4220362 // Insecure url
20363 url_ = "http://www.example.org/";
20364 request_.url = GURL(url_);
20365
Lily Chen00196ab62018-12-04 19:52:2920366 TestCompletionCallback callback;
20367 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4220368 auto trans =
20369 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20370 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20371 EXPECT_THAT(callback.GetResult(rv), IsOk());
20372
20373 std::string response_data;
20374 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20375 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2920376
20377 // Insecure request does not generate a report
20378 histograms.ExpectBucketCount(
20379 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0520380 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2920381
20382 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20383}
20384
20385TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20386 DontCreateReportHttpError) {
20387 base::HistogramTester histograms;
20388 RequestPolicy();
20389 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20390 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20391
20392 // Make HTTP request that fails
20393 MockRead data_reads[] = {
20394 MockRead("hello world"),
20395 MockRead(SYNCHRONOUS, OK),
20396 };
20397
20398 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
20399 session_deps_.socket_factory->AddSocketDataProvider(&data);
20400
Lily Chenfec60d92019-01-24 01:16:4220401 url_ = "http://www.originwithoutpolicy.com:2000/";
20402 request_.url = GURL(url_);
20403
Lily Chen00196ab62018-12-04 19:52:2920404 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20405
Lily Chen00196ab62018-12-04 19:52:2920406 auto trans =
20407 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2920408 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220409 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2920410 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
20411
20412 // Insecure request does not generate a report, regardless of existence of a
20413 // policy for the origin.
20414 histograms.ExpectBucketCount(
20415 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0520416 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2920417
20418 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20419}
20420
Lily Chen90ae93cc2019-02-14 01:15:3920421// Don't report on proxy auth challenges, don't report if connecting through a
20422// proxy.
20423TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
20424 HttpRequestInfo request;
20425 request.method = "GET";
20426 request.url = GURL("https://www.example.org/");
20427 request.traffic_annotation =
20428 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20429
20430 // Configure against proxy server "myproxy:70".
20431 session_deps_.proxy_resolution_service =
20432 ProxyResolutionService::CreateFixedFromPacResult(
20433 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20434 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20435
20436 // Since we have proxy, should try to establish tunnel.
20437 MockWrite data_writes1[] = {
20438 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20439 "Host: www.example.org:443\r\n"
20440 "Proxy-Connection: keep-alive\r\n\r\n"),
20441 };
20442
20443 // The proxy responds to the connect with a 407, using a non-persistent
20444 // connection.
20445 MockRead data_reads1[] = {
20446 // No credentials.
20447 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
20448 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20449 MockRead("Proxy-Connection: close\r\n\r\n"),
20450 };
20451
20452 MockWrite data_writes2[] = {
20453 // After calling trans->RestartWithAuth(), this is the request we should
20454 // be issuing -- the final header line contains the credentials.
20455 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20456 "Host: www.example.org:443\r\n"
20457 "Proxy-Connection: keep-alive\r\n"
20458 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
20459
20460 MockWrite("GET / HTTP/1.1\r\n"
20461 "Host: www.example.org\r\n"
20462 "Connection: keep-alive\r\n\r\n"),
20463 };
20464
20465 MockRead data_reads2[] = {
20466 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
20467
20468 MockRead("HTTP/1.1 200 OK\r\n"),
20469 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20470 MockRead("Content-Length: 5\r\n\r\n"),
20471 MockRead(SYNCHRONOUS, "hello"),
20472 };
20473
20474 StaticSocketDataProvider data1(data_reads1, data_writes1);
20475 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20476 StaticSocketDataProvider data2(data_reads2, data_writes2);
20477 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20478 SSLSocketDataProvider ssl(ASYNC, OK);
20479 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20480
20481 TestCompletionCallback callback1;
20482
20483 auto trans =
20484 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20485
20486 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
20487 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20488
20489 const HttpResponseInfo* response = trans->GetResponseInfo();
20490 EXPECT_EQ(407, response->headers->response_code());
20491
20492 std::string response_data;
20493 rv = ReadTransaction(trans.get(), &response_data);
20494 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
20495
20496 // No NEL report is generated for the 407.
20497 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20498
20499 TestCompletionCallback callback2;
20500
20501 rv =
20502 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20503 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20504
20505 response = trans->GetResponseInfo();
20506 EXPECT_EQ(200, response->headers->response_code());
20507
20508 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20509 EXPECT_EQ("hello", response_data);
20510
20511 trans.reset();
20512
20513 // No NEL report is generated because we are behind a proxy.
20514 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20515}
20516
Douglas Creageref5eecdc2018-11-09 20:50:3620517TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20518 ReportContainsUploadDepth) {
20519 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4220520 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3620521 RequestPolicy();
20522 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220523 const NetworkErrorLoggingService::RequestDetails& error =
20524 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3620525 EXPECT_EQ(7, error.reporting_upload_depth);
20526}
20527
Lily Chenfec60d92019-01-24 01:16:4220528TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
20529 std::string extra_header_string = extra_headers_.ToString();
20530 static const base::TimeDelta kSleepDuration =
20531 base::TimeDelta::FromMilliseconds(10);
20532
20533 std::vector<MockWrite> data_writes = {
20534 MockWrite(ASYNC, 0,
20535 "GET / HTTP/1.1\r\n"
20536 "Host: www.example.org\r\n"
20537 "Connection: keep-alive\r\n"),
20538 MockWrite(ASYNC, 1, extra_header_string.data()),
20539 };
20540
20541 std::vector<MockRead> data_reads = {
20542 // Write one byte of the status line, followed by a pause.
20543 MockRead(ASYNC, 2, "H"),
20544 MockRead(ASYNC, ERR_IO_PENDING, 3),
20545 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
20546 MockRead(ASYNC, 5, "hello world"),
20547 MockRead(SYNCHRONOUS, OK, 6),
20548 };
20549
20550 SequencedSocketData data(data_reads, data_writes);
20551 session_deps_.socket_factory->AddSocketDataProvider(&data);
20552
20553 SSLSocketDataProvider ssl(ASYNC, OK);
20554 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20555
20556 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20557
20558 auto trans =
20559 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20560
20561 TestCompletionCallback callback;
20562
20563 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20564 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20565
20566 data.RunUntilPaused();
20567 ASSERT_TRUE(data.IsPaused());
20568 FastForwardBy(kSleepDuration);
20569 data.Resume();
20570
20571 EXPECT_THAT(callback.GetResult(rv), IsOk());
20572
20573 std::string response_data;
20574 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20575 EXPECT_EQ("hello world", response_data);
20576
20577 trans.reset();
20578
Douglas Creageref5eecdc2018-11-09 20:50:3620579 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220580
20581 CheckReport(0 /* index */, 200 /* status_code */, OK);
20582
20583 const NetworkErrorLoggingService::RequestDetails& error =
20584 network_error_logging_service()->errors()[0];
20585
20586 // Sanity-check elapsed time in error report
20587 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3620588}
Lily Chenfec60d92019-01-24 01:16:4220589
Douglas Creager3cb042052018-11-06 23:08:5220590#endif // BUILDFLAG(ENABLE_REPORTING)
20591
Batalov Vladislava4e97a502019-04-11 15:35:2320592TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
20593 HttpRequestInfo request;
20594 request.method = "GET";
20595 request.url = GURL("http://example.org/");
20596
20597 request.load_flags = LOAD_ONLY_FROM_CACHE;
20598
20599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20600 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
20601 TestCompletionCallback callback1;
20602 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
20603
20604 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
20605}
20606
Steven Valdez1c1859172019-04-10 15:33:2820607TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
20608 HttpRequestInfo request;
20609 request.method = "GET";
20610 request.url = GURL("https://www.example.org/");
20611 request.traffic_annotation =
20612 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20613
20614 MockWrite data_writes[] = {
20615 MockWrite("GET / HTTP/1.1\r\n"
20616 "Host: www.example.org\r\n"
20617 "Connection: keep-alive\r\n\r\n"),
20618 };
20619
Steven Valdez1c1859172019-04-10 15:33:2820620 MockRead data_reads[] = {
20621 MockRead("HTTP/1.1 200 OK\r\n"),
20622 MockRead("Content-Length: 1\r\n\r\n"),
20623 MockRead(SYNCHRONOUS, "1"),
20624 };
20625
20626 StaticSocketDataProvider data(data_reads, data_writes);
20627 session_deps_.socket_factory->AddSocketDataProvider(&data);
20628 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20629 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20630 session_deps_.enable_early_data = true;
20631 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20632
20633 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20634
20635 TestCompletionCallback callback;
20636 auto trans =
20637 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20638
20639 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20640 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20641
20642 rv = callback.WaitForResult();
20643 EXPECT_THAT(rv, IsOk());
20644
20645 const HttpResponseInfo* response = trans->GetResponseInfo();
20646 ASSERT_TRUE(response);
20647 ASSERT_TRUE(response->headers);
20648 EXPECT_EQ(200, response->headers->response_code());
20649 EXPECT_EQ(1, response->headers->GetContentLength());
20650
20651 // Check that ConfirmHandshake wasn't called.
20652 ASSERT_FALSE(ssl.ConfirmDataConsumed());
20653 ASSERT_TRUE(ssl.WriteBeforeConfirm());
20654
20655 trans.reset();
20656
20657 session->CloseAllConnections();
20658}
20659
20660TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
20661 HttpRequestInfo request;
20662 request.method = "POST";
20663 request.url = GURL("https://www.example.org/");
20664 request.traffic_annotation =
20665 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20666
20667 MockWrite data_writes[] = {
20668 MockWrite(SYNCHRONOUS,
20669 "POST / HTTP/1.1\r\n"
20670 "Host: www.example.org\r\n"
20671 "Connection: keep-alive\r\n"
20672 "Content-Length: 0\r\n\r\n"),
20673 };
20674
Steven Valdez1c1859172019-04-10 15:33:2820675 MockRead data_reads[] = {
20676 MockRead("HTTP/1.1 200 OK\r\n"),
20677 MockRead("Content-Length: 1\r\n\r\n"),
20678 MockRead(SYNCHRONOUS, "1"),
20679 };
20680
20681 StaticSocketDataProvider data(data_reads, data_writes);
20682 session_deps_.socket_factory->AddSocketDataProvider(&data);
20683 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20684 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20685 session_deps_.enable_early_data = true;
20686 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20687
20688 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20689
20690 TestCompletionCallback callback;
20691 auto trans =
20692 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20693
20694 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20695 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20696
20697 rv = callback.WaitForResult();
20698 EXPECT_THAT(rv, IsOk());
20699
20700 const HttpResponseInfo* response = trans->GetResponseInfo();
20701 ASSERT_TRUE(response);
20702 ASSERT_TRUE(response->headers);
20703 EXPECT_EQ(200, response->headers->response_code());
20704 EXPECT_EQ(1, response->headers->GetContentLength());
20705
20706 // Check that the Write didn't get called before ConfirmHandshake completed.
20707 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20708
20709 trans.reset();
20710
20711 session->CloseAllConnections();
20712}
20713
20714TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
20715 HttpRequestInfo request;
20716 request.method = "POST";
20717 request.url = GURL("https://www.example.org/");
20718 request.traffic_annotation =
20719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20720
20721 MockWrite data_writes[] = {
20722 MockWrite(ASYNC,
20723 "POST / HTTP/1.1\r\n"
20724 "Host: www.example.org\r\n"
20725 "Connection: keep-alive\r\n"
20726 "Content-Length: 0\r\n\r\n"),
20727 };
20728
Steven Valdez1c1859172019-04-10 15:33:2820729 MockRead data_reads[] = {
20730 MockRead("HTTP/1.1 200 OK\r\n"),
20731 MockRead("Content-Length: 1\r\n\r\n"),
20732 MockRead(SYNCHRONOUS, "1"),
20733 };
20734
20735 StaticSocketDataProvider data(data_reads, data_writes);
20736 session_deps_.socket_factory->AddSocketDataProvider(&data);
20737 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20738 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20739 session_deps_.enable_early_data = true;
20740 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20741
20742 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20743
20744 TestCompletionCallback callback;
20745 auto trans =
20746 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20747
20748 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20749 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20750
20751 rv = callback.WaitForResult();
20752 EXPECT_THAT(rv, IsOk());
20753
20754 const HttpResponseInfo* response = trans->GetResponseInfo();
20755 ASSERT_TRUE(response);
20756 ASSERT_TRUE(response->headers);
20757 EXPECT_EQ(200, response->headers->response_code());
20758 EXPECT_EQ(1, response->headers->GetContentLength());
20759
20760 // Check that the Write didn't get called before ConfirmHandshake completed.
20761 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20762
20763 trans.reset();
20764
20765 session->CloseAllConnections();
20766}
20767
20768TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
20769 HttpRequestInfo request;
20770 request.method = "POST";
20771 request.url = GURL("https://www.example.org/");
20772 request.traffic_annotation =
20773 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20774
20775 MockWrite data_writes[] = {
20776 MockWrite(SYNCHRONOUS,
20777 "POST / HTTP/1.1\r\n"
20778 "Host: www.example.org\r\n"
20779 "Connection: keep-alive\r\n"
20780 "Content-Length: 0\r\n\r\n"),
20781 };
20782
Steven Valdez1c1859172019-04-10 15:33:2820783 MockRead data_reads[] = {
20784 MockRead("HTTP/1.1 200 OK\r\n"),
20785 MockRead("Content-Length: 1\r\n\r\n"),
20786 MockRead(SYNCHRONOUS, "1"),
20787 };
20788
20789 StaticSocketDataProvider data(data_reads, data_writes);
20790 session_deps_.socket_factory->AddSocketDataProvider(&data);
20791 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20792 ssl.confirm = MockConfirm(ASYNC, OK);
20793 session_deps_.enable_early_data = true;
20794 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20795
20796 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20797
20798 TestCompletionCallback callback;
20799 auto trans =
20800 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20801
20802 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20803 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20804
20805 rv = callback.WaitForResult();
20806 EXPECT_THAT(rv, IsOk());
20807
20808 const HttpResponseInfo* response = trans->GetResponseInfo();
20809 ASSERT_TRUE(response);
20810 ASSERT_TRUE(response->headers);
20811 EXPECT_EQ(200, response->headers->response_code());
20812 EXPECT_EQ(1, response->headers->GetContentLength());
20813
20814 // Check that the Write didn't get called before ConfirmHandshake completed.
20815 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20816
20817 trans.reset();
20818
20819 session->CloseAllConnections();
20820}
20821
20822TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
20823 HttpRequestInfo request;
20824 request.method = "POST";
20825 request.url = GURL("https://www.example.org/");
20826 request.traffic_annotation =
20827 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20828
20829 MockWrite data_writes[] = {
20830 MockWrite(ASYNC,
20831 "POST / HTTP/1.1\r\n"
20832 "Host: www.example.org\r\n"
20833 "Connection: keep-alive\r\n"
20834 "Content-Length: 0\r\n\r\n"),
20835 };
20836
Steven Valdez1c1859172019-04-10 15:33:2820837 MockRead data_reads[] = {
20838 MockRead("HTTP/1.1 200 OK\r\n"),
20839 MockRead("Content-Length: 1\r\n\r\n"),
20840 MockRead(SYNCHRONOUS, "1"),
20841 };
20842
20843 StaticSocketDataProvider data(data_reads, data_writes);
20844 session_deps_.socket_factory->AddSocketDataProvider(&data);
20845 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20846 ssl.confirm = MockConfirm(ASYNC, OK);
20847 session_deps_.enable_early_data = true;
20848 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20849
20850 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20851
20852 TestCompletionCallback callback;
20853 auto trans =
20854 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20855
20856 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20857 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20858
20859 rv = callback.WaitForResult();
20860 EXPECT_THAT(rv, IsOk());
20861
20862 const HttpResponseInfo* response = trans->GetResponseInfo();
20863 ASSERT_TRUE(response);
20864 ASSERT_TRUE(response->headers);
20865 EXPECT_EQ(200, response->headers->response_code());
20866 EXPECT_EQ(1, response->headers->GetContentLength());
20867
20868 // Check that the Write didn't get called before ConfirmHandshake completed.
20869 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20870
20871 trans.reset();
20872
20873 session->CloseAllConnections();
20874}
20875
David Benjaminfb976932019-05-15 13:39:1520876// 0-RTT rejects are handled at HttpNetworkTransaction.
20877TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
20878 enum class RejectType {
20879 kRead,
20880 kWrite,
20881 kConfirm,
20882 };
20883
20884 for (RejectType type :
20885 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
20886 SCOPED_TRACE(static_cast<int>(type));
20887 for (Error reject_error :
20888 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
20889 SCOPED_TRACE(reject_error);
20890 session_deps_.socket_factory =
20891 std::make_unique<MockClientSocketFactory>();
20892
20893 HttpRequestInfo request;
20894 request.method = type == RejectType::kConfirm ? "POST" : "GET";
20895 request.url = GURL("https://www.example.org/");
20896 request.traffic_annotation =
20897 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20898
20899 // The first request fails.
20900 std::vector<MockWrite> data1_writes;
20901 std::vector<MockRead> data1_reads;
20902 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
20903 switch (type) {
20904 case RejectType::kRead:
20905 data1_writes.emplace_back(
20906 "GET / HTTP/1.1\r\n"
20907 "Host: www.example.org\r\n"
20908 "Connection: keep-alive\r\n\r\n");
20909 data1_reads.emplace_back(ASYNC, reject_error);
20910 // Cause ConfirmHandshake to hang (it should not be called).
20911 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20912 break;
20913 case RejectType::kWrite:
20914 data1_writes.emplace_back(ASYNC, reject_error);
20915 // Cause ConfirmHandshake to hang (it should not be called).
20916 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20917 break;
20918 case RejectType::kConfirm:
20919 // The request never gets far enough to read or write.
20920 ssl1.confirm = MockConfirm(ASYNC, reject_error);
20921 break;
20922 }
20923
20924 StaticSocketDataProvider data1(data1_reads, data1_writes);
20925 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20926 session_deps_.enable_early_data = true;
20927 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20928
20929 // The retry succeeds.
20930 //
20931 // TODO(https://crbug.com/950705): If |reject_error| is
20932 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
20933 MockWrite data2_writes[] = {
20934 request.method == "POST"
20935 ? MockWrite("POST / HTTP/1.1\r\n"
20936 "Host: www.example.org\r\n"
20937 "Connection: keep-alive\r\n"
20938 "Content-Length: 0\r\n\r\n")
20939 : MockWrite("GET / HTTP/1.1\r\n"
20940 "Host: www.example.org\r\n"
20941 "Connection: keep-alive\r\n\r\n"),
20942 };
20943
20944 MockRead data2_reads[] = {
20945 MockRead("HTTP/1.1 200 OK\r\n"),
20946 MockRead("Content-Length: 1\r\n\r\n"),
20947 MockRead(SYNCHRONOUS, "1"),
20948 };
20949
20950 StaticSocketDataProvider data2(data2_reads, data2_writes);
20951 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20952 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
20953 ssl2.confirm = MockConfirm(ASYNC, OK);
20954 session_deps_.enable_early_data = true;
20955 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20956
20957 std::unique_ptr<HttpNetworkSession> session(
20958 CreateSession(&session_deps_));
20959
20960 TestCompletionCallback callback;
20961 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20962 session.get());
20963
20964 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20965 NetLogWithSource())),
20966 IsOk());
20967
20968 const HttpResponseInfo* response = trans->GetResponseInfo();
20969 ASSERT_TRUE(response);
20970 ASSERT_TRUE(response->headers);
20971 EXPECT_EQ(200, response->headers->response_code());
20972 EXPECT_EQ(1, response->headers->GetContentLength());
20973 }
20974 }
20975}
20976
Steven Valdez1c1859172019-04-10 15:33:2820977TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
20978 HttpRequestInfo request;
20979 request.method = "POST";
20980 request.url = GURL("https://www.example.org/");
20981 request.traffic_annotation =
20982 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20983
20984 MockWrite data_writes[] = {
20985 MockWrite("POST / HTTP/1.1\r\n"
20986 "Host: www.example.org\r\n"
20987 "Connection: keep-alive\r\n"
20988 "Content-Length: 0\r\n\r\n"),
20989 };
20990
Steven Valdez1c1859172019-04-10 15:33:2820991 MockRead data_reads[] = {
20992 MockRead("HTTP/1.1 200 OK\r\n"),
20993 MockRead("Content-Length: 1\r\n\r\n"),
20994 MockRead(SYNCHRONOUS, "1"),
20995 };
20996
20997 StaticSocketDataProvider data(data_reads, data_writes);
20998 session_deps_.socket_factory->AddSocketDataProvider(&data);
20999 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21000 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
21001 session_deps_.enable_early_data = true;
21002 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21003
21004 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21005
21006 TestCompletionCallback callback;
21007 auto trans =
21008 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21009
21010 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21011 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21012
21013 rv = callback.WaitForResult();
21014 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21015
21016 // Check that the Write didn't get called before ConfirmHandshake completed.
21017 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21018
21019 trans.reset();
21020
21021 session->CloseAllConnections();
21022}
21023
21024TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
21025 HttpRequestInfo request;
21026 request.method = "POST";
21027 request.url = GURL("https://www.example.org/");
21028 request.traffic_annotation =
21029 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21030
21031 MockWrite data_writes[] = {
21032 MockWrite("POST / HTTP/1.1\r\n"
21033 "Host: www.example.org\r\n"
21034 "Connection: keep-alive\r\n"
21035 "Content-Length: 0\r\n\r\n"),
21036 };
21037
Steven Valdez1c1859172019-04-10 15:33:2821038 MockRead data_reads[] = {
21039 MockRead("HTTP/1.1 200 OK\r\n"),
21040 MockRead("Content-Length: 1\r\n\r\n"),
21041 MockRead(SYNCHRONOUS, "1"),
21042 };
21043
21044 StaticSocketDataProvider data(data_reads, data_writes);
21045 session_deps_.socket_factory->AddSocketDataProvider(&data);
21046 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21047 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
21048 session_deps_.enable_early_data = true;
21049 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21050
21051 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21052
21053 TestCompletionCallback callback;
21054 auto trans =
21055 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21056
21057 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21058 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21059
21060 rv = callback.WaitForResult();
21061 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21062
21063 // Check that the Write didn't get called before ConfirmHandshake completed.
21064 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21065
21066 trans.reset();
21067
21068 session->CloseAllConnections();
21069}
21070
David Benjamin2eb827f2019-04-29 18:31:0421071// Test the proxy and origin server each requesting both TLS client certificates
21072// and HTTP auth. This is a regression test for https://crbug.com/946406.
21073TEST_F(HttpNetworkTransactionTest, AuthEverything) {
21074 // Note these hosts must match the CheckBasic*Auth() functions.
21075 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21076 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21077
21078 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21079 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21080
21081 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21082 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21083 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21084 ASSERT_TRUE(identity_proxy);
21085
21086 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21087 cert_request_info_origin->host_and_port =
21088 HostPortPair("www.example.org", 443);
21089
21090 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21091 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21092 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21093 ASSERT_TRUE(identity_origin);
21094
21095 HttpRequestInfo request;
21096 request.method = "GET";
21097 request.url = GURL("https://www.example.org/");
21098 request.traffic_annotation =
21099 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21100
David Benjamin7ebab032019-04-30 21:51:3021101 // First, the client connects to the proxy, which requests a client
21102 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421103 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21104 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21105 ssl_proxy1.expected_send_client_cert = false;
David Benjamin2eb827f2019-04-29 18:31:0421106 StaticSocketDataProvider data1;
21107 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021108 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421109
David Benjamin7ebab032019-04-30 21:51:3021110 // The client responds with a certificate on a new connection. The handshake
21111 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421112 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21113 ssl_proxy2.expected_send_client_cert = true;
21114 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021115 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421116 std::vector<MockWrite> mock_writes2;
21117 std::vector<MockRead> mock_reads2;
21118 mock_writes2.emplace_back(
21119 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21120 "Host: www.example.org:443\r\n"
21121 "Proxy-Connection: keep-alive\r\n\r\n");
21122 mock_reads2.emplace_back(
21123 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21124 "Content-Length: 0\r\n"
21125 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021126 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0421127 mock_writes2.emplace_back(
21128 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21129 "Host: www.example.org:443\r\n"
21130 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021131 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421132 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21133 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21134 // The origin requests client certificates.
21135 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21136 ssl_origin2.cert_request_info = cert_request_info_origin.get();
David Benjamin2eb827f2019-04-29 18:31:0421137 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21138 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021139 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21140 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0421141
David Benjamin7ebab032019-04-30 21:51:3021142 // The client responds to the origin client certificate request on a new
21143 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421144 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21145 ssl_proxy3.expected_send_client_cert = true;
21146 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
David Benjamin2eb827f2019-04-29 18:31:0421147 std::vector<MockWrite> mock_writes3;
21148 std::vector<MockRead> mock_reads3;
21149 mock_writes3.emplace_back(
21150 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21151 "Host: www.example.org:443\r\n"
21152 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021153 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421154 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21155 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21156 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
21157 ssl_origin3.expected_send_client_cert = true;
21158 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021159 // The client sends the origin HTTP request, which results in another HTTP
21160 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0421161 mock_writes3.emplace_back(
21162 "GET / HTTP/1.1\r\n"
21163 "Host: www.example.org\r\n"
21164 "Connection: keep-alive\r\n\r\n");
21165 mock_reads3.emplace_back(
21166 "HTTP/1.1 401 Unauthorized\r\n"
21167 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21168 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021169 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421170 mock_writes3.emplace_back(
21171 "GET / HTTP/1.1\r\n"
21172 "Host: www.example.org\r\n"
21173 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021174 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421175 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21176 mock_reads3.emplace_back(
21177 "HTTP/1.1 200 OK\r\n"
21178 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4121179 // The client makes another request. This should reuse the socket with all
21180 // credentials cached.
21181 mock_writes3.emplace_back(
21182 "GET / HTTP/1.1\r\n"
21183 "Host: www.example.org\r\n"
21184 "Connection: keep-alive\r\n"
21185 // Authenticate as user:pass.
21186 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21187 mock_reads3.emplace_back(
21188 "HTTP/1.1 200 OK\r\n"
21189 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0421190 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21191 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021192 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21193 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421194
21195 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21196
21197 // Start the request.
21198 TestCompletionCallback callback;
21199 auto trans =
21200 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21201 int rv = callback.GetResult(
21202 trans->Start(&request, callback.callback(), NetLogWithSource()));
21203
21204 // Handle the proxy client certificate challenge.
21205 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21206 SSLCertRequestInfo* cert_request_info =
21207 trans->GetResponseInfo()->cert_request_info.get();
21208 ASSERT_TRUE(cert_request_info);
21209 EXPECT_TRUE(cert_request_info->is_proxy);
21210 EXPECT_EQ(cert_request_info->host_and_port,
21211 cert_request_info_proxy->host_and_port);
21212 rv = callback.GetResult(trans->RestartWithCertificate(
21213 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21214 callback.callback()));
21215
21216 // Handle the proxy HTTP auth challenge.
21217 ASSERT_THAT(rv, IsOk());
21218 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21219 EXPECT_TRUE(
21220 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21221 rv = callback.GetResult(trans->RestartWithAuth(
21222 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21223 callback.callback()));
21224
21225 // Handle the origin client certificate challenge.
21226 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21227 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21228 ASSERT_TRUE(cert_request_info);
21229 EXPECT_FALSE(cert_request_info->is_proxy);
21230 EXPECT_EQ(cert_request_info->host_and_port,
21231 cert_request_info_origin->host_and_port);
21232 rv = callback.GetResult(trans->RestartWithCertificate(
21233 identity_origin->certificate(), identity_origin->ssl_private_key(),
21234 callback.callback()));
21235
21236 // Handle the origin HTTP auth challenge.
21237 ASSERT_THAT(rv, IsOk());
21238 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21239 EXPECT_TRUE(
21240 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21241 rv = callback.GetResult(trans->RestartWithAuth(
21242 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21243 callback.callback()));
21244
21245 // The request completes.
21246 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021247 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121248
21249 // Make a second request. This time all credentials are cached.
21250 trans =
21251 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21252 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21253 NetLogWithSource())),
21254 IsOk());
21255 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421256}
21257
21258// Test the proxy and origin server each requesting both TLS client certificates
21259// and HTTP auth and each HTTP auth closing the connection. This is a regression
21260// test for https://crbug.com/946406.
21261TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
21262 // Note these hosts must match the CheckBasic*Auth() functions.
21263 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21264 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21265
21266 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21267 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21268
21269 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21270 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21271 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21272 ASSERT_TRUE(identity_proxy);
21273
21274 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21275 cert_request_info_origin->host_and_port =
21276 HostPortPair("www.example.org", 443);
21277
21278 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21279 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21280 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21281 ASSERT_TRUE(identity_origin);
21282
21283 HttpRequestInfo request;
21284 request.method = "GET";
21285 request.url = GURL("https://www.example.org/");
21286 request.traffic_annotation =
21287 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21288
David Benjamin7ebab032019-04-30 21:51:3021289 // First, the client connects to the proxy, which requests a client
21290 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421291 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21292 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21293 ssl_proxy1.expected_send_client_cert = false;
21294 StaticSocketDataProvider data1;
21295 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021296 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421297
David Benjamin7ebab032019-04-30 21:51:3021298 // The client responds with a certificate on a new connection. The handshake
21299 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421300 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21301 ssl_proxy2.expected_send_client_cert = true;
21302 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021303 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421304 std::vector<MockWrite> mock_writes2;
21305 std::vector<MockRead> mock_reads2;
21306 mock_writes2.emplace_back(
21307 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21308 "Host: www.example.org:443\r\n"
21309 "Proxy-Connection: keep-alive\r\n\r\n");
21310 mock_reads2.emplace_back(
21311 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21312 "Content-Length: 0\r\n"
21313 "Proxy-Connection: close\r\n"
21314 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21315 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21316 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021317 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0421318
David Benjamin7ebab032019-04-30 21:51:3021319 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0421320 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21321 ssl_proxy3.expected_send_client_cert = true;
21322 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21323 std::vector<MockWrite> mock_writes3;
21324 std::vector<MockRead> mock_reads3;
21325 mock_writes3.emplace_back(
21326 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21327 "Host: www.example.org:443\r\n"
21328 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021329 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421330 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21331 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21332 // The origin requests client certificates.
21333 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21334 ssl_origin3.cert_request_info = cert_request_info_origin.get();
21335 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21336 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021337 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21338 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421339
David Benjamin7ebab032019-04-30 21:51:3021340 // The client responds to the origin client certificate request on a new
21341 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421342 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
21343 ssl_proxy4.expected_send_client_cert = true;
21344 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
21345 std::vector<MockWrite> mock_writes4;
21346 std::vector<MockRead> mock_reads4;
21347 mock_writes4.emplace_back(
21348 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21349 "Host: www.example.org:443\r\n"
21350 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021351 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421352 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21353 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21354 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
21355 ssl_origin4.expected_send_client_cert = true;
21356 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021357 // The client sends the origin HTTP request, which results in another HTTP
21358 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0421359 mock_writes4.emplace_back(
21360 "GET / HTTP/1.1\r\n"
21361 "Host: www.example.org\r\n"
21362 "Connection: keep-alive\r\n\r\n");
21363 mock_reads4.emplace_back(
21364 "HTTP/1.1 401 Unauthorized\r\n"
21365 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21366 "Connection: close\r\n"
21367 "Content-Length: 0\r\n\r\n");
21368 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
21369 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3021370 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
21371 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0421372
David Benjamin7ebab032019-04-30 21:51:3021373 // The client retries with credentials on a new connection, and the request
21374 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421375 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
21376 ssl_proxy5.expected_send_client_cert = true;
21377 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
21378 std::vector<MockWrite> mock_writes5;
21379 std::vector<MockRead> mock_reads5;
21380 mock_writes5.emplace_back(
21381 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21382 "Host: www.example.org:443\r\n"
21383 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021384 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421385 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21386 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21387 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
21388 ssl_origin5.expected_send_client_cert = true;
21389 ssl_origin5.expected_client_cert = identity_origin->certificate();
21390 mock_writes5.emplace_back(
21391 "GET / HTTP/1.1\r\n"
21392 "Host: www.example.org\r\n"
21393 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021394 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421395 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21396 mock_reads5.emplace_back(
21397 "HTTP/1.1 200 OK\r\n"
21398 "Connection: close\r\n"
21399 "Content-Length: 0\r\n\r\n");
21400 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
21401 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3021402 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
21403 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0421404
David Benjaminbac8dff2019-08-07 01:30:4121405 // The client makes a second request. This needs yet another connection, but
21406 // all credentials are cached.
21407 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
21408 ssl_proxy6.expected_send_client_cert = true;
21409 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
21410 std::vector<MockWrite> mock_writes6;
21411 std::vector<MockRead> mock_reads6;
21412 mock_writes6.emplace_back(
21413 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21414 "Host: www.example.org:443\r\n"
21415 "Proxy-Connection: keep-alive\r\n"
21416 // Authenticate as proxyuser:proxypass.
21417 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21418 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21419 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
21420 ssl_origin6.expected_send_client_cert = true;
21421 ssl_origin6.expected_client_cert = identity_origin->certificate();
21422 mock_writes6.emplace_back(
21423 "GET / HTTP/1.1\r\n"
21424 "Host: www.example.org\r\n"
21425 "Connection: keep-alive\r\n"
21426 // Authenticate as user:pass.
21427 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21428 mock_reads6.emplace_back(
21429 "HTTP/1.1 200 OK\r\n"
21430 "Connection: close\r\n"
21431 "Content-Length: 0\r\n\r\n");
21432 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
21433 session_deps_.socket_factory->AddSocketDataProvider(&data6);
21434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
21435 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
21436
David Benjamin2eb827f2019-04-29 18:31:0421437 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21438
21439 // Start the request.
21440 TestCompletionCallback callback;
21441 auto trans =
21442 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21443 int rv = callback.GetResult(
21444 trans->Start(&request, callback.callback(), NetLogWithSource()));
21445
21446 // Handle the proxy client certificate challenge.
21447 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21448 SSLCertRequestInfo* cert_request_info =
21449 trans->GetResponseInfo()->cert_request_info.get();
21450 ASSERT_TRUE(cert_request_info);
21451 EXPECT_TRUE(cert_request_info->is_proxy);
21452 EXPECT_EQ(cert_request_info->host_and_port,
21453 cert_request_info_proxy->host_and_port);
21454 rv = callback.GetResult(trans->RestartWithCertificate(
21455 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21456 callback.callback()));
21457
21458 // Handle the proxy HTTP auth challenge.
21459 ASSERT_THAT(rv, IsOk());
21460 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21461 EXPECT_TRUE(
21462 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21463 rv = callback.GetResult(trans->RestartWithAuth(
21464 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21465 callback.callback()));
21466
21467 // Handle the origin client certificate challenge.
21468 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21469 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21470 ASSERT_TRUE(cert_request_info);
21471 EXPECT_FALSE(cert_request_info->is_proxy);
21472 EXPECT_EQ(cert_request_info->host_and_port,
21473 cert_request_info_origin->host_and_port);
21474 rv = callback.GetResult(trans->RestartWithCertificate(
21475 identity_origin->certificate(), identity_origin->ssl_private_key(),
21476 callback.callback()));
21477
21478 // Handle the origin HTTP auth challenge.
21479 ASSERT_THAT(rv, IsOk());
21480 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21481 EXPECT_TRUE(
21482 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21483 rv = callback.GetResult(trans->RestartWithAuth(
21484 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21485 callback.callback()));
21486
21487 // The request completes.
21488 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021489 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121490
21491 // Make a second request. This time all credentials are cached.
21492 trans =
21493 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21494 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21495 NetLogWithSource())),
21496 IsOk());
21497 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3021498}
21499
21500// Test the proxy requesting HTTP auth and the server requesting TLS client
21501// certificates. This is a regression test for https://crbug.com/946406.
21502TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
21503 // Note these hosts must match the CheckBasic*Auth() functions.
21504 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21505 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21506
21507 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21508 cert_request_info_origin->host_and_port =
21509 HostPortPair("www.example.org", 443);
21510
21511 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21512 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21513 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21514 ASSERT_TRUE(identity_origin);
21515
21516 HttpRequestInfo request;
21517 request.method = "GET";
21518 request.url = GURL("https://www.example.org/");
21519 request.traffic_annotation =
21520 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21521
21522 // The client connects to the proxy. The handshake succeeds.
21523 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21524 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
21525 std::vector<MockWrite> mock_writes1;
21526 std::vector<MockRead> mock_reads1;
21527 mock_writes1.emplace_back(
21528 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21529 "Host: www.example.org:443\r\n"
21530 "Proxy-Connection: keep-alive\r\n\r\n");
21531 mock_reads1.emplace_back(
21532 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21533 "Content-Length: 0\r\n"
21534 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21535 // The client retries with credentials, and the request finally succeeds.
21536 mock_writes1.emplace_back(
21537 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21538 "Host: www.example.org:443\r\n"
21539 "Proxy-Connection: keep-alive\r\n"
21540 // Authenticate as proxyuser:proxypass.
21541 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21542 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21543 // The origin requests client certificates.
21544 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21545 ssl_origin1.cert_request_info = cert_request_info_origin.get();
21546 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
21547 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21548 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21549 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21550
21551 // The client responds to the origin client certificate request on a new
21552 // connection.
21553 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21554 std::vector<MockWrite> mock_writes2;
21555 std::vector<MockRead> mock_reads2;
21556 mock_writes2.emplace_back(
21557 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21558 "Host: www.example.org:443\r\n"
21559 "Proxy-Connection: keep-alive\r\n"
21560 // Authenticate as proxyuser:proxypass.
21561 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21562 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21563 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
21564 ssl_origin2.expected_send_client_cert = true;
21565 ssl_origin2.expected_client_cert = identity_origin->certificate();
21566 // The client sends the origin HTTP request, which succeeds.
21567 mock_writes2.emplace_back(
21568 "GET / HTTP/1.1\r\n"
21569 "Host: www.example.org\r\n"
21570 "Connection: keep-alive\r\n\r\n");
21571 mock_reads2.emplace_back(
21572 "HTTP/1.1 200 OK\r\n"
21573 "Content-Length: 0\r\n\r\n");
21574 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21575 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21576 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21577 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
21578
21579 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21580
21581 // Start the request.
21582 TestCompletionCallback callback;
21583 auto trans =
21584 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21585 int rv = callback.GetResult(
21586 trans->Start(&request, callback.callback(), NetLogWithSource()));
21587
21588 // Handle the proxy HTTP auth challenge.
21589 ASSERT_THAT(rv, IsOk());
21590 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21591 EXPECT_TRUE(
21592 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21593 rv = callback.GetResult(trans->RestartWithAuth(
21594 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21595 callback.callback()));
21596
21597 // Handle the origin client certificate challenge.
21598 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21599 SSLCertRequestInfo* cert_request_info =
21600 trans->GetResponseInfo()->cert_request_info.get();
21601 ASSERT_TRUE(cert_request_info);
21602 EXPECT_FALSE(cert_request_info->is_proxy);
21603 EXPECT_EQ(cert_request_info->host_and_port,
21604 cert_request_info_origin->host_and_port);
21605 rv = callback.GetResult(trans->RestartWithCertificate(
21606 identity_origin->certificate(), identity_origin->ssl_private_key(),
21607 callback.callback()));
21608
21609 // The request completes.
21610 ASSERT_THAT(rv, IsOk());
21611 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421612}
21613
David Benjamin6e673a82019-04-30 22:52:5821614// Test that socket reuse works with client certificates.
21615TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
21616 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
21617 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
21618
21619 std::unique_ptr<FakeClientCertIdentity> identity =
21620 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21621 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21622 ASSERT_TRUE(identity);
21623
21624 HttpRequestInfo request1;
21625 request1.method = "GET";
21626 request1.url = GURL("https://www.example.org/a");
21627 request1.traffic_annotation =
21628 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21629
21630 HttpRequestInfo request2;
21631 request2.method = "GET";
21632 request2.url = GURL("https://www.example.org/b");
21633 request2.traffic_annotation =
21634 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21635
21636 // The first connection results in a client certificate request.
21637 StaticSocketDataProvider data1;
21638 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21639 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21640 ssl1.cert_request_info = cert_request_info.get();
21641 ssl1.expected_send_client_cert = false;
21642 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21643
21644 // The second connection succeeds and is usable for both requests.
21645 MockWrite mock_writes[] = {
21646 MockWrite("GET /a HTTP/1.1\r\n"
21647 "Host: www.example.org\r\n"
21648 "Connection: keep-alive\r\n\r\n"),
21649 MockWrite("GET /b HTTP/1.1\r\n"
21650 "Host: www.example.org\r\n"
21651 "Connection: keep-alive\r\n\r\n"),
21652 };
21653 MockRead mock_reads[] = {
21654 MockRead("HTTP/1.1 200 OK\r\n"
21655 "Content-Length: 0\r\n\r\n"),
21656 MockRead("HTTP/1.1 200 OK\r\n"
21657 "Content-Length: 0\r\n\r\n"),
21658 };
21659 StaticSocketDataProvider data2(mock_reads, mock_writes);
21660 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21661 SSLSocketDataProvider ssl2(ASYNC, OK);
21662 ssl2.expected_send_client_cert = true;
21663 ssl2.expected_client_cert = identity->certificate();
21664 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21665
21666 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21667
21668 // Start the first request. It succeeds after providing client certificates.
21669 TestCompletionCallback callback;
21670 auto trans =
21671 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21672 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
21673 NetLogWithSource())),
21674 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21675
21676 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
21677 ASSERT_TRUE(info);
21678 EXPECT_FALSE(info->is_proxy);
21679 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
21680
21681 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
21682 identity->certificate(), identity->ssl_private_key(),
21683 callback.callback())),
21684 IsOk());
21685 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21686
21687 // Make the second request. It completes without requesting client
21688 // certificates.
21689 trans =
21690 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21691 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
21692 NetLogWithSource())),
21693 IsOk());
21694 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21695}
21696
Matt Menke166443c2019-05-24 18:45:5921697// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
21698// sequence with two different NetworkIsolationKeys, the first and last have the
21699// same key, the second a different one. Checks that the requests are
21700// partitioned across sockets as expected.
21701TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2721702 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21703 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21704 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21705 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5921706
21707 for (bool partition_connections : {false, true}) {
21708 SCOPED_TRACE(partition_connections);
21709
21710 base::test::ScopedFeatureList feature_list;
21711 if (partition_connections) {
21712 feature_list.InitAndEnableFeature(
21713 features::kPartitionConnectionsByNetworkIsolationKey);
21714 } else {
21715 feature_list.InitAndDisableFeature(
21716 features::kPartitionConnectionsByNetworkIsolationKey);
21717 }
21718
21719 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21720
21721 // Reads and writes for the unpartitioned case, where only one socket is
21722 // used.
21723
21724 const MockWrite kUnpartitionedWrites[] = {
21725 MockWrite("GET /1 HTTP/1.1\r\n"
21726 "Host: foo.test\r\n"
21727 "Connection: keep-alive\r\n\r\n"),
21728 MockWrite("GET /2 HTTP/1.1\r\n"
21729 "Host: foo.test\r\n"
21730 "Connection: keep-alive\r\n\r\n"),
21731 MockWrite("GET /3 HTTP/1.1\r\n"
21732 "Host: foo.test\r\n"
21733 "Connection: keep-alive\r\n\r\n"),
21734 };
21735
21736 const MockRead kUnpartitionedReads[] = {
21737 MockRead("HTTP/1.1 200 OK\r\n"
21738 "Connection: keep-alive\r\n"
21739 "Content-Length: 1\r\n\r\n"
21740 "1"),
21741 MockRead("HTTP/1.1 200 OK\r\n"
21742 "Connection: keep-alive\r\n"
21743 "Content-Length: 1\r\n\r\n"
21744 "2"),
21745 MockRead("HTTP/1.1 200 OK\r\n"
21746 "Connection: keep-alive\r\n"
21747 "Content-Length: 1\r\n\r\n"
21748 "3"),
21749 };
21750
21751 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
21752 kUnpartitionedWrites);
21753
21754 // Reads and writes for the partitioned case, where two sockets are used.
21755
21756 const MockWrite kPartitionedWrites1[] = {
21757 MockWrite("GET /1 HTTP/1.1\r\n"
21758 "Host: foo.test\r\n"
21759 "Connection: keep-alive\r\n\r\n"),
21760 MockWrite("GET /3 HTTP/1.1\r\n"
21761 "Host: foo.test\r\n"
21762 "Connection: keep-alive\r\n\r\n"),
21763 };
21764
21765 const MockRead kPartitionedReads1[] = {
21766 MockRead("HTTP/1.1 200 OK\r\n"
21767 "Connection: keep-alive\r\n"
21768 "Content-Length: 1\r\n\r\n"
21769 "1"),
21770 MockRead("HTTP/1.1 200 OK\r\n"
21771 "Connection: keep-alive\r\n"
21772 "Content-Length: 1\r\n\r\n"
21773 "3"),
21774 };
21775
21776 const MockWrite kPartitionedWrites2[] = {
21777 MockWrite("GET /2 HTTP/1.1\r\n"
21778 "Host: foo.test\r\n"
21779 "Connection: keep-alive\r\n\r\n"),
21780 };
21781
21782 const MockRead kPartitionedReads2[] = {
21783 MockRead("HTTP/1.1 200 OK\r\n"
21784 "Connection: keep-alive\r\n"
21785 "Content-Length: 1\r\n\r\n"
21786 "2"),
21787 };
21788
21789 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
21790 kPartitionedWrites1);
21791 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
21792 kPartitionedWrites2);
21793
21794 if (partition_connections) {
21795 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21796 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21797 } else {
21798 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
21799 }
21800
21801 TestCompletionCallback callback;
21802 HttpRequestInfo request1;
21803 request1.method = "GET";
21804 request1.url = GURL("http://foo.test/1");
21805 request1.traffic_annotation =
21806 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21807 request1.network_isolation_key = network_isolation_key1;
21808 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21809 session.get());
21810 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21811 EXPECT_THAT(callback.GetResult(rv), IsOk());
21812 std::string response_data1;
21813 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21814 EXPECT_EQ("1", response_data1);
21815 trans1.reset();
21816
21817 HttpRequestInfo request2;
21818 request2.method = "GET";
21819 request2.url = GURL("http://foo.test/2");
21820 request2.traffic_annotation =
21821 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21822 request2.network_isolation_key = network_isolation_key2;
21823 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21824 session.get());
21825 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21826 EXPECT_THAT(callback.GetResult(rv), IsOk());
21827 std::string response_data2;
21828 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21829 EXPECT_EQ("2", response_data2);
21830 trans2.reset();
21831
21832 HttpRequestInfo request3;
21833 request3.method = "GET";
21834 request3.url = GURL("http://foo.test/3");
21835 request3.traffic_annotation =
21836 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21837 request3.network_isolation_key = network_isolation_key1;
21838 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21839 session.get());
21840 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21841 EXPECT_THAT(callback.GetResult(rv), IsOk());
21842 std::string response_data3;
21843 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21844 EXPECT_EQ("3", response_data3);
21845 trans3.reset();
21846 }
21847}
21848
Matt Menkeae58eeb2019-05-24 21:09:5021849TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2721850 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21851 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21852 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21853 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5021854
21855 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
21856 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
21857 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
21858 // the same way as the HTTP over H2 proxy case.
21859 for (bool use_proxy : {false, true}) {
21860 SCOPED_TRACE(use_proxy);
21861 if (use_proxy) {
21862 session_deps_.proxy_resolution_service =
21863 ProxyResolutionService::CreateFixedFromPacResult(
21864 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
21865 } else {
21866 session_deps_.proxy_resolution_service =
21867 ProxyResolutionService::CreateDirect();
21868 }
21869 const char* url1 = nullptr;
21870 const char* url2 = nullptr;
21871 const char* url3 = nullptr;
21872 if (use_proxy) {
21873 url1 = "http://foo.test/1";
21874 url2 = "http://foo.test/2";
21875 url3 = "http://foo.test/3";
21876 } else {
21877 url1 = "https://foo.test/1";
21878 url2 = "https://foo.test/2";
21879 url3 = "https://foo.test/3";
21880 }
21881
21882 for (bool partition_connections : {false, true}) {
21883 SCOPED_TRACE(partition_connections);
21884
21885 base::test::ScopedFeatureList feature_list;
21886 if (partition_connections) {
21887 feature_list.InitAndEnableFeature(
21888 features::kPartitionConnectionsByNetworkIsolationKey);
21889 } else {
21890 feature_list.InitAndDisableFeature(
21891 features::kPartitionConnectionsByNetworkIsolationKey);
21892 }
21893
21894 std::unique_ptr<HttpNetworkSession> session(
21895 CreateSession(&session_deps_));
21896
21897 // Reads and writes for the unpartitioned case, where only one socket is
21898 // used.
21899
21900 SpdyTestUtil spdy_util;
21901 spdy::SpdySerializedFrame unpartitioned_req1(
21902 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
21903 spdy::SpdySerializedFrame unpartitioned_response1(
21904 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
21905 spdy::SpdySerializedFrame unpartitioned_body1(
21906 spdy_util.ConstructSpdyDataFrame(1, "1", true));
21907 spdy_util.UpdateWithStreamDestruction(1);
21908
21909 spdy::SpdySerializedFrame unpartitioned_req2(
21910 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
21911 spdy::SpdySerializedFrame unpartitioned_response2(
21912 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
21913 spdy::SpdySerializedFrame unpartitioned_body2(
21914 spdy_util.ConstructSpdyDataFrame(3, "2", true));
21915 spdy_util.UpdateWithStreamDestruction(3);
21916
21917 spdy::SpdySerializedFrame unpartitioned_req3(
21918 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
21919 spdy::SpdySerializedFrame unpartitioned_response3(
21920 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
21921 spdy::SpdySerializedFrame unpartitioned_body3(
21922 spdy_util.ConstructSpdyDataFrame(5, "3", true));
21923
21924 const MockWrite kUnpartitionedWrites[] = {
21925 CreateMockWrite(unpartitioned_req1, 0),
21926 CreateMockWrite(unpartitioned_req2, 3),
21927 CreateMockWrite(unpartitioned_req3, 6),
21928 };
21929
21930 const MockRead kUnpartitionedReads[] = {
21931 CreateMockRead(unpartitioned_response1, 1),
21932 CreateMockRead(unpartitioned_body1, 2),
21933 CreateMockRead(unpartitioned_response2, 4),
21934 CreateMockRead(unpartitioned_body2, 5),
21935 CreateMockRead(unpartitioned_response3, 7),
21936 CreateMockRead(unpartitioned_body3, 8),
21937 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
21938 };
21939
21940 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
21941 kUnpartitionedWrites);
21942
21943 // Reads and writes for the partitioned case, where two sockets are used.
21944
21945 SpdyTestUtil spdy_util2;
21946 spdy::SpdySerializedFrame partitioned_req1(
21947 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
21948 spdy::SpdySerializedFrame partitioned_response1(
21949 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
21950 spdy::SpdySerializedFrame partitioned_body1(
21951 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
21952 spdy_util2.UpdateWithStreamDestruction(1);
21953
21954 spdy::SpdySerializedFrame partitioned_req3(
21955 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
21956 spdy::SpdySerializedFrame partitioned_response3(
21957 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
21958 spdy::SpdySerializedFrame partitioned_body3(
21959 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
21960
21961 const MockWrite kPartitionedWrites1[] = {
21962 CreateMockWrite(partitioned_req1, 0),
21963 CreateMockWrite(partitioned_req3, 3),
21964 };
21965
21966 const MockRead kPartitionedReads1[] = {
21967 CreateMockRead(partitioned_response1, 1),
21968 CreateMockRead(partitioned_body1, 2),
21969 CreateMockRead(partitioned_response3, 4),
21970 CreateMockRead(partitioned_body3, 5),
21971 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
21972 };
21973
21974 SpdyTestUtil spdy_util3;
21975 spdy::SpdySerializedFrame partitioned_req2(
21976 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
21977 spdy::SpdySerializedFrame partitioned_response2(
21978 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
21979 spdy::SpdySerializedFrame partitioned_body2(
21980 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
21981
21982 const MockWrite kPartitionedWrites2[] = {
21983 CreateMockWrite(partitioned_req2, 0),
21984 };
21985
21986 const MockRead kPartitionedReads2[] = {
21987 CreateMockRead(partitioned_response2, 1),
21988 CreateMockRead(partitioned_body2, 2),
21989 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
21990 };
21991
21992 SequencedSocketData partitioned_data1(kPartitionedReads1,
21993 kPartitionedWrites1);
21994 SequencedSocketData partitioned_data2(kPartitionedReads2,
21995 kPartitionedWrites2);
21996
21997 // No need to segment SSLDataProviders by whether or not partitioning is
21998 // enabled.
21999 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22000 ssl_data1.next_proto = kProtoHTTP2;
22001 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22002 ssl_data2.next_proto = kProtoHTTP2;
22003
22004 if (partition_connections) {
22005 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22006 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22007 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22008 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22009 } else {
22010 session_deps_.socket_factory->AddSocketDataProvider(
22011 &unpartitioned_data);
22012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22013 }
22014
22015 TestCompletionCallback callback;
22016 HttpRequestInfo request1;
22017 request1.method = "GET";
22018 request1.url = GURL(url1);
22019 request1.traffic_annotation =
22020 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22021 request1.network_isolation_key = network_isolation_key1;
22022 auto trans1 =
22023 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22024 int rv =
22025 trans1->Start(&request1, callback.callback(), NetLogWithSource());
22026 EXPECT_THAT(callback.GetResult(rv), IsOk());
22027 std::string response_data1;
22028 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22029 EXPECT_EQ("1", response_data1);
22030 trans1.reset();
22031
22032 HttpRequestInfo request2;
22033 request2.method = "GET";
22034 request2.url = GURL(url2);
22035 request2.traffic_annotation =
22036 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22037 request2.network_isolation_key = network_isolation_key2;
22038 auto trans2 =
22039 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22040 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22041 EXPECT_THAT(callback.GetResult(rv), IsOk());
22042 std::string response_data2;
22043 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22044 EXPECT_EQ("2", response_data2);
22045 trans2.reset();
22046
22047 HttpRequestInfo request3;
22048 request3.method = "GET";
22049 request3.url = GURL(url3);
22050 request3.traffic_annotation =
22051 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22052 request3.network_isolation_key = network_isolation_key1;
22053 auto trans3 =
22054 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22055 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22056 EXPECT_THAT(callback.GetResult(rv), IsOk());
22057 std::string response_data3;
22058 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22059 EXPECT_EQ("3", response_data3);
22060 trans3.reset();
22061 }
22062 }
22063}
22064
Matt Menke7281f872019-06-25 19:29:2522065// Preconnect two sockets with different NetworkIsolationKeys when
22066// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
22067// request and make sure the correct socket is used. Loops three times,
22068// expecting to use the first preconnect, second preconnect, and neither.
22069TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
22070 base::test::ScopedFeatureList feature_list;
22071 feature_list.InitAndEnableFeature(
22072 features::kPartitionConnectionsByNetworkIsolationKey);
22073
22074 enum class TestCase {
22075 kUseFirstPreconnect,
22076 kUseSecondPreconnect,
22077 kDontUsePreconnect,
22078 };
22079
Shivani Sharma8ae506c2019-07-21 21:08:2722080 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22081 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22082 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
22083 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
22084 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
22085 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2522086
22087 // Test that only preconnects with
22088 for (TestCase test_case :
22089 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
22090 TestCase::kDontUsePreconnect}) {
22091 SpdySessionDependencies session_deps;
22092 // Make DNS lookups completely synchronously, so preconnects complete
22093 // immediately.
22094 session_deps.host_resolver->set_synchronous_mode(true);
22095
22096 const MockWrite kMockWrites[] = {
22097 MockWrite(ASYNC, 0,
22098 "GET / HTTP/1.1\r\n"
22099 "Host: www.foo.com\r\n"
22100 "Connection: keep-alive\r\n\r\n"),
22101 };
22102
22103 const MockRead kMockReads[] = {
22104 MockRead(ASYNC, 1,
22105 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
22106 "hello"),
22107 };
22108
22109 // Used for the socket that will actually be used, which may or may not be
22110 // one of the preconnects
22111 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
22112 kMockReads, kMockWrites);
22113
22114 // Used for the preconnects that won't actually be used.
22115 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
22116 base::span<const MockRead>(),
22117 base::span<const MockWrite>());
22118 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
22119 base::span<const MockRead>(),
22120 base::span<const MockWrite>());
22121
22122 NetworkIsolationKey network_isolation_key_for_request;
22123
22124 switch (test_case) {
22125 case TestCase::kUseFirstPreconnect:
22126 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22127 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22128 network_isolation_key_for_request = preconnect1_isolation_key;
22129 break;
22130 case TestCase::kUseSecondPreconnect:
22131 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22132 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22133 network_isolation_key_for_request = preconnect2_isolation_key;
22134 break;
22135 case TestCase::kDontUsePreconnect:
22136 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22137 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22138 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22139 network_isolation_key_for_request = not_preconnected_isolation_key;
22140 break;
22141 }
22142
22143 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
22144
22145 // Preconnect sockets.
22146 HttpRequestInfo request;
22147 request.method = "GET";
22148 request.url = GURL("http://www.foo.com/");
22149 request.traffic_annotation =
22150 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22151
22152 request.network_isolation_key = preconnect1_isolation_key;
22153 session->http_stream_factory()->PreconnectStreams(1, request);
22154
22155 request.network_isolation_key = preconnect2_isolation_key;
22156 session->http_stream_factory()->PreconnectStreams(1, request);
22157
22158 request.network_isolation_key = network_isolation_key_for_request;
22159
22160 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22161
22162 // Make the request.
22163 TestCompletionCallback callback;
22164
22165 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22166
22167 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22168 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22169
22170 rv = callback.WaitForResult();
22171 EXPECT_THAT(rv, IsOk());
22172
22173 const HttpResponseInfo* response = trans.GetResponseInfo();
22174 ASSERT_TRUE(response);
22175 ASSERT_TRUE(response->headers);
22176 EXPECT_EQ(200, response->headers->response_code());
22177
22178 std::string response_data;
22179 rv = ReadTransaction(&trans, &response_data);
22180 EXPECT_THAT(rv, IsOk());
22181 EXPECT_EQ("hello", response_data);
22182
22183 if (test_case != TestCase::kDontUsePreconnect) {
22184 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22185 } else {
22186 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
22187 }
22188 }
22189}
22190
David Benjamin6f2da652019-06-26 23:36:3522191// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22192// cache is isolated.
22193TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
22194 base::test::ScopedFeatureList feature_list;
22195 feature_list.InitWithFeatures(
22196 {features::kPartitionConnectionsByNetworkIsolationKey,
22197 features::kPartitionSSLSessionsByNetworkIsolationKey},
22198 {});
22199
Shivani Sharma8ae506c2019-07-21 21:08:2722200 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22201 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22202 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22203 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522204 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22205
22206 // The server always sends Connection: close, so each request goes over a
22207 // distinct socket.
22208
22209 const MockWrite kWrites1[] = {
22210 MockWrite("GET /1 HTTP/1.1\r\n"
22211 "Host: foo.test\r\n"
22212 "Connection: keep-alive\r\n\r\n")};
22213
22214 const MockRead kReads1[] = {
22215 MockRead("HTTP/1.1 200 OK\r\n"
22216 "Connection: close\r\n"
22217 "Content-Length: 1\r\n\r\n"
22218 "1")};
22219
22220 const MockWrite kWrites2[] = {
22221 MockWrite("GET /2 HTTP/1.1\r\n"
22222 "Host: foo.test\r\n"
22223 "Connection: keep-alive\r\n\r\n")};
22224
22225 const MockRead kReads2[] = {
22226 MockRead("HTTP/1.1 200 OK\r\n"
22227 "Connection: close\r\n"
22228 "Content-Length: 1\r\n\r\n"
22229 "2")};
22230
22231 const MockWrite kWrites3[] = {
22232 MockWrite("GET /3 HTTP/1.1\r\n"
22233 "Host: foo.test\r\n"
22234 "Connection: keep-alive\r\n\r\n")};
22235
22236 const MockRead kReads3[] = {
22237 MockRead("HTTP/1.1 200 OK\r\n"
22238 "Connection: close\r\n"
22239 "Content-Length: 1\r\n\r\n"
22240 "3")};
22241
22242 StaticSocketDataProvider data1(kReads1, kWrites1);
22243 StaticSocketDataProvider data2(kReads2, kWrites2);
22244 StaticSocketDataProvider data3(kReads3, kWrites3);
22245 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22246 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22247 session_deps_.socket_factory->AddSocketDataProvider(&data3);
22248
22249 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22250 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
22251 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
22252 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22253 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
22254 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
22255 SSLSocketDataProvider ssl_data3(ASYNC, OK);
22256 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
22257 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
22258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22259 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22260 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
22261
22262 TestCompletionCallback callback;
22263 HttpRequestInfo request1;
22264 request1.method = "GET";
22265 request1.url = GURL("https://foo.test/1");
22266 request1.traffic_annotation =
22267 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22268 request1.network_isolation_key = kNetworkIsolationKey1;
22269 auto trans1 =
22270 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22271 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22272 EXPECT_THAT(callback.GetResult(rv), IsOk());
22273 std::string response_data1;
22274 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22275 EXPECT_EQ("1", response_data1);
22276 trans1.reset();
22277
22278 HttpRequestInfo request2;
22279 request2.method = "GET";
22280 request2.url = GURL("https://foo.test/2");
22281 request2.traffic_annotation =
22282 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22283 request2.network_isolation_key = kNetworkIsolationKey2;
22284 auto trans2 =
22285 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22286 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22287 EXPECT_THAT(callback.GetResult(rv), IsOk());
22288 std::string response_data2;
22289 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22290 EXPECT_EQ("2", response_data2);
22291 trans2.reset();
22292
22293 HttpRequestInfo request3;
22294 request3.method = "GET";
22295 request3.url = GURL("https://foo.test/3");
22296 request3.traffic_annotation =
22297 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22298 request3.network_isolation_key = kNetworkIsolationKey1;
22299 auto trans3 =
22300 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22301 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22302 EXPECT_THAT(callback.GetResult(rv), IsOk());
22303 std::string response_data3;
22304 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22305 EXPECT_EQ("3", response_data3);
22306 trans3.reset();
22307}
22308
22309// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22310// cache is isolated, for both origins and proxies.
22311TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
22312 base::test::ScopedFeatureList feature_list;
22313 feature_list.InitWithFeatures(
22314 {features::kPartitionConnectionsByNetworkIsolationKey,
22315 features::kPartitionSSLSessionsByNetworkIsolationKey},
22316 {});
22317
22318 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
22319 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
22320
Shivani Sharma8ae506c2019-07-21 21:08:2722321 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22322 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22323 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22324 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522325 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22326
22327 // Make both a tunneled and non-tunneled request.
22328 HttpRequestInfo request1;
22329 request1.method = "GET";
22330 request1.url = GURL("https://foo.test/1");
22331 request1.traffic_annotation =
22332 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22333 request1.network_isolation_key = kNetworkIsolationKey1;
22334
22335 HttpRequestInfo request2;
22336 request2.method = "GET";
22337 request2.url = GURL("http://foo.test/2");
22338 request2.traffic_annotation =
22339 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22340 request2.network_isolation_key = kNetworkIsolationKey2;
22341
22342 const MockWrite kWrites1[] = {
22343 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
22344 "Host: foo.test:443\r\n"
22345 "Proxy-Connection: keep-alive\r\n\r\n"),
22346 MockWrite("GET /1 HTTP/1.1\r\n"
22347 "Host: foo.test\r\n"
22348 "Connection: keep-alive\r\n\r\n")};
22349
22350 const MockRead kReads1[] = {
22351 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
22352 MockRead("HTTP/1.1 200 OK\r\n"
22353 "Connection: close\r\n"
22354 "Content-Length: 1\r\n\r\n"
22355 "1")};
22356
22357 const MockWrite kWrites2[] = {
22358 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
22359 "Host: foo.test\r\n"
22360 "Proxy-Connection: keep-alive\r\n\r\n")};
22361
22362 const MockRead kReads2[] = {
22363 MockRead("HTTP/1.1 200 OK\r\n"
22364 "Connection: close\r\n"
22365 "Content-Length: 1\r\n\r\n"
22366 "2")};
22367
22368 StaticSocketDataProvider data1(kReads1, kWrites1);
22369 StaticSocketDataProvider data2(kReads2, kWrites2);
22370 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22371 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22372 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22373
22374 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
22375 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
22376 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
22377 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
22378 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
22379 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
22380 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22381 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
22382 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
22383 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22384 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22385 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22386
22387 TestCompletionCallback callback;
22388 auto trans1 =
22389 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22390 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22391 EXPECT_THAT(callback.GetResult(rv), IsOk());
22392 std::string response_data1;
22393 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22394 EXPECT_EQ("1", response_data1);
22395 trans1.reset();
22396
22397 auto trans2 =
22398 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22399 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22400 EXPECT_THAT(callback.GetResult(rv), IsOk());
22401 std::string response_data2;
22402 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22403 EXPECT_EQ("2", response_data2);
22404 trans2.reset();
22405}
22406
David Benjaminef2f2a5a2019-07-16 19:21:3122407// Test that SSLConfig changes from SSLConfigService are picked up even when
22408// there are live sockets.
22409TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5222410 SSLContextConfig ssl_context_config;
22411 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22412 auto ssl_config_service =
22413 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122414 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22415
22416 session_deps_.ssl_config_service = std::move(ssl_config_service);
22417
22418 // Make three requests. Between the second and third, the SSL config will
22419 // change.
22420 HttpRequestInfo request1;
22421 request1.method = "GET";
22422 request1.url = GURL("https://foo.test/1");
22423 request1.traffic_annotation =
22424 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22425
22426 HttpRequestInfo request2;
22427 request2.method = "GET";
22428 request2.url = GURL("https://foo.test/2");
22429 request2.traffic_annotation =
22430 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22431
22432 HttpRequestInfo request3;
22433 request3.method = "GET";
22434 request3.url = GURL("https://foo.test/3");
22435 request3.traffic_annotation =
22436 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22437
22438 const MockWrite kWrites1[] = {
22439 MockWrite("GET /1 HTTP/1.1\r\n"
22440 "Host: foo.test\r\n"
22441 "Connection: keep-alive\r\n\r\n"),
22442 MockWrite("GET /2 HTTP/1.1\r\n"
22443 "Host: foo.test\r\n"
22444 "Connection: keep-alive\r\n\r\n"),
22445 };
22446
22447 const MockRead kReads1[] = {
22448 MockRead("HTTP/1.1 200 OK\r\n"
22449 "Connection: keep-alive\r\n"
22450 "Content-Length: 1\r\n\r\n"
22451 "1"),
22452 MockRead("HTTP/1.1 200 OK\r\n"
22453 "Connection: keep-alive\r\n"
22454 "Content-Length: 1\r\n\r\n"
22455 "2"),
22456 };
22457
22458 // The third request goes on a different socket because the SSL config has
22459 // changed.
22460 const MockWrite kWrites2[] = {
22461 MockWrite("GET /3 HTTP/1.1\r\n"
22462 "Host: foo.test\r\n"
22463 "Connection: keep-alive\r\n\r\n")};
22464
22465 const MockRead kReads2[] = {
22466 MockRead("HTTP/1.1 200 OK\r\n"
22467 "Connection: keep-alive\r\n"
22468 "Content-Length: 1\r\n\r\n"
22469 "3")};
22470
22471 StaticSocketDataProvider data1(kReads1, kWrites1);
22472 StaticSocketDataProvider data2(kReads2, kWrites2);
22473 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22474 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22475
22476 SSLSocketDataProvider ssl1(ASYNC, OK);
22477 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22478 SSLSocketDataProvider ssl2(ASYNC, OK);
22479 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22480 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22481 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22482
22483 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22484
22485 TestCompletionCallback callback;
22486 auto trans1 =
22487 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22488 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22489 EXPECT_THAT(callback.GetResult(rv), IsOk());
22490 std::string response_data1;
22491 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22492 EXPECT_EQ("1", response_data1);
22493 trans1.reset();
22494
22495 auto trans2 =
22496 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22497 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22498 EXPECT_THAT(callback.GetResult(rv), IsOk());
22499 std::string response_data2;
22500 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22501 EXPECT_EQ("2", response_data2);
22502 trans2.reset();
22503
David Benjamin151ec6b2019-08-02 19:38:5222504 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22505 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122506
22507 auto trans3 =
22508 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22509 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22510 EXPECT_THAT(callback.GetResult(rv), IsOk());
22511 std::string response_data3;
22512 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22513 EXPECT_EQ("3", response_data3);
22514 trans3.reset();
22515}
22516
22517TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5222518 SSLContextConfig ssl_context_config;
22519 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22520 auto ssl_config_service =
22521 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122522 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22523
22524 session_deps_.ssl_config_service = std::move(ssl_config_service);
22525
22526 HttpRequestInfo request;
22527 request.method = "GET";
22528 request.url = GURL("https://foo.test/1");
22529 request.traffic_annotation =
22530 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22531
22532 // Make a socket which never connects.
22533 StaticSocketDataProvider data({}, {});
22534 session_deps_.socket_factory->AddSocketDataProvider(&data);
22535 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
22536 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22537 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
22538
22539 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22540
22541 TestCompletionCallback callback;
22542 auto trans =
22543 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22544 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
22545 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22546
David Benjamin151ec6b2019-08-02 19:38:5222547 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22548 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122549
22550 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
22551}
22552
David Benjaminbac8dff2019-08-07 01:30:4122553// Test that HttpNetworkTransaction correctly handles existing sockets when the
22554// server requests a client certificate post-handshake (via a TLS
22555// renegotiation). This is a regression test for https://crbug.com/829184.
22556TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
22557 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
22558 TRAFFIC_ANNOTATION_FOR_TESTS);
22559
22560 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
22561 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
22562
22563 std::unique_ptr<FakeClientCertIdentity> identity =
22564 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22565 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
22566 ASSERT_TRUE(identity);
22567
22568 // This test will make several requests so that, when the client certificate
22569 // request comes in, we have a socket in use, an idle socket, and a socket for
22570 // an unrelated host.
22571 //
22572 // First, two long-lived requests which do not complete until after the client
22573 // certificate request. This arranges for sockets to be in use during the
22574 // request. They should not be interrupted.
22575 HttpRequestInfo request_long_lived;
22576 request_long_lived.method = "GET";
22577 request_long_lived.url = GURL("https://foo.test/long-lived");
22578 request_long_lived.traffic_annotation = kTrafficAnnotation;
22579
22580 HttpRequestInfo request_long_lived_bar;
22581 request_long_lived_bar.method = "GET";
22582 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
22583 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
22584
22585 // Next, make a request that needs client certificates.
22586 HttpRequestInfo request_auth;
22587 request_auth.method = "GET";
22588 request_auth.url = GURL("https://foo.test/auth");
22589 request_auth.traffic_annotation = kTrafficAnnotation;
22590
22591 // Before responding to the challenge, make a request to an unauthenticated
22592 // endpoint. This will result in an idle socket when the client certificate
22593 // challenge is resolved.
22594 HttpRequestInfo request_unauth;
22595 request_unauth.method = "GET";
22596 request_unauth.url = GURL("https://foo.test/unauth");
22597 request_unauth.traffic_annotation = kTrafficAnnotation;
22598
22599 // After all the preceding requests complete, end with two additional requests
22600 // to ensure pre-authentication foo.test sockets are not used and bar.test
22601 // sockets are unaffected.
22602 HttpRequestInfo request_post_auth;
22603 request_post_auth.method = "GET";
22604 request_post_auth.url = GURL("https://foo.test/post-auth");
22605 request_post_auth.traffic_annotation = kTrafficAnnotation;
22606
22607 HttpRequestInfo request_post_auth_bar;
22608 request_post_auth_bar.method = "GET";
22609 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
22610 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
22611
22612 // The sockets for /long-lived and /unauth complete their request but are
22613 // not allocated for /post-auth or /retry because SSL state has since changed.
22614 const MockWrite kLongLivedWrites[] = {
22615 MockWrite(ASYNC, 0,
22616 "GET /long-lived HTTP/1.1\r\n"
22617 "Host: foo.test\r\n"
22618 "Connection: keep-alive\r\n\r\n"),
22619 };
22620 const MockRead kLongLivedReads[] = {
22621 // Pause so /long-lived completes after the client presents client
22622 // certificates.
22623 MockRead(ASYNC, ERR_IO_PENDING, 1),
22624 MockRead(ASYNC, 2,
22625 "HTTP/1.1 200 OK\r\n"
22626 "Connection: keep-alive\r\n"
22627 "Content-Length: 10\r\n\r\n"
22628 "long-lived"),
22629 };
22630 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
22631 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
22632 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
22633 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
22634
22635 // Requests for bar.test should be unaffected by foo.test and get allocated
22636 // a single socket.
22637 const MockWrite kBarWrites[] = {
22638 MockWrite(ASYNC, 0,
22639 "GET /long-lived HTTP/1.1\r\n"
22640 "Host: bar.test\r\n"
22641 "Connection: keep-alive\r\n\r\n"),
22642 MockWrite(ASYNC, 3,
22643 "GET /post-auth HTTP/1.1\r\n"
22644 "Host: bar.test\r\n"
22645 "Connection: keep-alive\r\n\r\n"),
22646 };
22647 const MockRead kBarReads[] = {
22648 // Pause on /long-lived so it completes after foo.test's authentication.
22649 MockRead(ASYNC, ERR_IO_PENDING, 1),
22650 MockRead(ASYNC, 2,
22651 "HTTP/1.1 200 OK\r\n"
22652 "Connection: keep-alive\r\n"
22653 "Content-Length: 10\r\n\r\n"
22654 "long-lived"),
22655 MockRead(ASYNC, 4,
22656 "HTTP/1.1 200 OK\r\n"
22657 "Connection: keep-alive\r\n"
22658 "Content-Length: 9\r\n\r\n"
22659 "post-auth"),
22660 };
22661 SequencedSocketData data_bar(kBarReads, kBarWrites);
22662 SSLSocketDataProvider ssl_bar(ASYNC, OK);
22663 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
22664 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
22665
22666 // Requesting /auth results in a post-handshake client certificate challenge.
22667 const MockWrite kAuthWrites[] = {
22668 MockWrite(ASYNC, 0,
22669 "GET /auth HTTP/1.1\r\n"
22670 "Host: foo.test\r\n"
22671 "Connection: keep-alive\r\n\r\n"),
22672 };
22673 const MockRead kAuthReads[] = {
22674 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
22675 };
22676 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
22677 SSLSocketDataProvider ssl_auth(ASYNC, OK);
22678 ssl_auth.cert_request_info = cert_request_info.get();
22679 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
22680 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
22681
22682 // Requesting /unauth completes.
22683 const MockWrite kUnauthWrites[] = {
22684 MockWrite(ASYNC, 0,
22685 "GET /unauth HTTP/1.1\r\n"
22686 "Host: foo.test\r\n"
22687 "Connection: keep-alive\r\n\r\n"),
22688 };
22689 const MockRead kUnauthReads[] = {
22690 MockRead(ASYNC, 1,
22691 "HTTP/1.1 200 OK\r\n"
22692 "Connection: keep-alive\r\n"
22693 "Content-Length: 6\r\n\r\n"
22694 "unauth"),
22695 };
22696 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
22697 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
22698 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
22699 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
22700
22701 // When the client certificate is selected, /auth is retried on a new
22702 // connection. In particular, it should not be retried on |data_unauth|,
22703 // which would not honor the new client certificate configuration.
22704 const MockWrite kRetryWrites[] = {
22705 MockWrite(ASYNC, 0,
22706 "GET /auth HTTP/1.1\r\n"
22707 "Host: foo.test\r\n"
22708 "Connection: keep-alive\r\n\r\n"),
22709 };
22710 const MockRead kRetryReads[] = {
22711 MockRead(ASYNC, 1,
22712 "HTTP/1.1 200 OK\r\n"
22713 // Close the connection so we test that /post-auth is not
22714 // allocated to |data_unauth| or |data_long_lived|.
22715 "Connection: close\r\n"
22716 "Content-Length: 4\r\n\r\n"
22717 "auth"),
22718 };
22719 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
22720 SSLSocketDataProvider ssl_retry(ASYNC, OK);
22721 ssl_retry.expected_send_client_cert = true;
22722 ssl_retry.expected_client_cert = identity->certificate();
22723 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
22724 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
22725
22726 // /post-auth gets its own socket.
22727 const MockWrite kPostAuthWrites[] = {
22728 MockWrite(ASYNC, 0,
22729 "GET /post-auth HTTP/1.1\r\n"
22730 "Host: foo.test\r\n"
22731 "Connection: keep-alive\r\n\r\n"),
22732 };
22733 const MockRead kPostAuthReads[] = {
22734 MockRead(ASYNC, 1,
22735 "HTTP/1.1 200 OK\r\n"
22736 "Connection: keep-alive\r\n"
22737 "Content-Length: 9\r\n\r\n"
22738 "post-auth"),
22739 };
22740 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
22741 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
22742 ssl_post_auth.expected_send_client_cert = true;
22743 ssl_post_auth.expected_client_cert = identity->certificate();
22744 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
22745 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
22746
22747 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22748
22749 // Start the two long-lived requests.
22750 TestCompletionCallback callback_long_lived;
22751 auto trans_long_lived =
22752 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22753 int rv = trans_long_lived->Start(
22754 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
22755 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22756 data_long_lived.RunUntilPaused();
22757
22758 TestCompletionCallback callback_long_lived_bar;
22759 auto trans_long_lived_bar =
22760 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22761 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
22762 callback_long_lived_bar.callback(),
22763 NetLogWithSource());
22764 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22765 data_bar.RunUntilPaused();
22766
22767 // Request /auth. This gives a client certificate challenge.
22768 TestCompletionCallback callback_auth;
22769 auto trans_auth =
22770 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22771 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
22772 NetLogWithSource());
22773 EXPECT_THAT(callback_auth.GetResult(rv),
22774 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22775
22776 // Make an unauthenticated request. This completes.
22777 TestCompletionCallback callback_unauth;
22778 auto trans_unauth =
22779 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22780 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
22781 NetLogWithSource());
22782 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
22783 std::string response_unauth;
22784 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
22785 EXPECT_EQ("unauth", response_unauth);
22786 trans_unauth.reset();
22787
22788 // Complete the authenticated request.
22789 rv = trans_auth->RestartWithCertificate(identity->certificate(),
22790 identity->ssl_private_key(),
22791 callback_auth.callback());
22792 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
22793 std::string response_auth;
22794 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
22795 EXPECT_EQ("auth", response_auth);
22796 trans_auth.reset();
22797
22798 // Complete the long-lived requests.
22799 data_long_lived.Resume();
22800 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
22801 std::string response_long_lived;
22802 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
22803 IsOk());
22804 EXPECT_EQ("long-lived", response_long_lived);
22805 trans_long_lived.reset();
22806
22807 data_bar.Resume();
22808 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
22809 std::string response_long_lived_bar;
22810 EXPECT_THAT(
22811 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
22812 IsOk());
22813 EXPECT_EQ("long-lived", response_long_lived_bar);
22814 trans_long_lived_bar.reset();
22815
22816 // Run the post-authentication requests.
22817 TestCompletionCallback callback_post_auth;
22818 auto trans_post_auth =
22819 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22820 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
22821 NetLogWithSource());
22822 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
22823 std::string response_post_auth;
22824 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
22825 IsOk());
22826 EXPECT_EQ("post-auth", response_post_auth);
22827 trans_post_auth.reset();
22828
22829 TestCompletionCallback callback_post_auth_bar;
22830 auto trans_post_auth_bar =
22831 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22832 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
22833 callback_post_auth_bar.callback(),
22834 NetLogWithSource());
22835 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
22836 std::string response_post_auth_bar;
22837 EXPECT_THAT(
22838 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
22839 IsOk());
22840 EXPECT_EQ("post-auth", response_post_auth_bar);
22841 trans_post_auth_bar.reset();
22842}
22843
[email protected]89ceba9a2009-03-21 03:46:0622844} // namespace net