blob: 5fcb4c03c5d3f662d993cfa0191357ce03c9c6c9 [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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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 Halavatib5e433e2018-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
3341 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583342 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013343
3344 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3345 TestLoadTimingNotReusedWithPac(load_timing_info,
3346 CONNECT_TIMING_HAS_SSL_TIMES);
3347
3348 trans.reset();
3349 session->CloseAllConnections();
3350}
3351
3352// Test the request-challenge-retry sequence for basic auth, over a connection
3353// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013354TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593355 HttpRequestInfo request;
3356 request.method = "GET";
bncce36dca22015-04-21 22:11:233357 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593358 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293359 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103360 request.traffic_annotation =
3361 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593362
[email protected]cb9bf6ca2011-01-28 13:15:273363 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593364 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493365 ProxyResolutionService::CreateFixedFromPacResult(
3366 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513367 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073368 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093369 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273370
[email protected]394816e92010-08-03 07:38:593371 // Since we have proxy, should try to establish tunnel.
3372 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543373 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173374 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543375 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113376 };
3377
mmenkee71e15332015-10-07 16:39:543378 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083379 // connection.
3380 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543381 // No credentials.
3382 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3383 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3384 MockRead("Proxy-Connection: close\r\n\r\n"),
3385 };
mmenkee0b5c882015-08-26 20:29:113386
mmenkee71e15332015-10-07 16:39:543387 MockWrite data_writes2[] = {
3388 // After calling trans->RestartWithAuth(), this is the request we should
3389 // be issuing -- the final header line contains the credentials.
3390 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173391 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543392 "Proxy-Connection: keep-alive\r\n"
3393 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083394
mmenkee71e15332015-10-07 16:39:543395 MockWrite("GET / HTTP/1.1\r\n"
3396 "Host: www.example.org\r\n"
3397 "Connection: keep-alive\r\n\r\n"),
3398 };
3399
3400 MockRead data_reads2[] = {
3401 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3402
3403 MockRead("HTTP/1.1 200 OK\r\n"),
3404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3405 MockRead("Content-Length: 5\r\n\r\n"),
3406 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593407 };
3408
Ryan Sleevib8d7ea02018-05-07 20:01:013409 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073410 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013411 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543412 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063413 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073414 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593415
[email protected]49639fa2011-12-20 23:22:413416 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593417
bnc87dcefc2017-05-25 12:47:583418 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193419 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503420
[email protected]49639fa2011-12-20 23:22:413421 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013422 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593423
3424 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013425 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543426 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593427 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003428 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3429 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593430 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403431 entries, pos,
mikecirone8b85c432016-09-08 19:11:003432 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3433 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593434
3435 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523436 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013437 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523438 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593439 EXPECT_EQ(407, response->headers->response_code());
3440 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583441 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593442
[email protected]029c83b62013-01-24 05:28:203443 LoadTimingInfo load_timing_info;
3444 // CONNECT requests and responses are handled at the connect job level, so
3445 // the transaction does not yet have a connection.
3446 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3447
[email protected]49639fa2011-12-20 23:22:413448 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593449
[email protected]49639fa2011-12-20 23:22:413450 rv = trans->RestartWithAuth(
3451 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013452 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593453
3454 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013455 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593456
3457 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523458 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593459
3460 EXPECT_TRUE(response->headers->IsKeepAlive());
3461 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503462 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593463 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3464
3465 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583466 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503467
[email protected]029c83b62013-01-24 05:28:203468 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3469 TestLoadTimingNotReusedWithPac(load_timing_info,
3470 CONNECT_TIMING_HAS_SSL_TIMES);
3471
[email protected]0b0bf032010-09-21 18:08:503472 trans.reset();
[email protected]102e27c2011-02-23 01:01:313473 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:593474}
3475
[email protected]11203f012009-11-12 23:02:313476// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013477// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013478TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233479 // On the second pass, the body read of the auth challenge is synchronous, so
3480 // IsConnectedAndIdle returns false. The socket should still be drained and
3481 // reused. See http://crbug.com/544255.
3482 for (int i = 0; i < 2; ++i) {
3483 HttpRequestInfo request;
3484 request.method = "GET";
3485 request.url = GURL("https://www.example.org/");
3486 // Ensure that proxy authentication is attempted even
3487 // when the no authentication data flag is set.
3488 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103489 request.traffic_annotation =
3490 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013491
mmenked39192ee2015-12-09 00:57:233492 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593493 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493494 ProxyResolutionService::CreateFixed("myproxy:70",
3495 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233496 BoundTestNetLog log;
3497 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093498 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013499
bnc691fda62016-08-12 00:43:163500 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013501
mmenked39192ee2015-12-09 00:57:233502 // Since we have proxy, should try to establish tunnel.
3503 MockWrite data_writes1[] = {
3504 MockWrite(ASYNC, 0,
3505 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3506 "Host: www.example.org:443\r\n"
3507 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013508
bnc691fda62016-08-12 00:43:163509 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233510 // be issuing -- the final header line contains the credentials.
3511 MockWrite(ASYNC, 3,
3512 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3513 "Host: www.example.org:443\r\n"
3514 "Proxy-Connection: keep-alive\r\n"
3515 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3516 };
ttuttle34f63b52015-03-05 04:33:013517
mmenked39192ee2015-12-09 00:57:233518 // The proxy responds to the connect with a 407, using a persistent
3519 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3520 MockRead data_reads1[] = {
3521 // No credentials.
3522 MockRead(ASYNC, 1,
3523 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3524 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3525 "Proxy-Connection: keep-alive\r\n"
3526 "Content-Length: 10\r\n\r\n"),
3527 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013528
mmenked39192ee2015-12-09 00:57:233529 // Wrong credentials (wrong password).
3530 MockRead(ASYNC, 4,
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 // No response body because the test stops reading here.
3536 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3537 };
ttuttle34f63b52015-03-05 04:33:013538
Ryan Sleevib8d7ea02018-05-07 20:01:013539 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233540 data1.set_busy_before_sync_reads(true);
3541 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013542
mmenked39192ee2015-12-09 00:57:233543 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013544
bnc691fda62016-08-12 00:43:163545 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013546 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013547
Eric Roman79cc7552019-07-19 02:17:543548 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233549 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003550 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3551 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233552 ExpectLogContainsSomewhere(
3553 entries, pos,
mikecirone8b85c432016-09-08 19:11:003554 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3555 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013556
bnc691fda62016-08-12 00:43:163557 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233558 ASSERT_TRUE(response);
3559 ASSERT_TRUE(response->headers);
3560 EXPECT_TRUE(response->headers->IsKeepAlive());
3561 EXPECT_EQ(407, response->headers->response_code());
3562 EXPECT_EQ(10, response->headers->GetContentLength());
3563 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583564 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013565
mmenked39192ee2015-12-09 00:57:233566 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013567
mmenked39192ee2015-12-09 00:57:233568 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163569 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3570 callback2.callback());
robpercival214763f2016-07-01 23:27:013571 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013572
bnc691fda62016-08-12 00:43:163573 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233574 ASSERT_TRUE(response);
3575 ASSERT_TRUE(response->headers);
3576 EXPECT_TRUE(response->headers->IsKeepAlive());
3577 EXPECT_EQ(407, response->headers->response_code());
3578 EXPECT_EQ(10, response->headers->GetContentLength());
3579 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583580 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013581
mmenked39192ee2015-12-09 00:57:233582 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3583 // out of scope.
3584 session->CloseAllConnections();
3585 }
ttuttle34f63b52015-03-05 04:33:013586}
3587
3588// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3589// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013590TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233591 // On the second pass, the body read of the auth challenge is synchronous, so
3592 // IsConnectedAndIdle returns false. The socket should still be drained and
3593 // reused. See http://crbug.com/544255.
3594 for (int i = 0; i < 2; ++i) {
3595 HttpRequestInfo request;
3596 request.method = "GET";
3597 request.url = GURL("https://www.example.org/");
3598 // Ensure that proxy authentication is attempted even
3599 // when the no authentication data flag is set.
3600 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103601 request.traffic_annotation =
3602 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233603
3604 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593605 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493606 ProxyResolutionService::CreateFixed("myproxy:70",
3607 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233608 BoundTestNetLog log;
3609 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093610 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233611
bnc691fda62016-08-12 00:43:163612 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233613
3614 // Since we have proxy, should try to establish tunnel.
3615 MockWrite data_writes1[] = {
3616 MockWrite(ASYNC, 0,
3617 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3618 "Host: www.example.org:443\r\n"
3619 "Proxy-Connection: keep-alive\r\n\r\n"),
3620
bnc691fda62016-08-12 00:43:163621 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233622 // be issuing -- the final header line contains the credentials.
3623 MockWrite(ASYNC, 3,
3624 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3625 "Host: www.example.org:443\r\n"
3626 "Proxy-Connection: keep-alive\r\n"
3627 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3628 };
3629
3630 // The proxy responds to the connect with a 407, using a persistent
3631 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3632 MockRead data_reads1[] = {
3633 // No credentials.
3634 MockRead(ASYNC, 1,
3635 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3636 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3637 "Content-Length: 10\r\n\r\n"),
3638 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3639
3640 // Wrong credentials (wrong password).
3641 MockRead(ASYNC, 4,
3642 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3643 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3644 "Content-Length: 10\r\n\r\n"),
3645 // No response body because the test stops reading here.
3646 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3647 };
3648
Ryan Sleevib8d7ea02018-05-07 20:01:013649 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233650 data1.set_busy_before_sync_reads(true);
3651 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3652
3653 TestCompletionCallback callback1;
3654
bnc691fda62016-08-12 00:43:163655 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013656 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233657
Eric Roman79cc7552019-07-19 02:17:543658 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233659 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003660 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3661 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233662 ExpectLogContainsSomewhere(
3663 entries, pos,
mikecirone8b85c432016-09-08 19:11:003664 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3665 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233666
bnc691fda62016-08-12 00:43:163667 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233668 ASSERT_TRUE(response);
3669 ASSERT_TRUE(response->headers);
3670 EXPECT_TRUE(response->headers->IsKeepAlive());
3671 EXPECT_EQ(407, response->headers->response_code());
3672 EXPECT_EQ(10, response->headers->GetContentLength());
3673 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583674 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503675 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233676
3677 TestCompletionCallback callback2;
3678
3679 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163680 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3681 callback2.callback());
robpercival214763f2016-07-01 23:27:013682 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233683
bnc691fda62016-08-12 00:43:163684 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233685 ASSERT_TRUE(response);
3686 ASSERT_TRUE(response->headers);
3687 EXPECT_TRUE(response->headers->IsKeepAlive());
3688 EXPECT_EQ(407, response->headers->response_code());
3689 EXPECT_EQ(10, response->headers->GetContentLength());
3690 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583691 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503692 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233693
3694 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3695 // out of scope.
3696 session->CloseAllConnections();
3697 }
3698}
3699
3700// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3701// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3702// the case the server sends extra data on the original socket, so it can't be
3703// reused.
bncd16676a2016-07-20 16:23:013704TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273705 HttpRequestInfo request;
3706 request.method = "GET";
bncce36dca22015-04-21 22:11:233707 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273708 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293709 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103710 request.traffic_annotation =
3711 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273712
[email protected]2d2697f92009-02-18 21:00:323713 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593714 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493715 ProxyResolutionService::CreateFixedFromPacResult(
3716 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513717 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073718 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093719 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323720
[email protected]2d2697f92009-02-18 21:00:323721 // Since we have proxy, should try to establish tunnel.
3722 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233723 MockWrite(ASYNC, 0,
3724 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173725 "Host: www.example.org:443\r\n"
3726 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233727 };
[email protected]2d2697f92009-02-18 21:00:323728
mmenked39192ee2015-12-09 00:57:233729 // The proxy responds to the connect with a 407, using a persistent, but sends
3730 // extra data, so the socket cannot be reused.
3731 MockRead data_reads1[] = {
3732 // No credentials.
3733 MockRead(ASYNC, 1,
3734 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3735 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3736 "Content-Length: 10\r\n\r\n"),
3737 MockRead(SYNCHRONOUS, 2, "0123456789"),
3738 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3739 };
3740
3741 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233742 // After calling trans->RestartWithAuth(), this is the request we should
3743 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233744 MockWrite(ASYNC, 0,
3745 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173746 "Host: www.example.org:443\r\n"
3747 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233748 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3749
3750 MockWrite(ASYNC, 2,
3751 "GET / HTTP/1.1\r\n"
3752 "Host: www.example.org\r\n"
3753 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323754 };
3755
mmenked39192ee2015-12-09 00:57:233756 MockRead data_reads2[] = {
3757 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323758
mmenked39192ee2015-12-09 00:57:233759 MockRead(ASYNC, 3,
3760 "HTTP/1.1 200 OK\r\n"
3761 "Content-Type: text/html; charset=iso-8859-1\r\n"
3762 "Content-Length: 5\r\n\r\n"),
3763 // No response body because the test stops reading here.
3764 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323765 };
3766
Ryan Sleevib8d7ea02018-05-07 20:01:013767 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233768 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073769 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013770 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233771 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3772 SSLSocketDataProvider ssl(ASYNC, OK);
3773 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323774
[email protected]49639fa2011-12-20 23:22:413775 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323776
bnc87dcefc2017-05-25 12:47:583777 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193778 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323779
mmenked39192ee2015-12-09 00:57:233780 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013781 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233782
Eric Roman79cc7552019-07-19 02:17:543783 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393784 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003785 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3786 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393787 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403788 entries, pos,
mikecirone8b85c432016-09-08 19:11:003789 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3790 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323791
[email protected]1c773ea12009-04-28 19:58:423792 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243793 ASSERT_TRUE(response);
3794 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323795 EXPECT_TRUE(response->headers->IsKeepAlive());
3796 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423797 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583798 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323799
mmenked39192ee2015-12-09 00:57:233800 LoadTimingInfo load_timing_info;
3801 // CONNECT requests and responses are handled at the connect job level, so
3802 // the transaction does not yet have a connection.
3803 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3804
[email protected]49639fa2011-12-20 23:22:413805 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323806
mmenked39192ee2015-12-09 00:57:233807 rv =
3808 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013809 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323810
[email protected]2d2697f92009-02-18 21:00:323811 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233812 EXPECT_EQ(200, response->headers->response_code());
3813 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423814 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133815
mmenked39192ee2015-12-09 00:57:233816 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583817 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233818
3819 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3820 TestLoadTimingNotReusedWithPac(load_timing_info,
3821 CONNECT_TIMING_HAS_SSL_TIMES);
3822
3823 trans.reset();
[email protected]102e27c2011-02-23 01:01:313824 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323825}
3826
mmenkee71e15332015-10-07 16:39:543827// Test the case a proxy closes a socket while the challenge body is being
3828// drained.
bncd16676a2016-07-20 16:23:013829TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543830 HttpRequestInfo request;
3831 request.method = "GET";
3832 request.url = GURL("https://www.example.org/");
3833 // Ensure that proxy authentication is attempted even
3834 // when the no authentication data flag is set.
3835 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103836 request.traffic_annotation =
3837 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543838
3839 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493840 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3841 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093842 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543843
bnc691fda62016-08-12 00:43:163844 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543845
3846 // Since we have proxy, should try to establish tunnel.
3847 MockWrite data_writes1[] = {
3848 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173849 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543850 "Proxy-Connection: keep-alive\r\n\r\n"),
3851 };
3852
3853 // The proxy responds to the connect with a 407, using a persistent
3854 // connection.
3855 MockRead data_reads1[] = {
3856 // No credentials.
3857 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3858 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3859 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3860 // Server hands up in the middle of the body.
3861 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3862 };
3863
3864 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163865 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543866 // be issuing -- the final header line contains the credentials.
3867 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173868 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543869 "Proxy-Connection: keep-alive\r\n"
3870 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3871
3872 MockWrite("GET / HTTP/1.1\r\n"
3873 "Host: www.example.org\r\n"
3874 "Connection: keep-alive\r\n\r\n"),
3875 };
3876
3877 MockRead data_reads2[] = {
3878 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3879
3880 MockRead("HTTP/1.1 200 OK\r\n"),
3881 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3882 MockRead("Content-Length: 5\r\n\r\n"),
3883 MockRead(SYNCHRONOUS, "hello"),
3884 };
3885
Ryan Sleevib8d7ea02018-05-07 20:01:013886 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543887 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013888 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543889 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3890 SSLSocketDataProvider ssl(ASYNC, OK);
3891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3892
3893 TestCompletionCallback callback;
3894
tfarina42834112016-09-22 13:38:203895 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013896 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543897
bnc691fda62016-08-12 00:43:163898 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543899 ASSERT_TRUE(response);
3900 ASSERT_TRUE(response->headers);
3901 EXPECT_TRUE(response->headers->IsKeepAlive());
3902 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583903 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543904
bnc691fda62016-08-12 00:43:163905 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013906 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543907
bnc691fda62016-08-12 00:43:163908 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543909 ASSERT_TRUE(response);
3910 ASSERT_TRUE(response->headers);
3911 EXPECT_TRUE(response->headers->IsKeepAlive());
3912 EXPECT_EQ(200, response->headers->response_code());
3913 std::string body;
bnc691fda62016-08-12 00:43:163914 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543915 EXPECT_EQ("hello", body);
3916}
3917
[email protected]a8e9b162009-03-12 00:06:443918// Test that we don't read the response body when we fail to establish a tunnel,
3919// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013920TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273921 HttpRequestInfo request;
3922 request.method = "GET";
bncce36dca22015-04-21 22:11:233923 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103924 request.traffic_annotation =
3925 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273926
[email protected]a8e9b162009-03-12 00:06:443927 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493928 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3929 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443930
danakj1fd259a02016-04-16 03:17:093931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443932
bnc691fda62016-08-12 00:43:163933 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443934
[email protected]a8e9b162009-03-12 00:06:443935 // Since we have proxy, should try to establish tunnel.
3936 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173937 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3938 "Host: www.example.org:443\r\n"
3939 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443940 };
3941
3942 // The proxy responds to the connect with a 407.
3943 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243944 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3945 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3946 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233947 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243948 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443949 };
3950
Ryan Sleevib8d7ea02018-05-07 20:01:013951 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073952 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443953
[email protected]49639fa2011-12-20 23:22:413954 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443955
tfarina42834112016-09-22 13:38:203956 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013957 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:443958
3959 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013960 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:443961
bnc691fda62016-08-12 00:43:163962 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243963 ASSERT_TRUE(response);
3964 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443965 EXPECT_TRUE(response->headers->IsKeepAlive());
3966 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423967 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443968
3969 std::string response_data;
bnc691fda62016-08-12 00:43:163970 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:013971 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:183972
3973 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313974 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443975}
3976
ttuttle7933c112015-01-06 00:55:243977// Test that we don't pass extraneous headers from the proxy's response to the
3978// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:013979TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:243980 HttpRequestInfo request;
3981 request.method = "GET";
bncce36dca22015-04-21 22:11:233982 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103983 request.traffic_annotation =
3984 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:243985
3986 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493987 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3988 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:243989
danakj1fd259a02016-04-16 03:17:093990 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243991
bnc691fda62016-08-12 00:43:163992 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:243993
3994 // Since we have proxy, should try to establish tunnel.
3995 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173996 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3997 "Host: www.example.org:443\r\n"
3998 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:243999 };
4000
4001 // The proxy responds to the connect with a 407.
4002 MockRead data_reads[] = {
4003 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4004 MockRead("X-Foo: bar\r\n"),
4005 MockRead("Set-Cookie: foo=bar\r\n"),
4006 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4007 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234008 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244009 };
4010
Ryan Sleevib8d7ea02018-05-07 20:01:014011 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244012 session_deps_.socket_factory->AddSocketDataProvider(&data);
4013
4014 TestCompletionCallback callback;
4015
tfarina42834112016-09-22 13:38:204016 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014017 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244018
4019 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014020 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244021
bnc691fda62016-08-12 00:43:164022 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244023 ASSERT_TRUE(response);
4024 ASSERT_TRUE(response->headers);
4025 EXPECT_TRUE(response->headers->IsKeepAlive());
4026 EXPECT_EQ(407, response->headers->response_code());
4027 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4028 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4029 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4030
4031 std::string response_data;
bnc691fda62016-08-12 00:43:164032 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014033 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244034
4035 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4036 session->CloseAllConnections();
4037}
4038
[email protected]8fdbcd22010-05-05 02:54:524039// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4040// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014041TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524042 HttpRequestInfo request;
4043 request.method = "GET";
bncce36dca22015-04-21 22:11:234044 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104045 request.traffic_annotation =
4046 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524047
[email protected]cb9bf6ca2011-01-28 13:15:274048 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094049 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164050 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274051
[email protected]8fdbcd22010-05-05 02:54:524052 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234053 MockWrite(
4054 "GET / HTTP/1.1\r\n"
4055 "Host: www.example.org\r\n"
4056 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524057 };
4058
4059 MockRead data_reads1[] = {
4060 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4061 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4062 // Large content-length -- won't matter, as connection will be reset.
4063 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064064 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524065 };
4066
Ryan Sleevib8d7ea02018-05-07 20:01:014067 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074068 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524069
[email protected]49639fa2011-12-20 23:22:414070 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524071
tfarina42834112016-09-22 13:38:204072 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014073 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524074
4075 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014076 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524077}
4078
[email protected]7a67a8152010-11-05 18:31:104079// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4080// through a non-authenticating proxy. The request should fail with
4081// ERR_UNEXPECTED_PROXY_AUTH.
4082// Note that it is impossible to detect if an HTTP server returns a 407 through
4083// a non-authenticating proxy - there is nothing to indicate whether the
4084// response came from the proxy or the server, so it is treated as if the proxy
4085// issued the challenge.
bncd16676a2016-07-20 16:23:014086TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274087 HttpRequestInfo request;
4088 request.method = "GET";
bncce36dca22015-04-21 22:11:234089 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104090 request.traffic_annotation =
4091 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274092
Ramin Halavatica8d5252018-03-12 05:33:494093 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4094 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514095 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074096 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094097 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104098
[email protected]7a67a8152010-11-05 18:31:104099 // Since we have proxy, should try to establish tunnel.
4100 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174101 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4102 "Host: www.example.org:443\r\n"
4103 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104104
rsleevidb16bb02015-11-12 23:47:174105 MockWrite("GET / HTTP/1.1\r\n"
4106 "Host: www.example.org\r\n"
4107 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104108 };
4109
4110 MockRead data_reads1[] = {
4111 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4112
4113 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4114 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4115 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064116 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104117 };
4118
Ryan Sleevib8d7ea02018-05-07 20:01:014119 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074120 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064121 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074122 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104123
[email protected]49639fa2011-12-20 23:22:414124 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104125
bnc691fda62016-08-12 00:43:164126 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104127
bnc691fda62016-08-12 00:43:164128 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014129 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104130
4131 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014132 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544133 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104134 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004135 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4136 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104137 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404138 entries, pos,
mikecirone8b85c432016-09-08 19:11:004139 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4140 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104141}
[email protected]2df19bb2010-08-25 20:13:464142
mmenke2a1781d2015-10-07 19:25:334143// Test a proxy auth scheme that allows default credentials and a proxy server
4144// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014145TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334146 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4147 HttpRequestInfo request;
4148 request.method = "GET";
4149 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104150 request.traffic_annotation =
4151 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334152
4153 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594154 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494155 ProxyResolutionService::CreateFixedFromPacResult(
4156 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334157
Jeremy Roman0579ed62017-08-29 15:56:194158 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334159 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194160 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334161 mock_handler->set_allows_default_credentials(true);
4162 auth_handler_factory->AddMockHandler(mock_handler.release(),
4163 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484164 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334165
4166 // Add NetLog just so can verify load timing information gets a NetLog ID.
4167 NetLog net_log;
4168 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094169 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334170
4171 // Since we have proxy, should try to establish tunnel.
4172 MockWrite data_writes1[] = {
4173 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174174 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334175 "Proxy-Connection: keep-alive\r\n\r\n"),
4176 };
4177
4178 // The proxy responds to the connect with a 407, using a non-persistent
4179 // connection.
4180 MockRead data_reads1[] = {
4181 // No credentials.
4182 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4183 MockRead("Proxy-Authenticate: Mock\r\n"),
4184 MockRead("Proxy-Connection: close\r\n\r\n"),
4185 };
4186
4187 // Since the first connection couldn't be reused, need to establish another
4188 // once given credentials.
4189 MockWrite data_writes2[] = {
4190 // After calling trans->RestartWithAuth(), this is the request we should
4191 // be issuing -- the final header line contains the credentials.
4192 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174193 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334194 "Proxy-Connection: keep-alive\r\n"
4195 "Proxy-Authorization: auth_token\r\n\r\n"),
4196
4197 MockWrite("GET / HTTP/1.1\r\n"
4198 "Host: www.example.org\r\n"
4199 "Connection: keep-alive\r\n\r\n"),
4200 };
4201
4202 MockRead data_reads2[] = {
4203 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4204
4205 MockRead("HTTP/1.1 200 OK\r\n"),
4206 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4207 MockRead("Content-Length: 5\r\n\r\n"),
4208 MockRead(SYNCHRONOUS, "hello"),
4209 };
4210
Ryan Sleevib8d7ea02018-05-07 20:01:014211 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334212 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014213 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334214 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4215 SSLSocketDataProvider ssl(ASYNC, OK);
4216 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4217
bnc87dcefc2017-05-25 12:47:584218 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194219 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334220
4221 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204222 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014223 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334224
4225 const HttpResponseInfo* response = trans->GetResponseInfo();
4226 ASSERT_TRUE(response);
4227 ASSERT_TRUE(response->headers);
4228 EXPECT_FALSE(response->headers->IsKeepAlive());
4229 EXPECT_EQ(407, response->headers->response_code());
4230 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4231 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584232 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334233
4234 LoadTimingInfo load_timing_info;
4235 // CONNECT requests and responses are handled at the connect job level, so
4236 // the transaction does not yet have a connection.
4237 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4238
4239 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014240 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334241 response = trans->GetResponseInfo();
4242 ASSERT_TRUE(response);
4243 ASSERT_TRUE(response->headers);
4244 EXPECT_TRUE(response->headers->IsKeepAlive());
4245 EXPECT_EQ(200, response->headers->response_code());
4246 EXPECT_EQ(5, response->headers->GetContentLength());
4247 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4248
4249 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584250 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334251
4252 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4253 TestLoadTimingNotReusedWithPac(load_timing_info,
4254 CONNECT_TIMING_HAS_SSL_TIMES);
4255
4256 trans.reset();
4257 session->CloseAllConnections();
4258}
4259
4260// Test a proxy auth scheme that allows default credentials and a proxy server
4261// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014262TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334263 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4264 HttpRequestInfo request;
4265 request.method = "GET";
4266 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104267 request.traffic_annotation =
4268 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334269
4270 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594271 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494272 ProxyResolutionService::CreateFixedFromPacResult(
4273 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334274
Jeremy Roman0579ed62017-08-29 15:56:194275 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334276 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194277 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334278 mock_handler->set_allows_default_credentials(true);
4279 auth_handler_factory->AddMockHandler(mock_handler.release(),
4280 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484281 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334282
4283 // Add NetLog just so can verify load timing information gets a NetLog ID.
4284 NetLog net_log;
4285 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094286 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334287
4288 // Should try to establish tunnel.
4289 MockWrite data_writes1[] = {
4290 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174291 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334292 "Proxy-Connection: keep-alive\r\n\r\n"),
4293
4294 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174295 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334296 "Proxy-Connection: keep-alive\r\n"
4297 "Proxy-Authorization: auth_token\r\n\r\n"),
4298 };
4299
4300 // The proxy responds to the connect with a 407, using a non-persistent
4301 // connection.
4302 MockRead data_reads1[] = {
4303 // No credentials.
4304 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4305 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4306 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4307 };
4308
4309 // Since the first connection was closed, need to establish another once given
4310 // credentials.
4311 MockWrite data_writes2[] = {
4312 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174313 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334314 "Proxy-Connection: keep-alive\r\n"
4315 "Proxy-Authorization: auth_token\r\n\r\n"),
4316
4317 MockWrite("GET / HTTP/1.1\r\n"
4318 "Host: www.example.org\r\n"
4319 "Connection: keep-alive\r\n\r\n"),
4320 };
4321
4322 MockRead data_reads2[] = {
4323 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4324
4325 MockRead("HTTP/1.1 200 OK\r\n"),
4326 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4327 MockRead("Content-Length: 5\r\n\r\n"),
4328 MockRead(SYNCHRONOUS, "hello"),
4329 };
4330
Ryan Sleevib8d7ea02018-05-07 20:01:014331 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334332 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014333 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334334 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4335 SSLSocketDataProvider ssl(ASYNC, OK);
4336 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4337
bnc87dcefc2017-05-25 12:47:584338 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194339 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334340
4341 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204342 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014343 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334344
4345 const HttpResponseInfo* response = trans->GetResponseInfo();
4346 ASSERT_TRUE(response);
4347 ASSERT_TRUE(response->headers);
4348 EXPECT_TRUE(response->headers->IsKeepAlive());
4349 EXPECT_EQ(407, response->headers->response_code());
4350 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4351 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584352 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334353
4354 LoadTimingInfo load_timing_info;
4355 // CONNECT requests and responses are handled at the connect job level, so
4356 // the transaction does not yet have a connection.
4357 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4358
4359 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014360 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334361
4362 response = trans->GetResponseInfo();
4363 ASSERT_TRUE(response);
4364 ASSERT_TRUE(response->headers);
4365 EXPECT_TRUE(response->headers->IsKeepAlive());
4366 EXPECT_EQ(200, response->headers->response_code());
4367 EXPECT_EQ(5, response->headers->GetContentLength());
4368 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4369
4370 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584371 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334372
4373 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4374 TestLoadTimingNotReusedWithPac(load_timing_info,
4375 CONNECT_TIMING_HAS_SSL_TIMES);
4376
4377 trans.reset();
4378 session->CloseAllConnections();
4379}
4380
4381// Test a proxy auth scheme that allows default credentials and a proxy server
4382// that hangs up when credentials are initially sent, and hangs up again when
4383// they are retried.
bncd16676a2016-07-20 16:23:014384TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334385 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
4386 HttpRequestInfo request;
4387 request.method = "GET";
4388 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104389 request.traffic_annotation =
4390 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334391
4392 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594393 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494394 ProxyResolutionService::CreateFixedFromPacResult(
4395 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334396
Jeremy Roman0579ed62017-08-29 15:56:194397 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334398 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194399 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334400 mock_handler->set_allows_default_credentials(true);
4401 auth_handler_factory->AddMockHandler(mock_handler.release(),
4402 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484403 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334404
4405 // Add NetLog just so can verify load timing information gets a NetLog ID.
4406 NetLog net_log;
4407 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094408 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334409
4410 // Should try to establish tunnel.
4411 MockWrite data_writes1[] = {
4412 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174413 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334414 "Proxy-Connection: keep-alive\r\n\r\n"),
4415
4416 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174417 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334418 "Proxy-Connection: keep-alive\r\n"
4419 "Proxy-Authorization: auth_token\r\n\r\n"),
4420 };
4421
4422 // The proxy responds to the connect with a 407, and then hangs up after the
4423 // second request is sent.
4424 MockRead data_reads1[] = {
4425 // No credentials.
4426 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4427 MockRead("Content-Length: 0\r\n"),
4428 MockRead("Proxy-Connection: keep-alive\r\n"),
4429 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4430 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4431 };
4432
4433 // HttpNetworkTransaction sees a reused connection that was closed with
4434 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
4435 // request.
4436 MockWrite data_writes2[] = {
4437 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174438 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334439 "Proxy-Connection: keep-alive\r\n\r\n"),
4440 };
4441
4442 // The proxy, having had more than enough of us, just hangs up.
4443 MockRead data_reads2[] = {
4444 // No credentials.
4445 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4446 };
4447
Ryan Sleevib8d7ea02018-05-07 20:01:014448 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334449 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014450 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334451 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4452
bnc87dcefc2017-05-25 12:47:584453 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194454 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334455
4456 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204457 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014458 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334459
4460 const HttpResponseInfo* response = trans->GetResponseInfo();
4461 ASSERT_TRUE(response);
4462 ASSERT_TRUE(response->headers);
4463 EXPECT_TRUE(response->headers->IsKeepAlive());
4464 EXPECT_EQ(407, response->headers->response_code());
4465 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4466 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584467 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334468
4469 LoadTimingInfo load_timing_info;
4470 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4471
4472 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014473 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:334474
4475 trans.reset();
4476 session->CloseAllConnections();
4477}
4478
Asanka Herathbc3f8f62018-11-16 23:08:304479// This test exercises an odd edge case where the proxy closes the connection
4480// after the authentication handshake is complete. Presumably this technique is
4481// used in lieu of returning a 403 or 5xx status code when the authentication
4482// succeeds, but the user is not authorized to connect to the destination
4483// server. There's no standard for what a proxy should do to indicate a blocked
4484// site.
4485TEST_F(HttpNetworkTransactionTest,
4486 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
4487 HttpRequestInfo request;
4488 request.method = "GET";
4489 request.url = GURL("https://www.example.org/");
4490 request.traffic_annotation =
4491 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4492
4493 // Configure against proxy server "myproxy:70".
4494 session_deps_.proxy_resolution_service =
4495 ProxyResolutionService::CreateFixedFromPacResult(
4496 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4497
Asanka Herathbc3f8f62018-11-16 23:08:304498 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
4499 auth_handler_factory->set_do_init_from_challenge(true);
4500
4501 // Create two mock AuthHandlers. This is because the transaction gets retried
4502 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
4503 // was a real network error.
4504 //
4505 // The handlers support both default and explicit credentials. The retry
4506 // mentioned above should be able to reuse the default identity. Thus there
4507 // should never be a need to prompt for explicit credentials.
4508 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
4509 mock_handler->set_allows_default_credentials(true);
4510 mock_handler->set_allows_explicit_credentials(true);
4511 mock_handler->set_connection_based(true);
4512 auth_handler_factory->AddMockHandler(mock_handler.release(),
4513 HttpAuth::AUTH_PROXY);
4514 mock_handler = std::make_unique<HttpAuthHandlerMock>();
4515 mock_handler->set_allows_default_credentials(true);
4516 mock_handler->set_allows_explicit_credentials(true);
4517 mock_handler->set_connection_based(true);
4518 auth_handler_factory->AddMockHandler(mock_handler.release(),
4519 HttpAuth::AUTH_PROXY);
4520 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4521
4522 NetLog net_log;
4523 session_deps_.net_log = &net_log;
4524 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4525
4526 // Data for both sockets.
4527 //
4528 // Writes are for the tunnel establishment attempts and the
4529 // authentication handshake.
4530 MockWrite data_writes1[] = {
4531 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4532 "Host: www.example.org:443\r\n"
4533 "Proxy-Connection: keep-alive\r\n\r\n"),
4534
4535 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4536 "Host: www.example.org:443\r\n"
4537 "Proxy-Connection: keep-alive\r\n"
4538 "Proxy-Authorization: auth_token\r\n\r\n"),
4539
4540 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4541 "Host: www.example.org:443\r\n"
4542 "Proxy-Connection: keep-alive\r\n"
4543 "Proxy-Authorization: auth_token\r\n\r\n"),
4544 };
4545
4546 // The server side of the authentication handshake. Note that the response to
4547 // the final CONNECT request is ERR_CONNECTION_CLOSED.
4548 MockRead data_reads1[] = {
4549 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4550 MockRead("Content-Length: 0\r\n"),
4551 MockRead("Proxy-Connection: keep-alive\r\n"),
4552 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4553
4554 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4555 MockRead("Content-Length: 0\r\n"),
4556 MockRead("Proxy-Connection: keep-alive\r\n"),
4557 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
4558
4559 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4560 };
4561
4562 StaticSocketDataProvider data1(data_reads1, data_writes1);
4563 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4564
4565 // The second socket is for the reconnection attempt. Data is identical to the
4566 // first attempt.
4567 StaticSocketDataProvider data2(data_reads1, data_writes1);
4568 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4569
4570 auto trans =
4571 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4572
4573 TestCompletionCallback callback;
4574 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4575
4576 // Two rounds per handshake. After one retry, the error is propagated up the
4577 // stack.
4578 for (int i = 0; i < 4; ++i) {
4579 EXPECT_THAT(callback.GetResult(rv), IsOk());
4580
4581 const HttpResponseInfo* response = trans->GetResponseInfo();
4582 ASSERT_TRUE(response);
4583 ASSERT_TRUE(response->headers);
4584 EXPECT_EQ(407, response->headers->response_code());
4585 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
4586
4587 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4588 }
4589
4590 // One shall be the number thou shalt retry, and the number of the retrying
4591 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
4592 // that thou then proceed to one. Three is right out. Once the number one,
4593 // being the first number, be reached, then lobbest thou thy
4594 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
4595 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
4596
4597 trans.reset();
4598 session->CloseAllConnections();
4599}
4600
mmenke2a1781d2015-10-07 19:25:334601// Test a proxy auth scheme that allows default credentials and a proxy server
4602// that hangs up when credentials are initially sent, and sends a challenge
4603// again they are retried.
bncd16676a2016-07-20 16:23:014604TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334605 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
4606 HttpRequestInfo request;
4607 request.method = "GET";
4608 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104609 request.traffic_annotation =
4610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334611
4612 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594613 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494614 ProxyResolutionService::CreateFixedFromPacResult(
4615 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334616
Jeremy Roman0579ed62017-08-29 15:56:194617 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334618 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194619 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334620 mock_handler->set_allows_default_credentials(true);
4621 auth_handler_factory->AddMockHandler(mock_handler.release(),
4622 HttpAuth::AUTH_PROXY);
4623 // Add another handler for the second challenge. It supports default
4624 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194625 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334626 mock_handler->set_allows_default_credentials(true);
4627 auth_handler_factory->AddMockHandler(mock_handler.release(),
4628 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484629 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334630
4631 // Add NetLog just so can verify load timing information gets a NetLog ID.
4632 NetLog net_log;
4633 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094634 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334635
4636 // Should try to establish tunnel.
4637 MockWrite data_writes1[] = {
4638 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174639 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334640 "Proxy-Connection: keep-alive\r\n\r\n"),
4641 };
4642
4643 // The proxy responds to the connect with a 407, using a non-persistent
4644 // connection.
4645 MockRead data_reads1[] = {
4646 // No credentials.
4647 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4648 MockRead("Proxy-Authenticate: Mock\r\n"),
4649 MockRead("Proxy-Connection: close\r\n\r\n"),
4650 };
4651
4652 // Since the first connection was closed, need to establish another once given
4653 // credentials.
4654 MockWrite data_writes2[] = {
4655 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174656 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334657 "Proxy-Connection: keep-alive\r\n"
4658 "Proxy-Authorization: auth_token\r\n\r\n"),
4659 };
4660
4661 MockRead data_reads2[] = {
4662 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4663 MockRead("Proxy-Authenticate: Mock\r\n"),
4664 MockRead("Proxy-Connection: close\r\n\r\n"),
4665 };
4666
Ryan Sleevib8d7ea02018-05-07 20:01:014667 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334668 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014669 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334670 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4671 SSLSocketDataProvider ssl(ASYNC, OK);
4672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4673
bnc87dcefc2017-05-25 12:47:584674 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194675 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334676
4677 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204678 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014679 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334680
4681 const HttpResponseInfo* response = trans->GetResponseInfo();
4682 ASSERT_TRUE(response);
4683 ASSERT_TRUE(response->headers);
4684 EXPECT_EQ(407, response->headers->response_code());
4685 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4686 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584687 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334688
4689 LoadTimingInfo load_timing_info;
4690 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4691
4692 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014693 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334694 response = trans->GetResponseInfo();
4695 ASSERT_TRUE(response);
4696 ASSERT_TRUE(response->headers);
4697 EXPECT_EQ(407, response->headers->response_code());
4698 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584699 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334700
4701 trans.reset();
4702 session->CloseAllConnections();
4703}
4704
asankae2257db2016-10-11 22:03:164705// A more nuanced test than GenerateAuthToken test which asserts that
4706// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
4707// unnecessarily invalidated, and that if the server co-operates, the
4708// authentication handshake can continue with the same scheme but with a
4709// different identity.
4710TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
4711 HttpRequestInfo request;
4712 request.method = "GET";
4713 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104714 request.traffic_annotation =
4715 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:164716
Jeremy Roman0579ed62017-08-29 15:56:194717 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:164718 auth_handler_factory->set_do_init_from_challenge(true);
4719
4720 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:194721 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164722 mock_handler->set_allows_default_credentials(true);
4723 mock_handler->set_allows_explicit_credentials(true);
4724 mock_handler->set_connection_based(true);
4725 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
4726 auth_handler_factory->AddMockHandler(mock_handler.release(),
4727 HttpAuth::AUTH_SERVER);
4728
4729 // Add another handler for the second challenge. It supports default
4730 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194731 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164732 mock_handler->set_allows_default_credentials(true);
4733 mock_handler->set_allows_explicit_credentials(true);
4734 mock_handler->set_connection_based(true);
4735 auth_handler_factory->AddMockHandler(mock_handler.release(),
4736 HttpAuth::AUTH_SERVER);
4737 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4738
4739 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4740
4741 MockWrite data_writes1[] = {
4742 MockWrite("GET / HTTP/1.1\r\n"
4743 "Host: www.example.org\r\n"
4744 "Connection: keep-alive\r\n\r\n"),
4745 };
4746
4747 MockRead data_reads1[] = {
4748 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4749 "WWW-Authenticate: Mock\r\n"
4750 "Connection: keep-alive\r\n\r\n"),
4751 };
4752
4753 // Identical to data_writes1[]. The AuthHandler encounters a
4754 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
4755 // transaction procceds without an authorization header.
4756 MockWrite data_writes2[] = {
4757 MockWrite("GET / HTTP/1.1\r\n"
4758 "Host: www.example.org\r\n"
4759 "Connection: keep-alive\r\n\r\n"),
4760 };
4761
4762 MockRead data_reads2[] = {
4763 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4764 "WWW-Authenticate: Mock\r\n"
4765 "Connection: keep-alive\r\n\r\n"),
4766 };
4767
4768 MockWrite data_writes3[] = {
4769 MockWrite("GET / HTTP/1.1\r\n"
4770 "Host: www.example.org\r\n"
4771 "Connection: keep-alive\r\n"
4772 "Authorization: auth_token\r\n\r\n"),
4773 };
4774
4775 MockRead data_reads3[] = {
4776 MockRead("HTTP/1.1 200 OK\r\n"
4777 "Content-Length: 5\r\n"
4778 "Content-Type: text/plain\r\n"
4779 "Connection: keep-alive\r\n\r\n"
4780 "Hello"),
4781 };
4782
Ryan Sleevib8d7ea02018-05-07 20:01:014783 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:164784 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4785
Ryan Sleevib8d7ea02018-05-07 20:01:014786 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:164787 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4788
Ryan Sleevib8d7ea02018-05-07 20:01:014789 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:164790 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4791
bnc87dcefc2017-05-25 12:47:584792 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194793 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:164794
4795 TestCompletionCallback callback;
4796 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4797 EXPECT_THAT(callback.GetResult(rv), IsOk());
4798
4799 const HttpResponseInfo* response = trans->GetResponseInfo();
4800 ASSERT_TRUE(response);
4801 ASSERT_TRUE(response->headers);
4802 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4803
4804 // The following three tests assert that an authentication challenge was
4805 // received and that the stack is ready to respond to the challenge using
4806 // ambient credentials.
4807 EXPECT_EQ(401, response->headers->response_code());
4808 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584809 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164810
4811 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4812 EXPECT_THAT(callback.GetResult(rv), IsOk());
4813 response = trans->GetResponseInfo();
4814 ASSERT_TRUE(response);
4815 ASSERT_TRUE(response->headers);
4816
4817 // The following three tests assert that an authentication challenge was
4818 // received and that the stack needs explicit credentials before it is ready
4819 // to respond to the challenge.
4820 EXPECT_EQ(401, response->headers->response_code());
4821 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584822 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164823
4824 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4825 EXPECT_THAT(callback.GetResult(rv), IsOk());
4826 response = trans->GetResponseInfo();
4827 ASSERT_TRUE(response);
4828 ASSERT_TRUE(response->headers);
4829 EXPECT_EQ(200, response->headers->response_code());
4830
4831 trans.reset();
4832 session->CloseAllConnections();
4833}
4834
Matt Menked1eb6d42018-01-17 04:54:064835// Proxy resolver that returns a proxy with the same host and port for different
4836// schemes, based on the path of the URL being requests.
4837class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
4838 public:
4839 SameProxyWithDifferentSchemesProxyResolver() {}
4840 ~SameProxyWithDifferentSchemesProxyResolver() override {}
4841
4842 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
4843
4844 static HostPortPair ProxyHostPortPair() {
4845 return HostPortPair::FromString(ProxyHostPortPairAsString());
4846 }
4847
4848 // ProxyResolver implementation.
4849 int GetProxyForURL(const GURL& url,
4850 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:174851 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:064852 std::unique_ptr<Request>* request,
4853 const NetLogWithSource& /*net_log*/) override {
4854 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:574855 results->set_traffic_annotation(
4856 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:064857 if (url.path() == "/socks4") {
4858 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
4859 return OK;
4860 }
4861 if (url.path() == "/socks5") {
4862 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
4863 return OK;
4864 }
4865 if (url.path() == "/http") {
4866 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
4867 return OK;
4868 }
4869 if (url.path() == "/https") {
4870 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
4871 return OK;
4872 }
Matt Menkee8648fa2019-01-17 16:47:074873 if (url.path() == "/https_trusted") {
4874 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
4875 ProxyHostPortPair(),
4876 true /* is_trusted_proxy */));
4877 return OK;
4878 }
Matt Menked1eb6d42018-01-17 04:54:064879 NOTREACHED();
4880 return ERR_NOT_IMPLEMENTED;
4881 }
4882
4883 private:
4884 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
4885};
4886
4887class SameProxyWithDifferentSchemesProxyResolverFactory
4888 : public ProxyResolverFactory {
4889 public:
4890 SameProxyWithDifferentSchemesProxyResolverFactory()
4891 : ProxyResolverFactory(false) {}
4892
Lily Houghton99597862018-03-07 16:40:424893 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
4894 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:174895 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:424896 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:064897 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
4898 return OK;
4899 }
4900
4901 private:
4902 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
4903};
4904
4905// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:074906// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:064907// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
4908// request to foo.com using proxy.com as an HTTP proxy.
4909TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:494910 session_deps_.proxy_resolution_service =
4911 std::make_unique<ProxyResolutionService>(
4912 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
4913 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
4914 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
4915 nullptr);
Matt Menked1eb6d42018-01-17 04:54:064916
4917 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4918
4919 MockWrite socks_writes[] = {
4920 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
4921 kSOCKS4OkRequestLocalHostPort80Length),
4922 MockWrite(SYNCHRONOUS,
4923 "GET /socks4 HTTP/1.1\r\n"
4924 "Host: test\r\n"
4925 "Connection: keep-alive\r\n\r\n"),
4926 };
4927 MockRead socks_reads[] = {
4928 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
4929 MockRead("HTTP/1.0 200 OK\r\n"
4930 "Connection: keep-alive\r\n"
4931 "Content-Length: 15\r\n\r\n"
4932 "SOCKS4 Response"),
4933 };
Ryan Sleevib8d7ea02018-05-07 20:01:014934 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:064935 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
4936
4937 const char kSOCKS5Request[] = {
4938 0x05, // Version
4939 0x01, // Command (CONNECT)
4940 0x00, // Reserved
4941 0x03, // Address type (DOMAINNAME)
4942 0x04, // Length of domain (4)
4943 't', 'e', 's', 't', // Domain string
4944 0x00, 0x50, // 16-bit port (80)
4945 };
4946 MockWrite socks5_writes[] = {
4947 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:244948 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:064949 MockWrite(SYNCHRONOUS,
4950 "GET /socks5 HTTP/1.1\r\n"
4951 "Host: test\r\n"
4952 "Connection: keep-alive\r\n\r\n"),
4953 };
4954 MockRead socks5_reads[] = {
4955 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
4956 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
4957 MockRead("HTTP/1.0 200 OK\r\n"
4958 "Connection: keep-alive\r\n"
4959 "Content-Length: 15\r\n\r\n"
4960 "SOCKS5 Response"),
4961 };
Ryan Sleevib8d7ea02018-05-07 20:01:014962 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:064963 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
4964
4965 MockWrite http_writes[] = {
4966 MockWrite(SYNCHRONOUS,
4967 "GET http://test/http HTTP/1.1\r\n"
4968 "Host: test\r\n"
4969 "Proxy-Connection: keep-alive\r\n\r\n"),
4970 };
4971 MockRead http_reads[] = {
4972 MockRead("HTTP/1.1 200 OK\r\n"
4973 "Proxy-Connection: keep-alive\r\n"
4974 "Content-Length: 13\r\n\r\n"
4975 "HTTP Response"),
4976 };
Ryan Sleevib8d7ea02018-05-07 20:01:014977 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:064978 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
4979
4980 MockWrite https_writes[] = {
4981 MockWrite(SYNCHRONOUS,
4982 "GET http://test/https HTTP/1.1\r\n"
4983 "Host: test\r\n"
4984 "Proxy-Connection: keep-alive\r\n\r\n"),
4985 };
4986 MockRead https_reads[] = {
4987 MockRead("HTTP/1.1 200 OK\r\n"
4988 "Proxy-Connection: keep-alive\r\n"
4989 "Content-Length: 14\r\n\r\n"
4990 "HTTPS Response"),
4991 };
Ryan Sleevib8d7ea02018-05-07 20:01:014992 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:064993 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
4994 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
4995 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4996
Matt Menkee8648fa2019-01-17 16:47:074997 MockWrite https_trusted_writes[] = {
4998 MockWrite(SYNCHRONOUS,
4999 "GET http://test/https_trusted HTTP/1.1\r\n"
5000 "Host: test\r\n"
5001 "Proxy-Connection: keep-alive\r\n\r\n"),
5002 };
5003 MockRead https_trusted_reads[] = {
5004 MockRead("HTTP/1.1 200 OK\r\n"
5005 "Proxy-Connection: keep-alive\r\n"
5006 "Content-Length: 22\r\n\r\n"
5007 "HTTPS Trusted Response"),
5008 };
5009 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5010 https_trusted_writes);
5011 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5012 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5013 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5014
Matt Menked1eb6d42018-01-17 04:54:065015 struct TestCase {
5016 GURL url;
5017 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075018 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065019 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075020 int expected_idle_socks4_sockets;
5021 int expected_idle_socks5_sockets;
5022 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5023 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065024 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075025 int expected_idle_https_sockets;
5026 // How many idle sockets there should be in the HTTPS proxy socket pool with
5027 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5028 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065029 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075030 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5031 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5032 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5033 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5034 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5035 1},
Matt Menked1eb6d42018-01-17 04:54:065036 };
5037
5038 for (const auto& test_case : kTestCases) {
5039 HttpRequestInfo request;
5040 request.method = "GET";
5041 request.url = test_case.url;
Ramin Halavatib5e433e2018-02-07 07:41:105042 request.traffic_annotation =
5043 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065044 std::unique_ptr<HttpNetworkTransaction> trans =
5045 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5046 session.get());
5047 TestCompletionCallback callback;
5048 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5049 EXPECT_THAT(callback.GetResult(rv), IsOk());
5050
5051 const HttpResponseInfo* response = trans->GetResponseInfo();
5052 ASSERT_TRUE(response);
5053 ASSERT_TRUE(response->headers);
5054 EXPECT_EQ(200, response->headers->response_code());
5055 std::string response_data;
5056 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5057 EXPECT_EQ(test_case.expected_response, response_data);
5058
5059 // Return the socket to the socket pool, so can make sure it's not used for
5060 // the next requests.
5061 trans.reset();
5062 base::RunLoop().RunUntilIdle();
5063
5064 // Check the number of idle sockets in the pool, to make sure that used
5065 // sockets are indeed being returned to the socket pool. If each request
5066 // doesn't return an idle socket to the pool, the test would incorrectly
5067 // pass.
Matt Menkee8648fa2019-01-17 16:47:075068 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5069 session
Matt Menked23ab952019-03-06 00:24:405070 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075071 HttpNetworkSession::NORMAL_SOCKET_POOL,
5072 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5073 SameProxyWithDifferentSchemesProxyResolver::
5074 ProxyHostPortPair()))
5075 ->IdleSocketCount());
5076 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5077 session
Matt Menked23ab952019-03-06 00:24:405078 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075079 HttpNetworkSession::NORMAL_SOCKET_POOL,
5080 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5081 SameProxyWithDifferentSchemesProxyResolver::
5082 ProxyHostPortPair()))
5083 ->IdleSocketCount());
5084 EXPECT_EQ(test_case.expected_idle_http_sockets,
5085 session
Matt Menked23ab952019-03-06 00:24:405086 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075087 HttpNetworkSession::NORMAL_SOCKET_POOL,
5088 ProxyServer(ProxyServer::SCHEME_HTTP,
5089 SameProxyWithDifferentSchemesProxyResolver::
5090 ProxyHostPortPair()))
5091 ->IdleSocketCount());
5092 EXPECT_EQ(test_case.expected_idle_https_sockets,
5093 session
Matt Menked23ab952019-03-06 00:24:405094 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075095 HttpNetworkSession::NORMAL_SOCKET_POOL,
5096 ProxyServer(ProxyServer::SCHEME_HTTPS,
5097 SameProxyWithDifferentSchemesProxyResolver::
5098 ProxyHostPortPair()))
5099 ->IdleSocketCount());
5100 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5101 session
Matt Menked23ab952019-03-06 00:24:405102 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075103 HttpNetworkSession::NORMAL_SOCKET_POOL,
5104 ProxyServer(ProxyServer::SCHEME_HTTPS,
5105 SameProxyWithDifferentSchemesProxyResolver::
5106 ProxyHostPortPair(),
5107 true /* is_trusted_proxy */))
5108 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065109 }
5110}
5111
[email protected]029c83b62013-01-24 05:28:205112// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015113TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205114 HttpRequestInfo request1;
5115 request1.method = "GET";
bncce36dca22015-04-21 22:11:235116 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:105117 request1.traffic_annotation =
5118 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205119
5120 HttpRequestInfo request2;
5121 request2.method = "GET";
bncce36dca22015-04-21 22:11:235122 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:105123 request2.traffic_annotation =
5124 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205125
5126 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495127 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5128 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515129 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075130 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095131 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205132
5133 // Since we have proxy, should try to establish tunnel.
5134 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175135 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5136 "Host: www.example.org:443\r\n"
5137 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205138
rsleevidb16bb02015-11-12 23:47:175139 MockWrite("GET /1 HTTP/1.1\r\n"
5140 "Host: www.example.org\r\n"
5141 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205142
rsleevidb16bb02015-11-12 23:47:175143 MockWrite("GET /2 HTTP/1.1\r\n"
5144 "Host: www.example.org\r\n"
5145 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205146 };
5147
5148 // The proxy responds to the connect with a 407, using a persistent
5149 // connection.
5150 MockRead data_reads1[] = {
5151 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5152
5153 MockRead("HTTP/1.1 200 OK\r\n"),
5154 MockRead("Content-Length: 1\r\n\r\n"),
5155 MockRead(SYNCHRONOUS, "1"),
5156
5157 MockRead("HTTP/1.1 200 OK\r\n"),
5158 MockRead("Content-Length: 2\r\n\r\n"),
5159 MockRead(SYNCHRONOUS, "22"),
5160 };
5161
Ryan Sleevib8d7ea02018-05-07 20:01:015162 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075163 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205164 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075165 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205166
5167 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585168 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195169 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205170
5171 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015172 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205173
5174 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015175 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205176
5177 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525178 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475179 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525180 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205181 EXPECT_EQ(1, response1->headers->GetContentLength());
5182
5183 LoadTimingInfo load_timing_info1;
5184 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5185 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5186
5187 trans1.reset();
5188
5189 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585190 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195191 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205192
5193 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015194 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205195
5196 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015197 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205198
5199 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525200 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475201 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525202 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205203 EXPECT_EQ(2, response2->headers->GetContentLength());
5204
5205 LoadTimingInfo load_timing_info2;
5206 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5207 TestLoadTimingReused(load_timing_info2);
5208
5209 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5210
5211 trans2.reset();
5212 session->CloseAllConnections();
5213}
5214
5215// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015216TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205217 HttpRequestInfo request1;
5218 request1.method = "GET";
bncce36dca22015-04-21 22:11:235219 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:105220 request1.traffic_annotation =
5221 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205222
5223 HttpRequestInfo request2;
5224 request2.method = "GET";
bncce36dca22015-04-21 22:11:235225 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:105226 request2.traffic_annotation =
5227 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205228
5229 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595230 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495231 ProxyResolutionService::CreateFixedFromPacResult(
5232 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515233 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075234 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095235 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205236
5237 // Since we have proxy, should try to establish tunnel.
5238 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175239 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5240 "Host: www.example.org:443\r\n"
5241 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205242
rsleevidb16bb02015-11-12 23:47:175243 MockWrite("GET /1 HTTP/1.1\r\n"
5244 "Host: www.example.org\r\n"
5245 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205246
rsleevidb16bb02015-11-12 23:47:175247 MockWrite("GET /2 HTTP/1.1\r\n"
5248 "Host: www.example.org\r\n"
5249 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205250 };
5251
5252 // The proxy responds to the connect with a 407, using a persistent
5253 // connection.
5254 MockRead data_reads1[] = {
5255 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5256
5257 MockRead("HTTP/1.1 200 OK\r\n"),
5258 MockRead("Content-Length: 1\r\n\r\n"),
5259 MockRead(SYNCHRONOUS, "1"),
5260
5261 MockRead("HTTP/1.1 200 OK\r\n"),
5262 MockRead("Content-Length: 2\r\n\r\n"),
5263 MockRead(SYNCHRONOUS, "22"),
5264 };
5265
Ryan Sleevib8d7ea02018-05-07 20:01:015266 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075267 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205268 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205270
5271 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585272 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195273 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205274
5275 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015276 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205277
5278 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015279 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205280
5281 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525282 ASSERT_TRUE(response1);
5283 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205284 EXPECT_EQ(1, response1->headers->GetContentLength());
5285
5286 LoadTimingInfo load_timing_info1;
5287 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5288 TestLoadTimingNotReusedWithPac(load_timing_info1,
5289 CONNECT_TIMING_HAS_SSL_TIMES);
5290
5291 trans1.reset();
5292
5293 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585294 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195295 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205296
5297 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205299
5300 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015301 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205302
5303 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525304 ASSERT_TRUE(response2);
5305 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205306 EXPECT_EQ(2, response2->headers->GetContentLength());
5307
5308 LoadTimingInfo load_timing_info2;
5309 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5310 TestLoadTimingReusedWithPac(load_timing_info2);
5311
5312 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5313
5314 trans2.reset();
5315 session->CloseAllConnections();
5316}
5317
[email protected]2df19bb2010-08-25 20:13:465318// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015319TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275320 HttpRequestInfo request;
5321 request.method = "GET";
bncce36dca22015-04-21 22:11:235322 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105323 request.traffic_annotation =
5324 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275325
[email protected]2df19bb2010-08-25 20:13:465326 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495327 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5328 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515329 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075330 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095331 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:465332
[email protected]2df19bb2010-08-25 20:13:465333 // Since we have proxy, should use full url
5334 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235335 MockWrite(
5336 "GET http://www.example.org/ HTTP/1.1\r\n"
5337 "Host: www.example.org\r\n"
5338 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465339 };
5340
5341 MockRead data_reads1[] = {
5342 MockRead("HTTP/1.1 200 OK\r\n"),
5343 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5344 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065345 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465346 };
5347
Ryan Sleevib8d7ea02018-05-07 20:01:015348 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075349 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065350 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075351 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465352
[email protected]49639fa2011-12-20 23:22:415353 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465354
bnc691fda62016-08-12 00:43:165355 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505356
bnc691fda62016-08-12 00:43:165357 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465359
5360 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015361 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465362
[email protected]58e32bb2013-01-21 18:23:255363 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165364 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255365 TestLoadTimingNotReused(load_timing_info,
5366 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5367
bnc691fda62016-08-12 00:43:165368 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525369 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:465370
tbansal2ecbbc72016-10-06 17:15:475371 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:465372 EXPECT_TRUE(response->headers->IsKeepAlive());
5373 EXPECT_EQ(200, response->headers->response_code());
5374 EXPECT_EQ(100, response->headers->GetContentLength());
5375 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5376
5377 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585378 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:465379}
5380
[email protected]7642b5ae2010-09-01 20:55:175381// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015382TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275383 HttpRequestInfo request;
5384 request.method = "GET";
bncce36dca22015-04-21 22:11:235385 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105386 request.traffic_annotation =
5387 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275388
[email protected]7642b5ae2010-09-01 20:55:175389 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495390 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5391 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515392 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075393 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095394 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:175395
bncce36dca22015-04-21 22:11:235396 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135397 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455398 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415399 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:175400
Ryan Hamilton0239aac2018-05-19 00:03:135401 spdy::SpdySerializedFrame resp(
5402 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5403 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:175404 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415405 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:175406 };
5407
Ryan Sleevib8d7ea02018-05-07 20:01:015408 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075409 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:175410
[email protected]8ddf8322012-02-23 18:08:065411 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365412 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:175414
[email protected]49639fa2011-12-20 23:22:415415 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:175416
bnc691fda62016-08-12 00:43:165417 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505418
bnc691fda62016-08-12 00:43:165419 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015420 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:175421
5422 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015423 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:175424
[email protected]58e32bb2013-01-21 18:23:255425 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165426 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255427 TestLoadTimingNotReused(load_timing_info,
5428 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5429
bnc691fda62016-08-12 00:43:165430 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525431 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:475432 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:525433 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025434 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:175435
5436 std::string response_data;
bnc691fda62016-08-12 00:43:165437 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235438 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:175439}
5440
[email protected]1c173852014-06-19 12:51:505441// Verifies that a session which races and wins against the owning transaction
5442// (completing prior to host resolution), doesn't fail the transaction.
5443// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:015444TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:505445 HttpRequestInfo request;
5446 request.method = "GET";
bncce36dca22015-04-21 22:11:235447 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105448 request.traffic_annotation =
5449 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:505450
5451 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495452 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5453 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515454 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:505455 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095456 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:505457
bncce36dca22015-04-21 22:11:235458 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:135459 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455460 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415461 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:505462
Raul Tambre94493c652019-03-11 17:18:355463 spdy::SpdySerializedFrame resp(
5464 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135465 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:505466 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415467 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:505468 };
5469
Ryan Sleevib8d7ea02018-05-07 20:01:015470 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:505471 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5472
5473 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365474 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:505475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5476
5477 TestCompletionCallback callback1;
5478
bnc691fda62016-08-12 00:43:165479 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:505480
5481 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:505482 session_deps_.host_resolver->set_ondemand_mode(true);
5483
bnc691fda62016-08-12 00:43:165484 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015485 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:505486
5487 // Race a session to the proxy, which completes first.
5488 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:045489 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:115490 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:345491 SpdySessionKey::IsProxySession::kTrue, SocketTag(),
5492 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]1c173852014-06-19 12:51:505493 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:525494 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:505495
5496 // Unstall the resolution begun by the transaction.
5497 session_deps_.host_resolver->set_ondemand_mode(true);
5498 session_deps_.host_resolver->ResolveAllPending();
5499
5500 EXPECT_FALSE(callback1.have_result());
5501 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015502 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:505503
bnc691fda62016-08-12 00:43:165504 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525505 ASSERT_TRUE(response);
5506 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025507 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:505508
5509 std::string response_data;
bnc691fda62016-08-12 00:43:165510 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:505511 EXPECT_EQ(kUploadData, response_data);
5512}
5513
[email protected]dc7bd1c52010-11-12 00:01:135514// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015515TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:275516 HttpRequestInfo request;
5517 request.method = "GET";
bncce36dca22015-04-21 22:11:235518 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105519 request.traffic_annotation =
5520 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275521
[email protected]79cb5c12011-09-12 13:12:045522 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495523 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5524 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515525 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075526 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095527 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:135528
[email protected]dc7bd1c52010-11-12 00:01:135529 // The first request will be a bare GET, the second request will be a
5530 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:455531 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:135532 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:485533 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385534 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:135535 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465536 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:135537 };
Ryan Hamilton0239aac2018-05-19 00:03:135538 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:245539 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:485540 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:135541 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415542 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:135543 };
5544
5545 // The first response is a 407 proxy authentication challenge, and the second
5546 // response will be a 200 response since the second request includes a valid
5547 // Authorization header.
5548 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465549 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:135550 };
Ryan Hamilton0239aac2018-05-19 00:03:135551 spdy::SpdySerializedFrame resp_authentication(
5552 spdy_util_.ConstructSpdyReplyError(
5553 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:245554 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135555 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:415556 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135557 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:355558 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:135559 spdy::SpdySerializedFrame body_data(
5560 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:135561 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415562 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:465563 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415564 CreateMockRead(resp_data, 4),
5565 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:135566 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:135567 };
5568
Ryan Sleevib8d7ea02018-05-07 20:01:015569 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075570 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:135571
[email protected]8ddf8322012-02-23 18:08:065572 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365573 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075574 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:135575
[email protected]49639fa2011-12-20 23:22:415576 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:135577
bnc691fda62016-08-12 00:43:165578 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:135579
bnc691fda62016-08-12 00:43:165580 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015581 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135582
5583 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015584 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135585
bnc691fda62016-08-12 00:43:165586 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135587
wezca1070932016-05-26 20:30:525588 ASSERT_TRUE(response);
5589 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:135590 EXPECT_EQ(407, response->headers->response_code());
5591 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:585592 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:135593
[email protected]49639fa2011-12-20 23:22:415594 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:135595
bnc691fda62016-08-12 00:43:165596 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015597 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135598
5599 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015600 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135601
bnc691fda62016-08-12 00:43:165602 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135603
wezca1070932016-05-26 20:30:525604 ASSERT_TRUE(response_restart);
5605 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:135606 EXPECT_EQ(200, response_restart->headers->response_code());
5607 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585608 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:135609}
5610
[email protected]d9da5fe2010-10-13 22:37:165611// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:015612TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:275613 HttpRequestInfo request;
5614 request.method = "GET";
bncce36dca22015-04-21 22:11:235615 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105616 request.traffic_annotation =
5617 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275618
[email protected]d9da5fe2010-10-13 22:37:165619 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495620 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5621 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515622 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075623 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095624 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165625
bnc691fda62016-08-12 00:43:165626 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165627
bncce36dca22015-04-21 22:11:235628 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135629 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045630 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5631 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235632 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:165633
bncce36dca22015-04-21 22:11:235634 const char get[] =
5635 "GET / HTTP/1.1\r\n"
5636 "Host: www.example.org\r\n"
5637 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135638 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:195639 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:135640 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355641 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:165642 const char resp[] = "HTTP/1.1 200 OK\r\n"
5643 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135644 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:195645 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:135646 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:195647 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:135648 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:415649 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:045650
5651 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415652 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5653 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:045654 };
5655
[email protected]d9da5fe2010-10-13 22:37:165656 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415657 CreateMockRead(conn_resp, 1, ASYNC),
5658 CreateMockRead(wrapped_get_resp, 3, ASYNC),
5659 CreateMockRead(wrapped_body, 4, ASYNC),
5660 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135661 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:165662 };
5663
Ryan Sleevib8d7ea02018-05-07 20:01:015664 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075665 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165666
[email protected]8ddf8322012-02-23 18:08:065667 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365668 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075669 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065670 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075671 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165672
[email protected]49639fa2011-12-20 23:22:415673 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165674
bnc691fda62016-08-12 00:43:165675 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015676 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165677
5678 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015679 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165680
[email protected]58e32bb2013-01-21 18:23:255681 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165682 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255683 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5684
bnc691fda62016-08-12 00:43:165685 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525686 ASSERT_TRUE(response);
5687 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:165688 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5689
5690 std::string response_data;
bnc691fda62016-08-12 00:43:165691 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:165692 EXPECT_EQ("1234567890", response_data);
5693}
5694
5695// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:015696TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
5697 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:385698
[email protected]cb9bf6ca2011-01-28 13:15:275699 HttpRequestInfo request;
5700 request.method = "GET";
bncce36dca22015-04-21 22:11:235701 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105702 request.traffic_annotation =
5703 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275704
[email protected]d9da5fe2010-10-13 22:37:165705 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495706 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5707 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515708 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075709 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095710 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165711
bnc691fda62016-08-12 00:43:165712 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165713
bncce36dca22015-04-21 22:11:235714 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135715 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045716 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5717 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235718 // fetch https://www.example.org/ via SPDY
5719 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:135720 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:495721 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135722 spdy::SpdySerializedFrame wrapped_get(
5723 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
5724 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355725 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135726 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355727 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135728 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:025729 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135730 spdy::SpdySerializedFrame body(
5731 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
5732 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:025733 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135734 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:415735 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:135736 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:415737 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:045738
5739 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415740 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5741 CreateMockWrite(window_update_get_resp, 6),
5742 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:045743 };
5744
[email protected]d9da5fe2010-10-13 22:37:165745 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415746 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:095747 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:415748 CreateMockRead(wrapped_get_resp, 4, ASYNC),
5749 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135750 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:165751 };
5752
Ryan Sleevib8d7ea02018-05-07 20:01:015753 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075754 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165755
[email protected]8ddf8322012-02-23 18:08:065756 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365757 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075758 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065759 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365760 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075761 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165762
[email protected]49639fa2011-12-20 23:22:415763 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165764
bnc691fda62016-08-12 00:43:165765 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015766 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165767
rch32320842015-05-16 15:57:095768 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:555769 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:095770 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:595771 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:165772 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015773 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165774
[email protected]58e32bb2013-01-21 18:23:255775 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165776 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255777 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5778
bnc691fda62016-08-12 00:43:165779 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525780 ASSERT_TRUE(response);
5781 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025782 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:165783
5784 std::string response_data;
bnc691fda62016-08-12 00:43:165785 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235786 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:165787}
5788
5789// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015790TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:275791 HttpRequestInfo request;
5792 request.method = "GET";
bncce36dca22015-04-21 22:11:235793 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105794 request.traffic_annotation =
5795 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275796
[email protected]d9da5fe2010-10-13 22:37:165797 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495798 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5799 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515800 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075801 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095802 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165803
bnc691fda62016-08-12 00:43:165804 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165805
bncce36dca22015-04-21 22:11:235806 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135807 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045808 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5809 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:135810 spdy::SpdySerializedFrame get(
5811 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:165812
5813 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415814 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:165815 };
5816
Ryan Hamilton0239aac2018-05-19 00:03:135817 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
5818 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:165819 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415820 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:165821 };
5822
Ryan Sleevib8d7ea02018-05-07 20:01:015823 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075824 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165825
[email protected]8ddf8322012-02-23 18:08:065826 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365827 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075828 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065829 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365830 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075831 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165832
[email protected]49639fa2011-12-20 23:22:415833 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165834
bnc691fda62016-08-12 00:43:165835 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015836 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165837
5838 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015839 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:165840
ttuttle960fcbf2016-04-19 13:26:325841 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:165842}
5843
Matt Menkecb2cd0982018-12-19 17:54:045844// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:245845// is observed, but does exist by the time auth credentials are provided. In
5846// this case, auth and SSL are fully negotated on the second request, but then
5847// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:045848TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
5849 ProxyConfig proxy_config;
5850 proxy_config.set_auto_detect(true);
5851 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
5852
5853 CapturingProxyResolver capturing_proxy_resolver;
5854 capturing_proxy_resolver.set_proxy_server(
5855 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
5856 session_deps_.proxy_resolution_service =
5857 std::make_unique<ProxyResolutionService>(
5858 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5859 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
5860 std::make_unique<CapturingProxyResolverFactory>(
5861 &capturing_proxy_resolver),
5862 nullptr);
5863
5864 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5865
5866 const char kMyUrl[] = "https://www.example.org/";
5867 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
5868 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355869 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:045870 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5871
5872 spdy_util_.UpdateWithStreamDestruction(1);
5873 spdy::SpdySerializedFrame get2(
5874 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
5875 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:355876 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:045877 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
5878
5879 MockWrite auth_challenge_writes[] = {
5880 MockWrite(ASYNC, 0,
5881 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5882 "Host: www.example.org:443\r\n"
5883 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:245884 MockWrite(ASYNC, 2,
5885 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5886 "Host: www.example.org:443\r\n"
5887 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:045888 };
5889
5890 MockRead auth_challenge_reads[] = {
5891 MockRead(ASYNC, 1,
5892 "HTTP/1.1 407 Authentication Required\r\n"
5893 "Content-Length: 0\r\n"
5894 "Proxy-Connection: close\r\n"
5895 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
5896 };
5897
5898 MockWrite spdy_writes[] = {
5899 MockWrite(ASYNC, 0,
5900 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5901 "Host: www.example.org:443\r\n"
5902 "Proxy-Connection: keep-alive\r\n"
5903 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5904 CreateMockWrite(get, 2),
5905 CreateMockWrite(get2, 5),
5906 };
5907
5908 MockRead spdy_reads[] = {
5909 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5910 CreateMockRead(get_resp, 3, ASYNC),
5911 CreateMockRead(body, 4, ASYNC),
5912 CreateMockRead(get_resp2, 6, ASYNC),
5913 CreateMockRead(body2, 7, ASYNC),
5914
5915 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
5916 };
5917
Matt Menke5062be22019-05-01 17:50:245918 MockWrite auth_response_writes_discarded_socket[] = {
5919 MockWrite(ASYNC, 0,
5920 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5921 "Host: www.example.org:443\r\n"
5922 "Proxy-Connection: keep-alive\r\n"
5923 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5924 };
5925
5926 MockRead auth_response_reads_discarded_socket[] = {
5927 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5928 };
5929
Matt Menkecb2cd0982018-12-19 17:54:045930 SequencedSocketData auth_challenge1(auth_challenge_reads,
5931 auth_challenge_writes);
5932 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
5933
5934 SequencedSocketData auth_challenge2(auth_challenge_reads,
5935 auth_challenge_writes);
5936 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
5937
5938 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
5939 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5940
Matt Menke5062be22019-05-01 17:50:245941 SequencedSocketData auth_response_discarded_socket(
5942 auth_response_reads_discarded_socket,
5943 auth_response_writes_discarded_socket);
5944 session_deps_.socket_factory->AddSocketDataProvider(
5945 &auth_response_discarded_socket);
5946
Matt Menkecb2cd0982018-12-19 17:54:045947 SSLSocketDataProvider ssl(ASYNC, OK);
5948 ssl.next_proto = kProtoHTTP2;
5949 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5950
Matt Menke5062be22019-05-01 17:50:245951 SSLSocketDataProvider ssl2(ASYNC, OK);
5952 ssl2.next_proto = kProtoHTTP2;
5953 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5954
Matt Menkecb2cd0982018-12-19 17:54:045955 TestCompletionCallback callback;
5956 std::string response_data;
5957
5958 // Run first request until an auth challenge is observed.
5959 HttpRequestInfo request1;
5960 request1.method = "GET";
5961 request1.url = GURL(kMyUrl);
5962 request1.traffic_annotation =
5963 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5964 HttpNetworkTransaction trans1(LOWEST, session.get());
5965 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
5966 EXPECT_THAT(callback.GetResult(rv), IsOk());
5967 const HttpResponseInfo* response = trans1.GetResponseInfo();
5968 ASSERT_TRUE(response);
5969 ASSERT_TRUE(response->headers);
5970 EXPECT_EQ(407, response->headers->response_code());
5971 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:585972 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:045973
5974 // Run second request until an auth challenge is observed.
5975 HttpRequestInfo request2;
5976 request2.method = "GET";
5977 request2.url = GURL(kMyUrl);
5978 request2.traffic_annotation =
5979 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5980 HttpNetworkTransaction trans2(LOWEST, session.get());
5981 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
5982 EXPECT_THAT(callback.GetResult(rv), IsOk());
5983 response = trans2.GetResponseInfo();
5984 ASSERT_TRUE(response);
5985 ASSERT_TRUE(response->headers);
5986 EXPECT_EQ(407, response->headers->response_code());
5987 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:585988 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:045989
5990 // Now provide credentials for the first request, and wait for it to complete.
5991 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
5992 rv = callback.GetResult(rv);
5993 EXPECT_THAT(rv, IsOk());
5994 response = trans1.GetResponseInfo();
5995 ASSERT_TRUE(response);
5996 ASSERT_TRUE(response->headers);
5997 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
5998 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
5999 EXPECT_EQ(kUploadData, response_data);
6000
6001 // Now provide credentials for the second request. It should notice the
6002 // existing session, and reuse it.
6003 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6004 EXPECT_THAT(callback.GetResult(rv), IsOk());
6005 response = trans2.GetResponseInfo();
6006 ASSERT_TRUE(response);
6007 ASSERT_TRUE(response->headers);
6008 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6009 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6010 EXPECT_EQ(kUploadData, response_data);
6011}
6012
[email protected]f6c63db52013-02-02 00:35:226013// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6014// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016015TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226016 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6017 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496018 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6019 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516020 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076021 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096022 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506023 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226024
6025 HttpRequestInfo request1;
6026 request1.method = "GET";
bncce36dca22015-04-21 22:11:236027 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226028 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106029 request1.traffic_annotation =
6030 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226031
6032 HttpRequestInfo request2;
6033 request2.method = "GET";
bncce36dca22015-04-21 22:11:236034 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226035 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106036 request2.traffic_annotation =
6037 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226038
bncce36dca22015-04-21 22:11:236039 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136040 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046041 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6042 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136043 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356044 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226045
bncce36dca22015-04-21 22:11:236046 // Fetch https://www.example.org/ via HTTP.
6047 const char get1[] =
6048 "GET / HTTP/1.1\r\n"
6049 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226050 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136051 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196052 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226053 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6054 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136055 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196056 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136057 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196058 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136059 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416060 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226061
bncce36dca22015-04-21 22:11:236062 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136063 spdy::SpdyHeaderBlock connect2_block;
6064 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6065 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6066 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046067 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6068 false));
[email protected]601e03f12014-04-06 16:26:396069
Ryan Hamilton0239aac2018-05-19 00:03:136070 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356071 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226072
bncce36dca22015-04-21 22:11:236073 // Fetch https://mail.example.org/ via HTTP.
6074 const char get2[] =
6075 "GET / HTTP/1.1\r\n"
6076 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226077 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136078 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196079 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226080 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6081 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136082 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196083 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136084 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196085 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226086
6087 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416088 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6089 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226090 };
6091
6092 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416093 CreateMockRead(conn_resp1, 1, ASYNC),
6094 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6095 CreateMockRead(wrapped_body1, 4, ASYNC),
6096 CreateMockRead(conn_resp2, 6, ASYNC),
6097 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6098 CreateMockRead(wrapped_body2, 9, ASYNC),
6099 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226100 };
6101
Ryan Sleevib8d7ea02018-05-07 20:01:016102 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506103 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226104
6105 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366106 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506107 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226108 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506109 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226110 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506111 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226112
6113 TestCompletionCallback callback;
6114
bnc691fda62016-08-12 00:43:166115 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206116 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016117 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226118
6119 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166120 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226121 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6122
bnc691fda62016-08-12 00:43:166123 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526124 ASSERT_TRUE(response);
6125 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226126 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6127
6128 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446129 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166130 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506131 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226132
bnc691fda62016-08-12 00:43:166133 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206134 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016135 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226136
6137 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166138 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226139 // Even though the SPDY connection is reused, a new tunnelled connection has
6140 // to be created, so the socket's load timing looks like a fresh connection.
6141 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6142
6143 // The requests should have different IDs, since they each are using their own
6144 // separate stream.
6145 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6146
bnc691fda62016-08-12 00:43:166147 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506148 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226149}
6150
6151// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6152// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016153TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226154 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6155 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496156 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6157 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516158 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076159 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096160 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506161 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226162
6163 HttpRequestInfo request1;
6164 request1.method = "GET";
bncce36dca22015-04-21 22:11:236165 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226166 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106167 request1.traffic_annotation =
6168 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226169
6170 HttpRequestInfo request2;
6171 request2.method = "GET";
bncce36dca22015-04-21 22:11:236172 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226173 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106174 request2.traffic_annotation =
6175 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226176
bncce36dca22015-04-21 22:11:236177 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136178 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046179 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6180 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136181 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356182 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226183
bncce36dca22015-04-21 22:11:236184 // Fetch https://www.example.org/ via HTTP.
6185 const char get1[] =
6186 "GET / HTTP/1.1\r\n"
6187 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226188 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136189 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196190 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226191 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6192 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136193 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196194 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136195 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196196 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136197 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416198 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226199
bncce36dca22015-04-21 22:11:236200 // Fetch https://www.example.org/2 via HTTP.
6201 const char get2[] =
6202 "GET /2 HTTP/1.1\r\n"
6203 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226204 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136205 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196206 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226207 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6208 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136209 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196210 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136211 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196212 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226213
6214 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416215 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6216 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226217 };
6218
6219 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416220 CreateMockRead(conn_resp1, 1, ASYNC),
6221 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466222 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416223 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466224 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416225 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226226 };
6227
Ryan Sleevib8d7ea02018-05-07 20:01:016228 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506229 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226230
6231 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366232 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506233 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226234 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506235 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226236
6237 TestCompletionCallback callback;
6238
bnc87dcefc2017-05-25 12:47:586239 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196240 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206241 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016242 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226243
6244 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016245 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226246
6247 LoadTimingInfo load_timing_info;
6248 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6249 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6250
6251 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526252 ASSERT_TRUE(response);
6253 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226254 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6255
6256 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446257 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506258 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226259 trans.reset();
6260
bnc87dcefc2017-05-25 12:47:586261 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196262 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206263 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016264 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226265
[email protected]f6c63db52013-02-02 00:35:226266 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016267 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226268
6269 LoadTimingInfo load_timing_info2;
6270 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6271 TestLoadTimingReused(load_timing_info2);
6272
6273 // The requests should have the same ID.
6274 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6275
[email protected]90499482013-06-01 00:39:506276 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226277}
6278
6279// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6280// Proxy to different servers.
bncd16676a2016-07-20 16:23:016281TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226282 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496283 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6284 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516285 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076286 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096287 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506288 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226289
6290 HttpRequestInfo request1;
6291 request1.method = "GET";
bncce36dca22015-04-21 22:11:236292 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226293 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106294 request1.traffic_annotation =
6295 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226296
6297 HttpRequestInfo request2;
6298 request2.method = "GET";
bncce36dca22015-04-21 22:11:236299 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226300 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106301 request2.traffic_annotation =
6302 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226303
bncce36dca22015-04-21 22:11:236304 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136305 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236306 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136307 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156308 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136309 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356310 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136311 spdy::SpdySerializedFrame body1(
6312 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386313 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226314
bncce36dca22015-04-21 22:11:236315 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136316 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:236317 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136318 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:156319 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136320 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356321 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136322 spdy::SpdySerializedFrame body2(
6323 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:226324
6325 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416326 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:226327 };
6328
6329 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416330 CreateMockRead(get_resp1, 1, ASYNC),
6331 CreateMockRead(body1, 2, ASYNC),
6332 CreateMockRead(get_resp2, 4, ASYNC),
6333 CreateMockRead(body2, 5, ASYNC),
6334 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:226335 };
6336
Ryan Sleevib8d7ea02018-05-07 20:01:016337 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506338 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226339
6340 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366341 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506342 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226343
6344 TestCompletionCallback callback;
6345
bnc87dcefc2017-05-25 12:47:586346 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196347 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206348 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016349 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226350
6351 LoadTimingInfo load_timing_info;
6352 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6353 TestLoadTimingNotReused(load_timing_info,
6354 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6355
6356 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526357 ASSERT_TRUE(response);
6358 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026359 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:226360
6361 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446362 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:506363 rv = trans->Read(buf.get(), 256, callback.callback());
6364 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226365 // Delete the first request, so the second one can reuse the socket.
6366 trans.reset();
6367
bnc691fda62016-08-12 00:43:166368 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206369 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016370 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226371
6372 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166373 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226374 TestLoadTimingReused(load_timing_info2);
6375
6376 // The requests should have the same ID.
6377 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6378
bnc691fda62016-08-12 00:43:166379 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506380 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226381}
6382
Matt Menke2436b2f2018-12-11 18:07:116383// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
6384// direct (non-proxied) request to the proxy server are not pooled, as that
6385// would break socket pool isolation.
6386TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
6387 ProxyConfig proxy_config;
6388 proxy_config.set_auto_detect(true);
6389 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6390
6391 CapturingProxyResolver capturing_proxy_resolver;
6392 session_deps_.proxy_resolution_service =
6393 std::make_unique<ProxyResolutionService>(
6394 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6395 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6396 std::make_unique<CapturingProxyResolverFactory>(
6397 &capturing_proxy_resolver),
6398 nullptr);
6399
6400 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6401
6402 SpdyTestUtil spdy_util1;
6403 // CONNECT to www.example.org:443 via HTTP/2.
6404 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046405 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6406 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116407 // fetch https://www.example.org/ via HTTP/2.
6408 const char kMyUrl[] = "https://www.example.org/";
6409 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6410 spdy::SpdySerializedFrame wrapped_get(
6411 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6412 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356413 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116414 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356415 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116416 spdy::SpdySerializedFrame wrapped_get_resp(
6417 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6418 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
6419 spdy::SpdySerializedFrame wrapped_body(
6420 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6421 spdy::SpdySerializedFrame window_update_get_resp(
6422 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6423 spdy::SpdySerializedFrame window_update_body(
6424 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6425
6426 MockWrite spdy_writes1[] = {
6427 CreateMockWrite(connect, 0),
6428 CreateMockWrite(wrapped_get, 2),
6429 CreateMockWrite(window_update_get_resp, 6),
6430 CreateMockWrite(window_update_body, 7),
6431 };
6432
6433 MockRead spdy_reads1[] = {
6434 CreateMockRead(conn_resp, 1, ASYNC),
6435 MockRead(ASYNC, ERR_IO_PENDING, 3),
6436 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6437 CreateMockRead(wrapped_body, 5, ASYNC),
6438 MockRead(ASYNC, 0, 8),
6439 };
6440
6441 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6442 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6443
6444 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
6445 // a new pipe.
6446 SpdyTestUtil spdy_util2;
6447 spdy::SpdySerializedFrame req(
6448 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6449 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
6450
6451 spdy::SpdySerializedFrame resp(
6452 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6453 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
6454 MockRead spdy_reads2[] = {
6455 CreateMockRead(resp, 1),
6456 CreateMockRead(data, 2),
6457 MockRead(ASYNC, 0, 3),
6458 };
6459 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6460 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6461
6462 SSLSocketDataProvider ssl(ASYNC, OK);
6463 ssl.next_proto = kProtoHTTP2;
6464 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6465 SSLSocketDataProvider ssl2(ASYNC, OK);
6466 ssl2.next_proto = kProtoHTTP2;
6467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6468 SSLSocketDataProvider ssl3(ASYNC, OK);
6469 ssl3.next_proto = kProtoHTTP2;
6470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6471
6472 TestCompletionCallback callback;
6473 std::string response_data;
6474
6475 // Make a request using proxy:70 as a HTTP/2 proxy.
6476 capturing_proxy_resolver.set_proxy_server(
6477 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6478 HttpRequestInfo request1;
6479 request1.method = "GET";
6480 request1.url = GURL("https://www.example.org/");
6481 request1.traffic_annotation =
6482 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6483
6484 HttpNetworkTransaction trans1(LOWEST, session.get());
6485 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6486 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6487
6488 // Allow the SpdyProxyClientSocket's write callback to complete.
6489 base::RunLoop().RunUntilIdle();
6490 // Now allow the read of the response to complete.
6491 spdy_data1.Resume();
6492 rv = callback.WaitForResult();
6493 EXPECT_THAT(rv, IsOk());
6494
6495 const HttpResponseInfo* response = trans1.GetResponseInfo();
6496 ASSERT_TRUE(response);
6497 ASSERT_TRUE(response->headers);
6498 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6499
6500 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6501 EXPECT_EQ(kUploadData, response_data);
6502 RunUntilIdle();
6503
6504 // Make a direct HTTP/2 request to proxy:70.
6505 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6506 HttpRequestInfo request2;
6507 request2.method = "GET";
6508 request2.url = GURL("https://proxy:70/");
6509 request2.traffic_annotation =
6510 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6511 HttpNetworkTransaction trans2(LOWEST, session.get());
6512 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
6513 NetLogWithSource())),
6514 IsOk());
6515 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6516}
6517
6518// Same as above, but reverse request order, since the code to check for an
6519// existing session is different for tunnels and direct connections.
6520TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
6521 // Configure against https proxy server "myproxy:80".
6522 ProxyConfig proxy_config;
6523 proxy_config.set_auto_detect(true);
6524 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6525
6526 CapturingProxyResolver capturing_proxy_resolver;
6527 session_deps_.proxy_resolution_service =
6528 std::make_unique<ProxyResolutionService>(
6529 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6530 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6531 std::make_unique<CapturingProxyResolverFactory>(
6532 &capturing_proxy_resolver),
6533 nullptr);
6534
6535 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6536 // Fetch https://proxy:70/ via HTTP/2.
6537 SpdyTestUtil spdy_util1;
6538 spdy::SpdySerializedFrame req(
6539 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6540 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
6541
6542 spdy::SpdySerializedFrame resp(
6543 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
6544 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
6545 MockRead spdy_reads1[] = {
6546 CreateMockRead(resp, 1),
6547 CreateMockRead(data, 2),
6548 MockRead(ASYNC, 0, 3),
6549 };
6550 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6551 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6552
6553 SpdyTestUtil spdy_util2;
6554 // CONNECT to www.example.org:443 via HTTP/2.
6555 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046556 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6557 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116558 // fetch https://www.example.org/ via HTTP/2.
6559 const char kMyUrl[] = "https://www.example.org/";
6560 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6561 spdy::SpdySerializedFrame wrapped_get(
6562 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6563 spdy::SpdySerializedFrame conn_resp(
6564 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6565 spdy::SpdySerializedFrame get_resp(
6566 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6567 spdy::SpdySerializedFrame wrapped_get_resp(
6568 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6569 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
6570 spdy::SpdySerializedFrame wrapped_body(
6571 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6572 spdy::SpdySerializedFrame window_update_get_resp(
6573 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6574 spdy::SpdySerializedFrame window_update_body(
6575 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6576
6577 MockWrite spdy_writes2[] = {
6578 CreateMockWrite(connect, 0),
6579 CreateMockWrite(wrapped_get, 2),
6580 CreateMockWrite(window_update_get_resp, 6),
6581 CreateMockWrite(window_update_body, 7),
6582 };
6583
6584 MockRead spdy_reads2[] = {
6585 CreateMockRead(conn_resp, 1, ASYNC),
6586 MockRead(ASYNC, ERR_IO_PENDING, 3),
6587 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6588 CreateMockRead(wrapped_body, 5, ASYNC),
6589 MockRead(ASYNC, 0, 8),
6590 };
6591
6592 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6593 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6594
6595 SSLSocketDataProvider ssl(ASYNC, OK);
6596 ssl.next_proto = kProtoHTTP2;
6597 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6598 SSLSocketDataProvider ssl2(ASYNC, OK);
6599 ssl2.next_proto = kProtoHTTP2;
6600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6601 SSLSocketDataProvider ssl3(ASYNC, OK);
6602 ssl3.next_proto = kProtoHTTP2;
6603 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6604
6605 TestCompletionCallback callback;
6606 std::string response_data;
6607
6608 // Make a direct HTTP/2 request to proxy:70.
6609 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6610 HttpRequestInfo request1;
6611 request1.method = "GET";
6612 request1.url = GURL("https://proxy:70/");
6613 request1.traffic_annotation =
6614 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6615 HttpNetworkTransaction trans1(LOWEST, session.get());
6616 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
6617 NetLogWithSource())),
6618 IsOk());
6619 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6620 RunUntilIdle();
6621
6622 // Make a request using proxy:70 as a HTTP/2 proxy.
6623 capturing_proxy_resolver.set_proxy_server(
6624 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6625 HttpRequestInfo request2;
6626 request2.method = "GET";
6627 request2.url = GURL("https://www.example.org/");
6628 request2.traffic_annotation =
6629 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6630
6631 HttpNetworkTransaction trans2(LOWEST, session.get());
6632 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6633 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6634
6635 // Allow the SpdyProxyClientSocket's write callback to complete.
6636 base::RunLoop().RunUntilIdle();
6637 // Now allow the read of the response to complete.
6638 spdy_data2.Resume();
6639 rv = callback.WaitForResult();
6640 EXPECT_THAT(rv, IsOk());
6641
6642 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
6643 ASSERT_TRUE(response2);
6644 ASSERT_TRUE(response2->headers);
6645 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
6646
6647 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6648 EXPECT_EQ(kUploadData, response_data);
6649}
6650
[email protected]2df19bb2010-08-25 20:13:466651// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:016652TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:466653 HttpRequestInfo request;
6654 request.method = "GET";
bncce36dca22015-04-21 22:11:236655 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:466656 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:296657 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:106658 request.traffic_annotation =
6659 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:466660
[email protected]79cb5c12011-09-12 13:12:046661 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496662 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6663 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516664 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076665 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096666 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276667
[email protected]2df19bb2010-08-25 20:13:466668 // Since we have proxy, should use full url
6669 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:166670 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6671 "Host: www.example.org\r\n"
6672 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466673
bnc691fda62016-08-12 00:43:166674 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:236675 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:166676 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6677 "Host: www.example.org\r\n"
6678 "Proxy-Connection: keep-alive\r\n"
6679 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466680 };
6681
6682 // The proxy responds to the GET with a 407, using a persistent
6683 // connection.
6684 MockRead data_reads1[] = {
6685 // No credentials.
6686 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6687 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6688 MockRead("Proxy-Connection: keep-alive\r\n"),
6689 MockRead("Content-Length: 0\r\n\r\n"),
6690
6691 MockRead("HTTP/1.1 200 OK\r\n"),
6692 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6693 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066694 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466695 };
6696
Ryan Sleevib8d7ea02018-05-07 20:01:016697 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076698 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066699 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076700 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466701
[email protected]49639fa2011-12-20 23:22:416702 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466703
bnc691fda62016-08-12 00:43:166704 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506705
bnc691fda62016-08-12 00:43:166706 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016707 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466708
6709 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016710 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466711
[email protected]58e32bb2013-01-21 18:23:256712 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166713 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256714 TestLoadTimingNotReused(load_timing_info,
6715 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6716
bnc691fda62016-08-12 00:43:166717 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526718 ASSERT_TRUE(response);
6719 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:466720 EXPECT_EQ(407, response->headers->response_code());
6721 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586722 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:506723 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466724
[email protected]49639fa2011-12-20 23:22:416725 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:466726
bnc691fda62016-08-12 00:43:166727 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016728 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466729
6730 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016731 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466732
[email protected]58e32bb2013-01-21 18:23:256733 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:166734 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256735 // Retrying with HTTP AUTH is considered to be reusing a socket.
6736 TestLoadTimingReused(load_timing_info);
6737
bnc691fda62016-08-12 00:43:166738 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526739 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466740
6741 EXPECT_TRUE(response->headers->IsKeepAlive());
6742 EXPECT_EQ(200, response->headers->response_code());
6743 EXPECT_EQ(100, response->headers->GetContentLength());
6744 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:506745 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466746
6747 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586748 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466749}
6750
[email protected]23e482282013-06-14 16:08:026751void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:086752 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:426753 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:086754 request.method = "GET";
bncce36dca22015-04-21 22:11:236755 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106756 request.traffic_annotation =
6757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:086758
[email protected]cb9bf6ca2011-01-28 13:15:276759 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496760 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6761 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096762 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276763
[email protected]c744cf22009-02-27 07:28:086764 // Since we have proxy, should try to establish tunnel.
6765 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:176766 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6767 "Host: www.example.org:443\r\n"
6768 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:086769 };
6770
6771 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:236772 status, MockRead("Content-Length: 10\r\n\r\n"),
6773 // No response body because the test stops reading here.
6774 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:086775 };
6776
Ryan Sleevib8d7ea02018-05-07 20:01:016777 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:076778 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:086779
[email protected]49639fa2011-12-20 23:22:416780 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:086781
bnc691fda62016-08-12 00:43:166782 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506783
tfarina42834112016-09-22 13:38:206784 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016785 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:086786
6787 rv = callback.WaitForResult();
6788 EXPECT_EQ(expected_status, rv);
6789}
6790
[email protected]23e482282013-06-14 16:08:026791void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:236792 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:086793 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:426794 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:086795}
6796
bncd16676a2016-07-20 16:23:016797TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:086798 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
6799}
6800
bncd16676a2016-07-20 16:23:016801TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:086802 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
6803}
6804
bncd16676a2016-07-20 16:23:016805TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:086806 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
6807}
6808
bncd16676a2016-07-20 16:23:016809TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:086810 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
6811}
6812
bncd16676a2016-07-20 16:23:016813TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:086814 ConnectStatusHelper(
6815 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
6816}
6817
bncd16676a2016-07-20 16:23:016818TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:086819 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
6820}
6821
bncd16676a2016-07-20 16:23:016822TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:086823 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
6824}
6825
bncd16676a2016-07-20 16:23:016826TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:086827 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
6828}
6829
bncd16676a2016-07-20 16:23:016830TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:086831 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
6832}
6833
bncd16676a2016-07-20 16:23:016834TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:086835 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
6836}
6837
bncd16676a2016-07-20 16:23:016838TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:086839 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
6840}
6841
bncd16676a2016-07-20 16:23:016842TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:086843 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
6844}
6845
bncd16676a2016-07-20 16:23:016846TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:086847 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
6848}
6849
bncd16676a2016-07-20 16:23:016850TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:086851 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
6852}
6853
bncd16676a2016-07-20 16:23:016854TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:086855 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
6856}
6857
bncd16676a2016-07-20 16:23:016858TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:086859 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
6860}
6861
bncd16676a2016-07-20 16:23:016862TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:376863 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
6864}
6865
bncd16676a2016-07-20 16:23:016866TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:086867 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
6868}
6869
bncd16676a2016-07-20 16:23:016870TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:086871 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
6872}
6873
bncd16676a2016-07-20 16:23:016874TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:086875 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
6876}
6877
bncd16676a2016-07-20 16:23:016878TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:086879 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
6880}
6881
bncd16676a2016-07-20 16:23:016882TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:086883 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
6884}
6885
bncd16676a2016-07-20 16:23:016886TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:086887 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
6888}
6889
bncd16676a2016-07-20 16:23:016890TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:086891 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
6892}
6893
bncd16676a2016-07-20 16:23:016894TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:086895 ConnectStatusHelperWithExpectedStatus(
6896 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:546897 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:086898}
6899
bncd16676a2016-07-20 16:23:016900TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:086901 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
6902}
6903
bncd16676a2016-07-20 16:23:016904TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:086905 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
6906}
6907
bncd16676a2016-07-20 16:23:016908TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:086909 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
6910}
6911
bncd16676a2016-07-20 16:23:016912TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:086913 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
6914}
6915
bncd16676a2016-07-20 16:23:016916TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:086917 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
6918}
6919
bncd16676a2016-07-20 16:23:016920TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:086921 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
6922}
6923
bncd16676a2016-07-20 16:23:016924TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:086925 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
6926}
6927
bncd16676a2016-07-20 16:23:016928TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:086929 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
6930}
6931
bncd16676a2016-07-20 16:23:016932TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:086933 ConnectStatusHelper(
6934 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
6935}
6936
bncd16676a2016-07-20 16:23:016937TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:086938 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
6939}
6940
bncd16676a2016-07-20 16:23:016941TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:086942 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
6943}
6944
bncd16676a2016-07-20 16:23:016945TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:086946 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
6947}
6948
bncd16676a2016-07-20 16:23:016949TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:086950 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
6951}
6952
bncd16676a2016-07-20 16:23:016953TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:086954 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
6955}
6956
bncd16676a2016-07-20 16:23:016957TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:086958 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
6959}
6960
bncd16676a2016-07-20 16:23:016961TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:086962 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
6963}
6964
[email protected]038e9a32008-10-08 22:40:166965// Test the flow when both the proxy server AND origin server require
6966// authentication. Again, this uses basic auth for both since that is
6967// the simplest to mock.
bncd16676a2016-07-20 16:23:016968TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:276969 HttpRequestInfo request;
6970 request.method = "GET";
bncce36dca22015-04-21 22:11:236971 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106972 request.traffic_annotation =
6973 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276974
[email protected]038e9a32008-10-08 22:40:166975 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496976 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6977 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096978 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:076979
bnc691fda62016-08-12 00:43:166980 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:166981
[email protected]f9ee6b52008-11-08 06:46:236982 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236983 MockWrite(
6984 "GET http://www.example.org/ HTTP/1.1\r\n"
6985 "Host: www.example.org\r\n"
6986 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236987 };
6988
[email protected]038e9a32008-10-08 22:40:166989 MockRead data_reads1[] = {
6990 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
6991 // Give a couple authenticate options (only the middle one is actually
6992 // supported).
[email protected]22927ad2009-09-21 19:56:196993 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:166994 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6995 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
6996 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6997 // Large content-length -- won't matter, as connection will be reset.
6998 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066999 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167000 };
7001
bnc691fda62016-08-12 00:43:167002 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167003 // request we should be issuing -- the final header line contains the
7004 // proxy's credentials.
7005 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237006 MockWrite(
7007 "GET http://www.example.org/ HTTP/1.1\r\n"
7008 "Host: www.example.org\r\n"
7009 "Proxy-Connection: keep-alive\r\n"
7010 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167011 };
7012
7013 // Now the proxy server lets the request pass through to origin server.
7014 // The origin server responds with a 401.
7015 MockRead data_reads2[] = {
7016 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7017 // Note: We are using the same realm-name as the proxy server. This is
7018 // completely valid, as realms are unique across hosts.
7019 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7020 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7021 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067022 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167023 };
7024
bnc691fda62016-08-12 00:43:167025 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167026 // the credentials for both the proxy and origin server.
7027 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237028 MockWrite(
7029 "GET http://www.example.org/ HTTP/1.1\r\n"
7030 "Host: www.example.org\r\n"
7031 "Proxy-Connection: keep-alive\r\n"
7032 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7033 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167034 };
7035
7036 // Lastly we get the desired content.
7037 MockRead data_reads3[] = {
7038 MockRead("HTTP/1.0 200 OK\r\n"),
7039 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7040 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067041 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167042 };
7043
Ryan Sleevib8d7ea02018-05-07 20:01:017044 StaticSocketDataProvider data1(data_reads1, data_writes1);
7045 StaticSocketDataProvider data2(data_reads2, data_writes2);
7046 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077047 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7048 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7049 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167050
[email protected]49639fa2011-12-20 23:22:417051 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167052
tfarina42834112016-09-22 13:38:207053 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167055
7056 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017057 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167058
bnc691fda62016-08-12 00:43:167059 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527060 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587061 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167062
[email protected]49639fa2011-12-20 23:22:417063 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167064
bnc691fda62016-08-12 00:43:167065 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017066 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167067
7068 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017069 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167070
bnc691fda62016-08-12 00:43:167071 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527072 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587073 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167074
[email protected]49639fa2011-12-20 23:22:417075 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167076
bnc691fda62016-08-12 00:43:167077 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7078 callback3.callback());
robpercival214763f2016-07-01 23:27:017079 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167080
7081 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017082 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167083
bnc691fda62016-08-12 00:43:167084 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587085 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167086 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167087}
[email protected]4ddaf2502008-10-23 18:26:197088
[email protected]ea9dc9a2009-09-05 00:43:327089// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7090// can't hook into its internals to cause it to generate predictable NTLM
7091// authorization headers.
7092#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377093// The NTLM authentication unit tests are based on known test data from the
7094// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7095// flow rather than the implementation of the NTLM protocol. See net/ntlm
7096// for the implementation and testing of the protocol.
7097//
7098// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297099
7100// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557101TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427102 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247103 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557104 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:107105 request.traffic_annotation =
7106 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547107
7108 // Ensure load is not disrupted by flags which suppress behaviour specific
7109 // to other auth schemes.
7110 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247111
Zentaro Kavanagh6ccee512017-09-28 18:34:097112 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7113 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097114 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277115
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377116 // Generate the NTLM messages based on known test data.
7117 std::string negotiate_msg;
7118 std::string challenge_msg;
7119 std::string authenticate_msg;
7120 base::Base64Encode(
7121 base::StringPiece(
7122 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247123 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377124 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557125 base::Base64Encode(
7126 base::StringPiece(
7127 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247128 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557129 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377130 base::Base64Encode(
7131 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097132 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557133 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247134 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557135 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377136 &authenticate_msg);
7137
[email protected]3f918782009-02-28 01:29:247138 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557139 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7140 "Host: server\r\n"
7141 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247142 };
7143
7144 MockRead data_reads1[] = {
7145 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047146 // Negotiate and NTLM are often requested together. However, we only want
7147 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7148 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247149 MockRead("WWW-Authenticate: NTLM\r\n"),
7150 MockRead("Connection: close\r\n"),
7151 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367152 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247153 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247154 };
7155
7156 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167157 // After restarting with a null identity, this is the
7158 // request we should be issuing -- the final header line contains a Type
7159 // 1 message.
7160 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557161 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167162 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377163 "Authorization: NTLM "),
7164 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247165
bnc691fda62016-08-12 00:43:167166 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377167 // (using correct credentials). The second request continues on the
7168 // same connection.
bnc691fda62016-08-12 00:43:167169 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557170 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167171 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377172 "Authorization: NTLM "),
7173 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247174 };
7175
7176 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027177 // The origin server responds with a Type 2 message.
7178 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377179 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7180 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027181 MockRead("Content-Type: text/html\r\n\r\n"),
7182 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247183
Bence Béky1e4ef192017-09-18 19:58:027184 // Lastly we get the desired content.
7185 MockRead("HTTP/1.1 200 OK\r\n"),
7186 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7187 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247188 };
7189
Ryan Sleevib8d7ea02018-05-07 20:01:017190 StaticSocketDataProvider data1(data_reads1, data_writes1);
7191 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077192 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7193 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247194
Bence Béky83eb3512017-09-05 12:56:097195 SSLSocketDataProvider ssl1(ASYNC, OK);
7196 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7197 SSLSocketDataProvider ssl2(ASYNC, OK);
7198 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7199
[email protected]49639fa2011-12-20 23:22:417200 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247201
bnc691fda62016-08-12 00:43:167202 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507203
tfarina42834112016-09-22 13:38:207204 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017205 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247206
7207 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017208 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247209
bnc691fda62016-08-12 00:43:167210 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227211
bnc691fda62016-08-12 00:43:167212 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527213 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587214 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247215
[email protected]49639fa2011-12-20 23:22:417216 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257217
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377218 rv = trans.RestartWithAuth(
7219 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7220 callback2.callback());
robpercival214763f2016-07-01 23:27:017221 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257222
7223 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017224 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257225
bnc691fda62016-08-12 00:43:167226 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257227
bnc691fda62016-08-12 00:43:167228 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527229 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587230 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257231
[email protected]49639fa2011-12-20 23:22:417232 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247233
bnc691fda62016-08-12 00:43:167234 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017235 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247236
[email protected]0757e7702009-03-27 04:00:227237 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017238 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247239
bnc691fda62016-08-12 00:43:167240 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527241 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587242 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027243 EXPECT_EQ(14, response->headers->GetContentLength());
7244
7245 std::string response_data;
7246 rv = ReadTransaction(&trans, &response_data);
7247 EXPECT_THAT(rv, IsOk());
7248 EXPECT_EQ("Please Login\r\n", response_data);
7249
7250 EXPECT_TRUE(data1.AllReadDataConsumed());
7251 EXPECT_TRUE(data1.AllWriteDataConsumed());
7252 EXPECT_TRUE(data2.AllReadDataConsumed());
7253 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247254}
7255
[email protected]385a4672009-03-11 22:21:297256// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557257TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427258 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297259 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557260 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:107261 request.traffic_annotation =
7262 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297263
Zentaro Kavanagh6ccee512017-09-28 18:34:097264 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7265 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097266 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277267
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377268 // Generate the NTLM messages based on known test data.
7269 std::string negotiate_msg;
7270 std::string challenge_msg;
7271 std::string authenticate_msg;
7272 base::Base64Encode(
7273 base::StringPiece(
7274 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247275 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377276 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557277 base::Base64Encode(
7278 base::StringPiece(
7279 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247280 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557281 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377282 base::Base64Encode(
7283 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097284 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557285 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247286 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557287 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377288 &authenticate_msg);
7289
7290 // The authenticate message when |kWrongPassword| is sent.
7291 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557292 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7293 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7294 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7295 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7296 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7297 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377298
Zentaro Kavanagh1890a3d2018-01-29 19:52:557299 // Sanity check that it's the same length as the correct authenticate message
7300 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377301 ASSERT_EQ(authenticate_msg.length(),
7302 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557303 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377304
[email protected]385a4672009-03-11 22:21:297305 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557306 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7307 "Host: server\r\n"
7308 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297309 };
7310
7311 MockRead data_reads1[] = {
7312 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047313 // Negotiate and NTLM are often requested together. However, we only want
7314 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7315 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:297316 MockRead("WWW-Authenticate: NTLM\r\n"),
7317 MockRead("Connection: close\r\n"),
7318 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367319 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297320 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297321 };
7322
7323 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167324 // After restarting with a null identity, this is the
7325 // request we should be issuing -- the final header line contains a Type
7326 // 1 message.
7327 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557328 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167329 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377330 "Authorization: NTLM "),
7331 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297332
bnc691fda62016-08-12 00:43:167333 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377334 // (using incorrect credentials). The second request continues on the
7335 // same connection.
bnc691fda62016-08-12 00:43:167336 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557337 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167338 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377339 "Authorization: NTLM "),
7340 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297341 };
7342
7343 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377344 // The origin server responds with a Type 2 message.
7345 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7346 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7347 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
7348 MockRead("Content-Type: text/html\r\n\r\n"),
7349 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297350
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377351 // Wrong password.
7352 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7353 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
7354 MockRead("Content-Length: 42\r\n"),
7355 MockRead("Content-Type: text/html\r\n\r\n"),
7356 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297357 };
7358
7359 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:167360 // After restarting with a null identity, this is the
7361 // request we should be issuing -- the final header line contains a Type
7362 // 1 message.
7363 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557364 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167365 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377366 "Authorization: NTLM "),
7367 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297368
bnc691fda62016-08-12 00:43:167369 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7370 // (the credentials for the origin server). The second request continues
7371 // on the same connection.
7372 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557373 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167374 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377375 "Authorization: NTLM "),
7376 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297377 };
7378
7379 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:027380 // The origin server responds with a Type 2 message.
7381 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377382 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7383 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027384 MockRead("Content-Type: text/html\r\n\r\n"),
7385 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297386
Bence Béky1e4ef192017-09-18 19:58:027387 // Lastly we get the desired content.
7388 MockRead("HTTP/1.1 200 OK\r\n"),
7389 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7390 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:297391 };
7392
Ryan Sleevib8d7ea02018-05-07 20:01:017393 StaticSocketDataProvider data1(data_reads1, data_writes1);
7394 StaticSocketDataProvider data2(data_reads2, data_writes2);
7395 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077396 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7397 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7398 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:297399
Bence Béky83eb3512017-09-05 12:56:097400 SSLSocketDataProvider ssl1(ASYNC, OK);
7401 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7402 SSLSocketDataProvider ssl2(ASYNC, OK);
7403 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7404 SSLSocketDataProvider ssl3(ASYNC, OK);
7405 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7406
[email protected]49639fa2011-12-20 23:22:417407 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:297408
bnc691fda62016-08-12 00:43:167409 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507410
tfarina42834112016-09-22 13:38:207411 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017412 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297413
7414 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017415 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297416
bnc691fda62016-08-12 00:43:167417 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:297418
bnc691fda62016-08-12 00:43:167419 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527420 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587421 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:297422
[email protected]49639fa2011-12-20 23:22:417423 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:297424
[email protected]0757e7702009-03-27 04:00:227425 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377426 rv = trans.RestartWithAuth(
7427 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
7428 callback2.callback());
robpercival214763f2016-07-01 23:27:017429 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297430
[email protected]10af5fe72011-01-31 16:17:257431 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017432 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297433
bnc691fda62016-08-12 00:43:167434 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417435 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:167436 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017437 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257438 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017439 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:167440 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227441
bnc691fda62016-08-12 00:43:167442 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527443 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587444 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:227445
[email protected]49639fa2011-12-20 23:22:417446 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:227447
7448 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377449 rv = trans.RestartWithAuth(
7450 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7451 callback4.callback());
robpercival214763f2016-07-01 23:27:017452 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257453
7454 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:017455 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257456
bnc691fda62016-08-12 00:43:167457 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257458
[email protected]49639fa2011-12-20 23:22:417459 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:257460
7461 // One more roundtrip
bnc691fda62016-08-12 00:43:167462 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:017463 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227464
7465 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:017466 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227467
bnc691fda62016-08-12 00:43:167468 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587469 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027470 EXPECT_EQ(14, response->headers->GetContentLength());
7471
7472 std::string response_data;
7473 rv = ReadTransaction(&trans, &response_data);
7474 EXPECT_THAT(rv, IsOk());
7475 EXPECT_EQ("Please Login\r\n", response_data);
7476
7477 EXPECT_TRUE(data1.AllReadDataConsumed());
7478 EXPECT_TRUE(data1.AllWriteDataConsumed());
7479 EXPECT_TRUE(data2.AllReadDataConsumed());
7480 EXPECT_TRUE(data2.AllWriteDataConsumed());
7481 EXPECT_TRUE(data3.AllReadDataConsumed());
7482 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:297483}
Bence Béky83eb3512017-09-05 12:56:097484
Bence Béky3238f2e12017-09-22 22:44:497485// Server requests NTLM authentication, which is not supported over HTTP/2.
7486// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:097487TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:097488 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7489 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:097490
Zentaro Kavanagh1890a3d2018-01-29 19:52:557491 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:097492
7493 HttpRequestInfo request;
7494 request.method = "GET";
7495 request.url = GURL(kUrl);
Ramin Halavatib5e433e2018-02-07 07:41:107496 request.traffic_annotation =
7497 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:097498
7499 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:137500 spdy::SpdyHeaderBlock request_headers0(
7501 spdy_util_.ConstructGetHeaderBlock(kUrl));
7502 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:097503 1, std::move(request_headers0), LOWEST, true));
7504
Ryan Hamilton0239aac2018-05-19 00:03:137505 spdy::SpdyHeaderBlock response_headers0;
7506 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:097507 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:137508 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:097509 1, std::move(response_headers0), true));
7510
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377511 // Stream 1 is closed.
7512 spdy_util_.UpdateWithStreamDestruction(1);
7513
7514 // Generate the NTLM messages based on known test data.
7515 std::string negotiate_msg;
7516 std::string challenge_msg;
7517 std::string authenticate_msg;
7518 base::Base64Encode(
7519 base::StringPiece(
7520 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247521 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377522 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557523 base::Base64Encode(
7524 base::StringPiece(
7525 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247526 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557527 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377528 base::Base64Encode(
7529 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097530 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557531 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247532 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557533 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377534 &authenticate_msg);
7535
Bence Béky3238f2e12017-09-22 22:44:497536 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:167537 MockRead reads0[] = {CreateMockRead(resp, 1),
7538 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:097539
7540 // Retry yet again using HTTP/1.1.
7541 MockWrite writes1[] = {
7542 // After restarting with a null identity, this is the
7543 // request we should be issuing -- the final header line contains a Type
7544 // 1 message.
7545 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557546 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097547 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377548 "Authorization: NTLM "),
7549 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097550
7551 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7552 // (the credentials for the origin server). The second request continues
7553 // on the same connection.
7554 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557555 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097556 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377557 "Authorization: NTLM "),
7558 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097559 };
7560
7561 MockRead reads1[] = {
7562 // The origin server responds with a Type 2 message.
7563 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377564 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7565 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:097566 MockRead("Content-Type: text/html\r\n\r\n"),
7567 MockRead("You are not authorized to view this page\r\n"),
7568
7569 // Lastly we get the desired content.
7570 MockRead("HTTP/1.1 200 OK\r\n"),
7571 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027572 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:097573 };
Ryan Sleevib8d7ea02018-05-07 20:01:017574 SequencedSocketData data0(reads0, writes0);
7575 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:097576 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7577 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7578
7579 SSLSocketDataProvider ssl0(ASYNC, OK);
7580 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:167581 ssl0.next_protos_expected_in_ssl_config =
7582 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:097583 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:167584 // When creating the second connection, only HTTP/1.1 should be allowed.
7585 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:097586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7587 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7588
7589 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7590 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7591
7592 TestCompletionCallback callback1;
7593 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
7594 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7595
7596 rv = callback1.WaitForResult();
7597 EXPECT_THAT(rv, IsOk());
7598
7599 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7600
7601 const HttpResponseInfo* response = trans.GetResponseInfo();
7602 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587603 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:097604
7605 TestCompletionCallback callback2;
7606
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377607 rv = trans.RestartWithAuth(
7608 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7609 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:097610 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7611
7612 rv = callback2.WaitForResult();
7613 EXPECT_THAT(rv, IsOk());
7614
7615 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7616
7617 response = trans.GetResponseInfo();
7618 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587619 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:097620
7621 TestCompletionCallback callback3;
7622
7623 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
7624 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7625
7626 rv = callback3.WaitForResult();
7627 EXPECT_THAT(rv, IsOk());
7628
7629 response = trans.GetResponseInfo();
7630 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587631 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027632 EXPECT_EQ(14, response->headers->GetContentLength());
7633
7634 std::string response_data;
7635 rv = ReadTransaction(&trans, &response_data);
7636 EXPECT_THAT(rv, IsOk());
7637 EXPECT_EQ("Please Login\r\n", response_data);
7638
7639 EXPECT_TRUE(data0.AllReadDataConsumed());
7640 EXPECT_TRUE(data0.AllWriteDataConsumed());
7641 EXPECT_TRUE(data1.AllReadDataConsumed());
7642 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:097643}
David Benjamin5cb91132018-04-06 05:54:497644
Matt Menkef2ee07c2019-08-29 02:10:367645#if BUILDFLAG(ENABLE_WEBSOCKETS)
7646
7647// Variant of above test using WebSockets.
7648TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
7649 const GURL kInitialUrl("https://server/");
7650 const GURL kWebSocketUrl("wss://server/");
7651 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7652 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7653
7654 // Initial request establishes an H2 connection, which will then be reused for
7655 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
7656 // it won't create a new one.
7657 spdy::SpdyHeaderBlock initial_request_headers(
7658 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
7659 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
7660 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
7661 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
7662
7663 // Settings frame, indicating WebSockets is supported.
7664 spdy::SettingsMap settings;
7665 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
7666 spdy::SpdySerializedFrame settings_frame(
7667 spdy_util_.ConstructSpdySettings(settings));
7668
7669 // Response headers for first request. Body is never received, but that
7670 // shouldn't matter for the purposes of this test.
7671 spdy::SpdySerializedFrame initial_response(
7672 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7673
7674 // First WebSocket request, which has no credentials.
7675 spdy::SpdyHeaderBlock websocket_request_headers;
7676 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
7677 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
7678 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
7679 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
7680 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
7681 websocket_request_headers["origin"] = "http://server";
7682 websocket_request_headers["sec-websocket-version"] = "13";
7683 websocket_request_headers["sec-websocket-extensions"] =
7684 "permessage-deflate; client_max_window_bits";
7685 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
7686 3, std::move(websocket_request_headers), MEDIUM, false));
7687
7688 // Auth challenge to WebSocket request.
7689 spdy::SpdyHeaderBlock auth_challenge_headers;
7690 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
7691 auth_challenge_headers["www-authenticate"] = "NTLM";
7692 spdy::SpdySerializedFrame websocket_auth_challenge(
7693 spdy_util_.ConstructSpdyResponseHeaders(
7694 3, std::move(auth_challenge_headers), true));
7695
7696 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
7697 CreateMockWrite(settings_ack, 2),
7698 CreateMockWrite(websocket_request, 4),
7699 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
7700 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
7701 CreateMockRead(initial_response, 3),
7702 CreateMockRead(websocket_auth_challenge, 5),
7703 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
7704
7705 // Generate the NTLM messages based on known test data.
7706 std::string negotiate_msg;
7707 std::string challenge_msg;
7708 std::string authenticate_msg;
7709 base::Base64Encode(
7710 base::StringPiece(
7711 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
7712 base::size(ntlm::test::kExpectedNegotiateMsg)),
7713 &negotiate_msg);
7714 base::Base64Encode(
7715 base::StringPiece(
7716 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
7717 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
7718 &challenge_msg);
7719 base::Base64Encode(
7720 base::StringPiece(
7721 reinterpret_cast<const char*>(
7722 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
7723 base::size(
7724 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7725 &authenticate_msg);
7726
7727 // Retry yet again using HTTP/1.1.
7728 MockWrite writes1[] = {
7729 // After restarting with a null identity, this is the
7730 // request we should be issuing -- the final header line contains a Type
7731 // 1 message.
7732 MockWrite("GET / HTTP/1.1\r\n"
7733 "Host: server\r\n"
7734 "Connection: Upgrade\r\n"
7735 "Authorization: NTLM "),
7736 MockWrite(negotiate_msg.c_str()),
7737 MockWrite("\r\n"),
7738 MockWrite("Origin: http://server\r\n"
7739 "Sec-WebSocket-Version: 13\r\n"
7740 "Upgrade: websocket\r\n"
7741 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7742 "Sec-WebSocket-Extensions: permessage-deflate; "
7743 "client_max_window_bits\r\n\r\n"),
7744
7745 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7746 // (the credentials for the origin server). The second request continues
7747 // on the same connection.
7748 MockWrite("GET / HTTP/1.1\r\n"
7749 "Host: server\r\n"
7750 "Connection: Upgrade\r\n"
7751 "Authorization: NTLM "),
7752 MockWrite(authenticate_msg.c_str()),
7753 MockWrite("\r\n"),
7754 MockWrite("Origin: http://server\r\n"
7755 "Sec-WebSocket-Version: 13\r\n"
7756 "Upgrade: websocket\r\n"
7757 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7758 "Sec-WebSocket-Extensions: permessage-deflate; "
7759 "client_max_window_bits\r\n\r\n"),
7760 };
7761
7762 MockRead reads1[] = {
7763 // The origin server responds with a Type 2 message.
7764 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7765 MockRead("WWW-Authenticate: NTLM "),
7766 MockRead(challenge_msg.c_str()),
7767 MockRead("\r\n"),
7768 MockRead("Content-Length: 42\r\n"),
7769 MockRead("Content-Type: text/html\r\n\r\n"),
7770 MockRead("You are not authorized to view this page\r\n"),
7771
7772 // Lastly we get the desired content.
7773 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
7774 "Upgrade: websocket\r\n"
7775 "Connection: Upgrade\r\n"
7776 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
7777 };
7778 SequencedSocketData data0(reads0, writes0);
7779 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7780 SSLSocketDataProvider ssl0(ASYNC, OK);
7781 ssl0.next_proto = kProtoHTTP2;
7782 ssl0.next_protos_expected_in_ssl_config =
7783 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
7784 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7785
7786 StaticSocketDataProvider data1(reads1, writes1);
7787 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7788 SSLSocketDataProvider ssl1(ASYNC, OK);
7789 // When creating the second connection, only HTTP/1.1 should be allowed.
7790 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
7791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7792
7793 session_deps_.enable_websocket_over_http2 = true;
7794 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7795
7796 HttpRequestInfo initial_request_info;
7797 initial_request_info.method = "GET";
7798 initial_request_info.url = kInitialUrl;
7799 initial_request_info.traffic_annotation =
7800 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7801 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
7802 TestCompletionCallback initial_callback;
7803 int rv = initial_trans.Start(&initial_request_info,
7804 initial_callback.callback(), NetLogWithSource());
7805 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
7806
7807 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
7808 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
7809
7810 HttpRequestInfo websocket_request_info;
7811 websocket_request_info.method = "GET";
7812 websocket_request_info.url = kWebSocketUrl;
7813 websocket_request_info.traffic_annotation =
7814 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7815 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
7816 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
7817 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
7818 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7819 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
7820 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
7821 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
7822
7823 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7824
7825 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
7826 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
7827 &websocket_stream_create_helper);
7828
7829 TestCompletionCallback websocket_callback;
7830 rv = websocket_trans.Start(&websocket_request_info,
7831 websocket_callback.callback(), NetLogWithSource());
7832 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
7833
7834 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
7835
7836 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
7837 ASSERT_TRUE(response);
7838 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
7839
7840 rv = websocket_trans.RestartWithAuth(
7841 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7842 websocket_callback.callback());
7843 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
7844
7845 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
7846
7847 response = websocket_trans.GetResponseInfo();
7848 ASSERT_TRUE(response);
7849 EXPECT_FALSE(response->auth_challenge.has_value());
7850
7851 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
7852 websocket_callback.callback());
7853 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
7854
7855 // The server should have been marked as requiring HTTP/1.1. The important
7856 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
7857 // WSS.
7858 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
7859 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
7860}
7861
7862#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
7863
David Benjamin5cb91132018-04-06 05:54:497864// Test that, if we have an NTLM proxy and the origin resets the connection, we
7865// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:377866// regression test for https://crbug.com/823387. The version interference probe
7867// has since been removed, but retain the regression test so we can update it if
7868// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:497869TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
7870 // The NTLM test data expects the proxy to be named 'server'. The origin is
7871 // https://origin/.
7872 session_deps_.proxy_resolution_service =
7873 ProxyResolutionService::CreateFixedFromPacResult(
7874 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
7875
David Benjamin151ec6b2019-08-02 19:38:527876 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:497877 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:077878 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:497879
7880 HttpRequestInfo request;
7881 request.method = "GET";
7882 request.url = GURL("https://origin/");
7883 request.traffic_annotation =
7884 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7885
7886 // Ensure load is not disrupted by flags which suppress behaviour specific
7887 // to other auth schemes.
7888 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
7889
7890 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7891 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7892 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7893
7894 // Generate the NTLM messages based on known test data.
7895 std::string negotiate_msg;
7896 std::string challenge_msg;
7897 std::string authenticate_msg;
7898 base::Base64Encode(
7899 base::StringPiece(
7900 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247901 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:497902 &negotiate_msg);
7903 base::Base64Encode(
7904 base::StringPiece(
7905 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247906 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:497907 &challenge_msg);
7908 base::Base64Encode(
7909 base::StringPiece(
7910 reinterpret_cast<const char*>(
7911 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247912 base::size(
David Benjamin5cb91132018-04-06 05:54:497913 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7914 &authenticate_msg);
7915
7916 MockWrite data_writes[] = {
7917 // The initial CONNECT request.
7918 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7919 "Host: origin:443\r\n"
7920 "Proxy-Connection: keep-alive\r\n\r\n"),
7921
7922 // After restarting with an identity.
7923 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7924 "Host: origin:443\r\n"
7925 "Proxy-Connection: keep-alive\r\n"
7926 "Proxy-Authorization: NTLM "),
7927 MockWrite(negotiate_msg.c_str()),
7928 // End headers.
7929 MockWrite("\r\n\r\n"),
7930
7931 // The second restart.
7932 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7933 "Host: origin:443\r\n"
7934 "Proxy-Connection: keep-alive\r\n"
7935 "Proxy-Authorization: NTLM "),
7936 MockWrite(authenticate_msg.c_str()),
7937 // End headers.
7938 MockWrite("\r\n\r\n"),
7939 };
7940
7941 MockRead data_reads[] = {
7942 // The initial NTLM response.
7943 MockRead("HTTP/1.1 407 Access Denied\r\n"
7944 "Content-Length: 0\r\n"
7945 "Proxy-Authenticate: NTLM\r\n\r\n"),
7946
7947 // The NTLM challenge message.
7948 MockRead("HTTP/1.1 407 Access Denied\r\n"
7949 "Content-Length: 0\r\n"
7950 "Proxy-Authenticate: NTLM "),
7951 MockRead(challenge_msg.c_str()),
7952 // End headers.
7953 MockRead("\r\n\r\n"),
7954
7955 // Finally the tunnel is established.
7956 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
7957 };
7958
Ryan Sleevib8d7ea02018-05-07 20:01:017959 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:497960 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:497961 session_deps_.socket_factory->AddSocketDataProvider(&data);
7962 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:497963
7964 // Start the transaction. The proxy responds with an NTLM authentication
7965 // request.
7966 TestCompletionCallback callback;
7967 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7968 int rv = callback.GetResult(
7969 trans.Start(&request, callback.callback(), NetLogWithSource()));
7970
7971 EXPECT_THAT(rv, IsOk());
7972 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7973 const HttpResponseInfo* response = trans.GetResponseInfo();
7974 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587975 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:497976
David Benjamind61bd532019-04-23 21:11:377977 // Configure credentials and restart. The proxy responds with the challenge
7978 // message.
David Benjamin5cb91132018-04-06 05:54:497979 rv = callback.GetResult(trans.RestartWithAuth(
7980 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7981 callback.callback()));
7982 EXPECT_THAT(rv, IsOk());
7983 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7984 response = trans.GetResponseInfo();
7985 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587986 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:497987
David Benjamind61bd532019-04-23 21:11:377988 // Restart once more. The tunnel will be established and then the SSL
7989 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:497990 rv = callback.GetResult(
7991 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
7992 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
7993}
7994
[email protected]ea9dc9a2009-09-05 00:43:327995#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:297996
[email protected]4ddaf2502008-10-23 18:26:197997// Test reading a server response which has only headers, and no body.
7998// After some maximum number of bytes is consumed, the transaction should
7999// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:018000TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:428001 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:198002 request.method = "GET";
bncce36dca22015-04-21 22:11:238003 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108004 request.traffic_annotation =
8005 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:198006
danakj1fd259a02016-04-16 03:17:098007 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168008 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278009
[email protected]b75b7b2f2009-10-06 00:54:538010 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:438011 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:538012 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:198013
8014 MockRead data_reads[] = {
8015 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:068016 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:198017 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:068018 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:198019 };
Ryan Sleevib8d7ea02018-05-07 20:01:018020 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078021 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:198022
[email protected]49639fa2011-12-20 23:22:418023 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:198024
tfarina42834112016-09-22 13:38:208025 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018026 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:198027
8028 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018029 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:198030}
[email protected]f4e426b2008-11-05 00:24:498031
8032// Make sure that we don't try to reuse a TCPClientSocket when failing to
8033// establish tunnel.
8034// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:018035TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:278036 HttpRequestInfo request;
8037 request.method = "GET";
bncce36dca22015-04-21 22:11:238038 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108039 request.traffic_annotation =
8040 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278041
[email protected]f4e426b2008-11-05 00:24:498042 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:498043 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
8044 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:018045
danakj1fd259a02016-04-16 03:17:098046 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:498047
bnc87dcefc2017-05-25 12:47:588048 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198049 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:498050
[email protected]f4e426b2008-11-05 00:24:498051 // Since we have proxy, should try to establish tunnel.
8052 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:178053 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8054 "Host: www.example.org:443\r\n"
8055 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:498056 };
8057
[email protected]77848d12008-11-14 00:00:228058 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:498059 // connection. Usually a proxy would return 501 (not implemented),
8060 // or 200 (tunnel established).
8061 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:238062 MockRead("HTTP/1.1 404 Not Found\r\n"),
8063 MockRead("Content-Length: 10\r\n\r\n"),
8064 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:498065 };
8066
Ryan Sleevib8d7ea02018-05-07 20:01:018067 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078068 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:498069
[email protected]49639fa2011-12-20 23:22:418070 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:498071
tfarina42834112016-09-22 13:38:208072 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018073 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:498074
8075 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018076 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:498077
[email protected]b4404c02009-04-10 16:38:528078 // Empty the current queue. This is necessary because idle sockets are
8079 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558080 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528081
[email protected]f4e426b2008-11-05 00:24:498082 // We now check to make sure the TCPClientSocket was not added back to
8083 // the pool.
[email protected]90499482013-06-01 00:39:508084 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498085 trans.reset();
fdoray92e35a72016-06-10 15:54:558086 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:498087 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:508088 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498089}
[email protected]372d34a2008-11-05 21:30:518090
[email protected]1b157c02009-04-21 01:55:408091// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:018092TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:428093 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:408094 request.method = "GET";
bncce36dca22015-04-21 22:11:238095 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108096 request.traffic_annotation =
8097 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:408098
danakj1fd259a02016-04-16 03:17:098099 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278100
bnc691fda62016-08-12 00:43:168101 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278102
[email protected]1b157c02009-04-21 01:55:408103 MockRead data_reads[] = {
8104 // A part of the response body is received with the response headers.
8105 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8106 // The rest of the response body is received in two parts.
8107 MockRead("lo"),
8108 MockRead(" world"),
8109 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068110 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:408111 };
8112
Ryan Sleevib8d7ea02018-05-07 20:01:018113 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078114 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:408115
[email protected]49639fa2011-12-20 23:22:418116 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:408117
tfarina42834112016-09-22 13:38:208118 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018119 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:408120
8121 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018122 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408123
bnc691fda62016-08-12 00:43:168124 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528125 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:408126
wezca1070932016-05-26 20:30:528127 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:408128 std::string status_line = response->headers->GetStatusLine();
8129 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8130
[email protected]90499482013-06-01 00:39:508131 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408132
8133 std::string response_data;
bnc691fda62016-08-12 00:43:168134 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018135 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408136 EXPECT_EQ("hello world", response_data);
8137
8138 // Empty the current queue. This is necessary because idle sockets are
8139 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558140 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:408141
8142 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508143 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408144}
8145
[email protected]76a505b2010-08-25 06:23:008146// Make sure that we recycle a SSL socket after reading all of the response
8147// body.
bncd16676a2016-07-20 16:23:018148TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008149 HttpRequestInfo request;
8150 request.method = "GET";
bncce36dca22015-04-21 22:11:238151 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108152 request.traffic_annotation =
8153 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008154
8155 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238156 MockWrite(
8157 "GET / HTTP/1.1\r\n"
8158 "Host: www.example.org\r\n"
8159 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008160 };
8161
8162 MockRead data_reads[] = {
8163 MockRead("HTTP/1.1 200 OK\r\n"),
8164 MockRead("Content-Length: 11\r\n\r\n"),
8165 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068166 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008167 };
8168
[email protected]8ddf8322012-02-23 18:08:068169 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078170 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:008171
Ryan Sleevib8d7ea02018-05-07 20:01:018172 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078173 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008174
[email protected]49639fa2011-12-20 23:22:418175 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008176
danakj1fd259a02016-04-16 03:17:098177 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168178 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008179
tfarina42834112016-09-22 13:38:208180 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008181
robpercival214763f2016-07-01 23:27:018182 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8183 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008184
bnc691fda62016-08-12 00:43:168185 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528186 ASSERT_TRUE(response);
8187 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008188 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8189
[email protected]90499482013-06-01 00:39:508190 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008191
8192 std::string response_data;
bnc691fda62016-08-12 00:43:168193 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018194 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008195 EXPECT_EQ("hello world", response_data);
8196
8197 // Empty the current queue. This is necessary because idle sockets are
8198 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558199 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008200
8201 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238202 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008203}
8204
8205// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8206// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018207TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008208 HttpRequestInfo request;
8209 request.method = "GET";
bncce36dca22015-04-21 22:11:238210 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108211 request.traffic_annotation =
8212 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008213
8214 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238215 MockWrite(
8216 "GET / HTTP/1.1\r\n"
8217 "Host: www.example.org\r\n"
8218 "Connection: keep-alive\r\n\r\n"),
8219 MockWrite(
8220 "GET / HTTP/1.1\r\n"
8221 "Host: www.example.org\r\n"
8222 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008223 };
8224
8225 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428226 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8227 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008228
[email protected]8ddf8322012-02-23 18:08:068229 SSLSocketDataProvider ssl(ASYNC, OK);
8230 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078231 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008233
Ryan Sleevib8d7ea02018-05-07 20:01:018234 StaticSocketDataProvider data(data_reads, data_writes);
8235 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078236 session_deps_.socket_factory->AddSocketDataProvider(&data);
8237 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008238
[email protected]49639fa2011-12-20 23:22:418239 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008240
danakj1fd259a02016-04-16 03:17:098241 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588242 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198243 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008244
tfarina42834112016-09-22 13:38:208245 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008246
robpercival214763f2016-07-01 23:27:018247 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8248 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008249
8250 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528251 ASSERT_TRUE(response);
8252 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008253 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8254
[email protected]90499482013-06-01 00:39:508255 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008256
8257 std::string response_data;
8258 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018259 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008260 EXPECT_EQ("hello world", response_data);
8261
8262 // Empty the current queue. This is necessary because idle sockets are
8263 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558264 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008265
8266 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238267 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008268
8269 // Now start the second transaction, which should reuse the previous socket.
8270
bnc87dcefc2017-05-25 12:47:588271 trans =
Jeremy Roman0579ed62017-08-29 15:56:198272 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008273
tfarina42834112016-09-22 13:38:208274 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008275
robpercival214763f2016-07-01 23:27:018276 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8277 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008278
8279 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528280 ASSERT_TRUE(response);
8281 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008282 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8283
[email protected]90499482013-06-01 00:39:508284 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008285
8286 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018287 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008288 EXPECT_EQ("hello world", response_data);
8289
8290 // Empty the current queue. This is necessary because idle sockets are
8291 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558292 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008293
8294 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238295 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008296}
8297
maksim.sisov0adf8592016-07-15 06:25:568298// Grab a socket, use it, and put it back into the pool. Then, make
8299// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018300TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568301 HttpRequestInfo request;
8302 request.method = "GET";
8303 request.url = GURL("http://www.example.org/");
8304 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108305 request.traffic_annotation =
8306 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568307
8308 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8309
bnc691fda62016-08-12 00:43:168310 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568311
8312 MockRead data_reads[] = {
8313 // A part of the response body is received with the response headers.
8314 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8315 // The rest of the response body is received in two parts.
8316 MockRead("lo"), MockRead(" world"),
8317 MockRead("junk"), // Should not be read!!
8318 MockRead(SYNCHRONOUS, OK),
8319 };
8320
Ryan Sleevib8d7ea02018-05-07 20:01:018321 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:568322 session_deps_.socket_factory->AddSocketDataProvider(&data);
8323
8324 TestCompletionCallback callback;
8325
tfarina42834112016-09-22 13:38:208326 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568327 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8328
8329 EXPECT_THAT(callback.GetResult(rv), IsOk());
8330
bnc691fda62016-08-12 00:43:168331 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568332 ASSERT_TRUE(response);
8333 EXPECT_TRUE(response->headers);
8334 std::string status_line = response->headers->GetStatusLine();
8335 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8336
8337 // Make memory critical notification and ensure the transaction still has been
8338 // operating right.
8339 base::MemoryPressureListener::NotifyMemoryPressure(
8340 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8341 base::RunLoop().RunUntilIdle();
8342
8343 // Socket should not be flushed as long as it is not idle.
8344 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8345
8346 std::string response_data;
bnc691fda62016-08-12 00:43:168347 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568348 EXPECT_THAT(rv, IsOk());
8349 EXPECT_EQ("hello world", response_data);
8350
8351 // Empty the current queue. This is necessary because idle sockets are
8352 // added to the connection pool asynchronously with a PostTask.
8353 base::RunLoop().RunUntilIdle();
8354
8355 // We now check to make sure the socket was added back to the pool.
8356 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8357
8358 // Idle sockets should be flushed now.
8359 base::MemoryPressureListener::NotifyMemoryPressure(
8360 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8361 base::RunLoop().RunUntilIdle();
8362
8363 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8364}
8365
yucliu48f235d2018-01-11 00:59:558366// Disable idle socket closing on memory pressure.
8367// Grab a socket, use it, and put it back into the pool. Then, make
8368// low memory notification and ensure the socket pool is NOT flushed.
8369TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
8370 HttpRequestInfo request;
8371 request.method = "GET";
8372 request.url = GURL("http://www.example.org/");
8373 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108374 request.traffic_annotation =
8375 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:558376
8377 // Disable idle socket closing on memory pressure.
8378 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
8379 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8380
8381 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8382
8383 MockRead data_reads[] = {
8384 // A part of the response body is received with the response headers.
8385 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8386 // The rest of the response body is received in two parts.
8387 MockRead("lo"), MockRead(" world"),
8388 MockRead("junk"), // Should not be read!!
8389 MockRead(SYNCHRONOUS, OK),
8390 };
8391
Ryan Sleevib8d7ea02018-05-07 20:01:018392 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:558393 session_deps_.socket_factory->AddSocketDataProvider(&data);
8394
8395 TestCompletionCallback callback;
8396
8397 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
8398 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8399
8400 EXPECT_THAT(callback.GetResult(rv), IsOk());
8401
8402 const HttpResponseInfo* response = trans.GetResponseInfo();
8403 ASSERT_TRUE(response);
8404 EXPECT_TRUE(response->headers);
8405 std::string status_line = response->headers->GetStatusLine();
8406 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8407
8408 // Make memory critical notification and ensure the transaction still has been
8409 // operating right.
8410 base::MemoryPressureListener::NotifyMemoryPressure(
8411 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8412 base::RunLoop().RunUntilIdle();
8413
8414 // Socket should not be flushed as long as it is not idle.
8415 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8416
8417 std::string response_data;
8418 rv = ReadTransaction(&trans, &response_data);
8419 EXPECT_THAT(rv, IsOk());
8420 EXPECT_EQ("hello world", response_data);
8421
8422 // Empty the current queue. This is necessary because idle sockets are
8423 // added to the connection pool asynchronously with a PostTask.
8424 base::RunLoop().RunUntilIdle();
8425
8426 // We now check to make sure the socket was added back to the pool.
8427 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8428
8429 // Idle sockets should NOT be flushed on moderate memory pressure.
8430 base::MemoryPressureListener::NotifyMemoryPressure(
8431 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
8432 base::RunLoop().RunUntilIdle();
8433
8434 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8435
8436 // Idle sockets should NOT be flushed on critical memory pressure.
8437 base::MemoryPressureListener::NotifyMemoryPressure(
8438 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8439 base::RunLoop().RunUntilIdle();
8440
8441 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8442}
8443
maksim.sisov0adf8592016-07-15 06:25:568444// Grab an SSL socket, use it, and put it back into the pool. Then, make
8445// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018446TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568447 HttpRequestInfo request;
8448 request.method = "GET";
8449 request.url = GURL("https://www.example.org/");
8450 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108451 request.traffic_annotation =
8452 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568453
8454 MockWrite data_writes[] = {
8455 MockWrite("GET / HTTP/1.1\r\n"
8456 "Host: www.example.org\r\n"
8457 "Connection: keep-alive\r\n\r\n"),
8458 };
8459
8460 MockRead data_reads[] = {
8461 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8462 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
8463
8464 SSLSocketDataProvider ssl(ASYNC, OK);
8465 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8466
Ryan Sleevib8d7ea02018-05-07 20:01:018467 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:568468 session_deps_.socket_factory->AddSocketDataProvider(&data);
8469
8470 TestCompletionCallback callback;
8471
8472 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168473 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568474
Matt Menke9d5e2c92019-02-05 01:42:238475 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:208476 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568477
8478 EXPECT_THAT(callback.GetResult(rv), IsOk());
8479
bnc691fda62016-08-12 00:43:168480 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568481 ASSERT_TRUE(response);
8482 ASSERT_TRUE(response->headers);
8483 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8484
8485 // Make memory critical notification and ensure the transaction still has been
8486 // operating right.
8487 base::MemoryPressureListener::NotifyMemoryPressure(
8488 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8489 base::RunLoop().RunUntilIdle();
8490
Matt Menke9d5e2c92019-02-05 01:42:238491 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568492
8493 std::string response_data;
bnc691fda62016-08-12 00:43:168494 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568495 EXPECT_THAT(rv, IsOk());
8496 EXPECT_EQ("hello world", response_data);
8497
8498 // Empty the current queue. This is necessary because idle sockets are
8499 // added to the connection pool asynchronously with a PostTask.
8500 base::RunLoop().RunUntilIdle();
8501
8502 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238503 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568504
8505 // Make memory notification once again and ensure idle socket is closed.
8506 base::MemoryPressureListener::NotifyMemoryPressure(
8507 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8508 base::RunLoop().RunUntilIdle();
8509
Matt Menke9d5e2c92019-02-05 01:42:238510 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568511}
8512
[email protected]b4404c02009-04-10 16:38:528513// Make sure that we recycle a socket after a zero-length response.
8514// http://crbug.com/9880
bncd16676a2016-07-20 16:23:018515TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:428516 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:528517 request.method = "GET";
bncce36dca22015-04-21 22:11:238518 request.url = GURL(
8519 "http://www.example.org/csi?v=3&s=web&action=&"
8520 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
8521 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
8522 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e2018-02-07 07:41:108523 request.traffic_annotation =
8524 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:528525
danakj1fd259a02016-04-16 03:17:098526 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278527
[email protected]b4404c02009-04-10 16:38:528528 MockRead data_reads[] = {
8529 MockRead("HTTP/1.1 204 No Content\r\n"
8530 "Content-Length: 0\r\n"
8531 "Content-Type: text/html\r\n\r\n"),
8532 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068533 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:528534 };
8535
Ryan Sleevib8d7ea02018-05-07 20:01:018536 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078537 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:528538
mmenkecc2298e2015-12-07 18:20:188539 // Transaction must be created after the MockReads, so it's destroyed before
8540 // them.
bnc691fda62016-08-12 00:43:168541 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:188542
[email protected]49639fa2011-12-20 23:22:418543 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:528544
tfarina42834112016-09-22 13:38:208545 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018546 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:528547
8548 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018549 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528550
bnc691fda62016-08-12 00:43:168551 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528552 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:528553
wezca1070932016-05-26 20:30:528554 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:528555 std::string status_line = response->headers->GetStatusLine();
8556 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
8557
[email protected]90499482013-06-01 00:39:508558 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528559
8560 std::string response_data;
bnc691fda62016-08-12 00:43:168561 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018562 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528563 EXPECT_EQ("", response_data);
8564
8565 // Empty the current queue. This is necessary because idle sockets are
8566 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558567 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528568
8569 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508570 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528571}
8572
bncd16676a2016-07-20 16:23:018573TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:098574 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:228575 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:198576 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:228577 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:278578
[email protected]1c773ea12009-04-28 19:58:428579 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:518580 // Transaction 1: a GET request that succeeds. The socket is recycled
8581 // after use.
8582 request[0].method = "GET";
8583 request[0].url = GURL("http://www.google.com/");
8584 request[0].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108585 request[0].traffic_annotation =
8586 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518587 // Transaction 2: a POST request. Reuses the socket kept alive from
8588 // transaction 1. The first attempts fails when writing the POST data.
8589 // This causes the transaction to retry with a new socket. The second
8590 // attempt succeeds.
8591 request[1].method = "POST";
8592 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:278593 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:518594 request[1].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108595 request[1].traffic_annotation =
8596 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518597
danakj1fd259a02016-04-16 03:17:098598 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:518599
8600 // The first socket is used for transaction 1 and the first attempt of
8601 // transaction 2.
8602
8603 // The response of transaction 1.
8604 MockRead data_reads1[] = {
8605 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
8606 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068607 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518608 };
8609 // The mock write results of transaction 1 and the first attempt of
8610 // transaction 2.
8611 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:068612 MockWrite(SYNCHRONOUS, 64), // GET
8613 MockWrite(SYNCHRONOUS, 93), // POST
8614 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:518615 };
Ryan Sleevib8d7ea02018-05-07 20:01:018616 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:518617
8618 // The second socket is used for the second attempt of transaction 2.
8619
8620 // The response of transaction 2.
8621 MockRead data_reads2[] = {
8622 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
8623 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:068624 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518625 };
8626 // The mock write results of the second attempt of transaction 2.
8627 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:068628 MockWrite(SYNCHRONOUS, 93), // POST
8629 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:518630 };
Ryan Sleevib8d7ea02018-05-07 20:01:018631 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:518632
[email protected]bb88e1d32013-05-03 23:11:078633 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8634 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:518635
thestig9d3bb0c2015-01-24 00:49:518636 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:518637 "hello world", "welcome"
8638 };
8639
8640 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:168641 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:518642
[email protected]49639fa2011-12-20 23:22:418643 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:518644
tfarina42834112016-09-22 13:38:208645 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018646 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:518647
8648 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018649 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518650
bnc691fda62016-08-12 00:43:168651 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528652 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:518653
wezca1070932016-05-26 20:30:528654 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:518655 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8656
8657 std::string response_data;
bnc691fda62016-08-12 00:43:168658 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018659 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518660 EXPECT_EQ(kExpectedResponseData[i], response_data);
8661 }
8662}
[email protected]f9ee6b52008-11-08 06:46:238663
8664// Test the request-challenge-retry sequence for basic auth when there is
8665// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:168666// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:018667TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:428668 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238669 request.method = "GET";
bncce36dca22015-04-21 22:11:238670 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:418671 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:108672 request.traffic_annotation =
8673 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:298674
danakj1fd259a02016-04-16 03:17:098675 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168676 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278677
[email protected]a97cca42009-08-14 01:00:298678 // The password contains an escaped character -- for this test to pass it
8679 // will need to be unescaped by HttpNetworkTransaction.
8680 EXPECT_EQ("b%40r", request.url.password());
8681
[email protected]f9ee6b52008-11-08 06:46:238682 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238683 MockWrite(
8684 "GET / HTTP/1.1\r\n"
8685 "Host: www.example.org\r\n"
8686 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238687 };
8688
8689 MockRead data_reads1[] = {
8690 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8691 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8692 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068693 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238694 };
8695
[email protected]2262e3a2012-05-22 16:08:168696 // After the challenge above, the transaction will be restarted using the
8697 // identity from the url (foo, b@r) to answer the challenge.
8698 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238699 MockWrite(
8700 "GET / HTTP/1.1\r\n"
8701 "Host: www.example.org\r\n"
8702 "Connection: keep-alive\r\n"
8703 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168704 };
8705
8706 MockRead data_reads2[] = {
8707 MockRead("HTTP/1.0 200 OK\r\n"),
8708 MockRead("Content-Length: 100\r\n\r\n"),
8709 MockRead(SYNCHRONOUS, OK),
8710 };
8711
Ryan Sleevib8d7ea02018-05-07 20:01:018712 StaticSocketDataProvider data1(data_reads1, data_writes1);
8713 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078714 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8715 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238716
[email protected]49639fa2011-12-20 23:22:418717 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208718 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018719 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238720 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018721 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168722 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168723
8724 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168725 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018726 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168727 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018728 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168729 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228730
bnc691fda62016-08-12 00:43:168731 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528732 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168733
8734 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:588735 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168736
8737 EXPECT_EQ(100, response->headers->GetContentLength());
8738
8739 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558740 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:168741}
8742
8743// Test the request-challenge-retry sequence for basic auth when there is an
8744// incorrect identity in the URL. The identity from the URL should be used only
8745// once.
bncd16676a2016-07-20 16:23:018746TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:168747 HttpRequestInfo request;
8748 request.method = "GET";
8749 // Note: the URL has a username:password in it. The password "baz" is
8750 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:238751 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:168752
8753 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:108754 request.traffic_annotation =
8755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:168756
danakj1fd259a02016-04-16 03:17:098757 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168758 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:168759
8760 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238761 MockWrite(
8762 "GET / HTTP/1.1\r\n"
8763 "Host: www.example.org\r\n"
8764 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168765 };
8766
8767 MockRead data_reads1[] = {
8768 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8769 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8770 MockRead("Content-Length: 10\r\n\r\n"),
8771 MockRead(SYNCHRONOUS, ERR_FAILED),
8772 };
8773
8774 // After the challenge above, the transaction will be restarted using the
8775 // identity from the url (foo, baz) to answer the challenge.
8776 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238777 MockWrite(
8778 "GET / HTTP/1.1\r\n"
8779 "Host: www.example.org\r\n"
8780 "Connection: keep-alive\r\n"
8781 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168782 };
8783
8784 MockRead data_reads2[] = {
8785 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8786 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8787 MockRead("Content-Length: 10\r\n\r\n"),
8788 MockRead(SYNCHRONOUS, ERR_FAILED),
8789 };
8790
8791 // After the challenge above, the transaction will be restarted using the
8792 // identity supplied by the user (foo, bar) to answer the challenge.
8793 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238794 MockWrite(
8795 "GET / HTTP/1.1\r\n"
8796 "Host: www.example.org\r\n"
8797 "Connection: keep-alive\r\n"
8798 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168799 };
8800
8801 MockRead data_reads3[] = {
8802 MockRead("HTTP/1.0 200 OK\r\n"),
8803 MockRead("Content-Length: 100\r\n\r\n"),
8804 MockRead(SYNCHRONOUS, OK),
8805 };
8806
Ryan Sleevib8d7ea02018-05-07 20:01:018807 StaticSocketDataProvider data1(data_reads1, data_writes1);
8808 StaticSocketDataProvider data2(data_reads2, data_writes2);
8809 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078810 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8811 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8812 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:168813
8814 TestCompletionCallback callback1;
8815
tfarina42834112016-09-22 13:38:208816 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018817 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168818
8819 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018820 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:168821
bnc691fda62016-08-12 00:43:168822 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168823 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168824 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018825 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168826 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018827 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168828 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168829
bnc691fda62016-08-12 00:43:168830 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528831 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588832 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:168833
8834 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168835 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018836 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168837 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018838 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168839 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168840
bnc691fda62016-08-12 00:43:168841 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528842 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168843
8844 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588845 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168846
8847 EXPECT_EQ(100, response->headers->GetContentLength());
8848
[email protected]ea9dc9a2009-09-05 00:43:328849 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558850 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:328851}
8852
[email protected]2217aa22013-10-11 03:03:548853
8854// Test the request-challenge-retry sequence for basic auth when there is a
8855// correct identity in the URL, but its use is being suppressed. The identity
8856// from the URL should never be used.
bncd16676a2016-07-20 16:23:018857TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:548858 HttpRequestInfo request;
8859 request.method = "GET";
bncce36dca22015-04-21 22:11:238860 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:548861 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e2018-02-07 07:41:108862 request.traffic_annotation =
8863 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:548864
danakj1fd259a02016-04-16 03:17:098865 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168866 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:548867
8868 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238869 MockWrite(
8870 "GET / HTTP/1.1\r\n"
8871 "Host: www.example.org\r\n"
8872 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548873 };
8874
8875 MockRead data_reads1[] = {
8876 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8877 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8878 MockRead("Content-Length: 10\r\n\r\n"),
8879 MockRead(SYNCHRONOUS, ERR_FAILED),
8880 };
8881
8882 // After the challenge above, the transaction will be restarted using the
8883 // identity supplied by the user, not the one in the URL, to answer the
8884 // challenge.
8885 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238886 MockWrite(
8887 "GET / HTTP/1.1\r\n"
8888 "Host: www.example.org\r\n"
8889 "Connection: keep-alive\r\n"
8890 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548891 };
8892
8893 MockRead data_reads3[] = {
8894 MockRead("HTTP/1.0 200 OK\r\n"),
8895 MockRead("Content-Length: 100\r\n\r\n"),
8896 MockRead(SYNCHRONOUS, OK),
8897 };
8898
Ryan Sleevib8d7ea02018-05-07 20:01:018899 StaticSocketDataProvider data1(data_reads1, data_writes1);
8900 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:548901 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8902 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8903
8904 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208905 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018906 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548907 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018908 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168909 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548910
bnc691fda62016-08-12 00:43:168911 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528912 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588913 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:548914
8915 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168916 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018917 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548918 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018919 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168920 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548921
bnc691fda62016-08-12 00:43:168922 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528923 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:548924
8925 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588926 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:548927 EXPECT_EQ(100, response->headers->GetContentLength());
8928
8929 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558930 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:548931}
8932
[email protected]f9ee6b52008-11-08 06:46:238933// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:018934TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:098935 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:238936
8937 // Transaction 1: authenticate (foo, bar) on MyRealm1
8938 {
[email protected]1c773ea12009-04-28 19:58:428939 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238940 request.method = "GET";
bncce36dca22015-04-21 22:11:238941 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:108942 request.traffic_annotation =
8943 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238944
bnc691fda62016-08-12 00:43:168945 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278946
[email protected]f9ee6b52008-11-08 06:46:238947 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238948 MockWrite(
8949 "GET /x/y/z HTTP/1.1\r\n"
8950 "Host: www.example.org\r\n"
8951 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238952 };
8953
8954 MockRead data_reads1[] = {
8955 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8956 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8957 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068958 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238959 };
8960
8961 // Resend with authorization (username=foo, password=bar)
8962 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238963 MockWrite(
8964 "GET /x/y/z HTTP/1.1\r\n"
8965 "Host: www.example.org\r\n"
8966 "Connection: keep-alive\r\n"
8967 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238968 };
8969
8970 // Sever accepts the authorization.
8971 MockRead data_reads2[] = {
8972 MockRead("HTTP/1.0 200 OK\r\n"),
8973 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068974 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238975 };
8976
Ryan Sleevib8d7ea02018-05-07 20:01:018977 StaticSocketDataProvider data1(data_reads1, data_writes1);
8978 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078979 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8980 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238981
[email protected]49639fa2011-12-20 23:22:418982 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238983
tfarina42834112016-09-22 13:38:208984 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018985 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238986
8987 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018988 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238989
bnc691fda62016-08-12 00:43:168990 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528991 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588992 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:238993
[email protected]49639fa2011-12-20 23:22:418994 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238995
bnc691fda62016-08-12 00:43:168996 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
8997 callback2.callback());
robpercival214763f2016-07-01 23:27:018998 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238999
9000 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019001 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239002
bnc691fda62016-08-12 00:43:169003 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529004 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589005 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239006 EXPECT_EQ(100, response->headers->GetContentLength());
9007 }
9008
9009 // ------------------------------------------------------------------------
9010
9011 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
9012 {
[email protected]1c773ea12009-04-28 19:58:429013 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239014 request.method = "GET";
9015 // Note that Transaction 1 was at /x/y/z, so this is in the same
9016 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:239017 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:109018 request.traffic_annotation =
9019 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239020
bnc691fda62016-08-12 00:43:169021 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279022
[email protected]f9ee6b52008-11-08 06:46:239023 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239024 MockWrite(
9025 "GET /x/y/a/b HTTP/1.1\r\n"
9026 "Host: www.example.org\r\n"
9027 "Connection: keep-alive\r\n"
9028 // Send preemptive authorization for MyRealm1
9029 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239030 };
9031
9032 // The server didn't like the preemptive authorization, and
9033 // challenges us for a different realm (MyRealm2).
9034 MockRead data_reads1[] = {
9035 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9036 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
9037 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069038 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239039 };
9040
9041 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
9042 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239043 MockWrite(
9044 "GET /x/y/a/b HTTP/1.1\r\n"
9045 "Host: www.example.org\r\n"
9046 "Connection: keep-alive\r\n"
9047 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239048 };
9049
9050 // Sever accepts the authorization.
9051 MockRead data_reads2[] = {
9052 MockRead("HTTP/1.0 200 OK\r\n"),
9053 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069054 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239055 };
9056
Ryan Sleevib8d7ea02018-05-07 20:01:019057 StaticSocketDataProvider data1(data_reads1, data_writes1);
9058 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079059 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9060 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239061
[email protected]49639fa2011-12-20 23:22:419062 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239063
tfarina42834112016-09-22 13:38:209064 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019065 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239066
9067 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019068 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239069
bnc691fda62016-08-12 00:43:169070 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529071 ASSERT_TRUE(response);
9072 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:049073 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:439074 EXPECT_EQ("http://www.example.org",
9075 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049076 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:199077 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:239078
[email protected]49639fa2011-12-20 23:22:419079 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239080
bnc691fda62016-08-12 00:43:169081 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
9082 callback2.callback());
robpercival214763f2016-07-01 23:27:019083 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239084
9085 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019086 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239087
bnc691fda62016-08-12 00:43:169088 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529089 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589090 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239091 EXPECT_EQ(100, response->headers->GetContentLength());
9092 }
9093
9094 // ------------------------------------------------------------------------
9095
9096 // Transaction 3: Resend a request in MyRealm's protection space --
9097 // succeed with preemptive authorization.
9098 {
[email protected]1c773ea12009-04-28 19:58:429099 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239100 request.method = "GET";
bncce36dca22015-04-21 22:11:239101 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e2018-02-07 07:41:109102 request.traffic_annotation =
9103 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239104
bnc691fda62016-08-12 00:43:169105 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279106
[email protected]f9ee6b52008-11-08 06:46:239107 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239108 MockWrite(
9109 "GET /x/y/z2 HTTP/1.1\r\n"
9110 "Host: www.example.org\r\n"
9111 "Connection: keep-alive\r\n"
9112 // The authorization for MyRealm1 gets sent preemptively
9113 // (since the url is in the same protection space)
9114 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239115 };
9116
9117 // Sever accepts the preemptive authorization
9118 MockRead data_reads1[] = {
9119 MockRead("HTTP/1.0 200 OK\r\n"),
9120 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069121 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239122 };
9123
Ryan Sleevib8d7ea02018-05-07 20:01:019124 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079125 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:239126
[email protected]49639fa2011-12-20 23:22:419127 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239128
tfarina42834112016-09-22 13:38:209129 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019130 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239131
9132 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019133 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239134
bnc691fda62016-08-12 00:43:169135 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529136 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:239137
Emily Starkf2c9bbd2019-04-09 17:08:589138 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239139 EXPECT_EQ(100, response->headers->GetContentLength());
9140 }
9141
9142 // ------------------------------------------------------------------------
9143
9144 // Transaction 4: request another URL in MyRealm (however the
9145 // url is not known to belong to the protection space, so no pre-auth).
9146 {
[email protected]1c773ea12009-04-28 19:58:429147 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239148 request.method = "GET";
bncce36dca22015-04-21 22:11:239149 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e2018-02-07 07:41:109150 request.traffic_annotation =
9151 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239152
bnc691fda62016-08-12 00:43:169153 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279154
[email protected]f9ee6b52008-11-08 06:46:239155 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239156 MockWrite(
9157 "GET /x/1 HTTP/1.1\r\n"
9158 "Host: www.example.org\r\n"
9159 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239160 };
9161
9162 MockRead data_reads1[] = {
9163 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9164 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9165 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069166 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239167 };
9168
9169 // Resend with authorization from MyRealm's cache.
9170 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239171 MockWrite(
9172 "GET /x/1 HTTP/1.1\r\n"
9173 "Host: www.example.org\r\n"
9174 "Connection: keep-alive\r\n"
9175 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239176 };
9177
9178 // Sever accepts the authorization.
9179 MockRead data_reads2[] = {
9180 MockRead("HTTP/1.0 200 OK\r\n"),
9181 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069182 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239183 };
9184
Ryan Sleevib8d7ea02018-05-07 20:01:019185 StaticSocketDataProvider data1(data_reads1, data_writes1);
9186 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079187 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9188 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239189
[email protected]49639fa2011-12-20 23:22:419190 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239191
tfarina42834112016-09-22 13:38:209192 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019193 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239194
9195 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019196 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239197
bnc691fda62016-08-12 00:43:169198 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419199 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169200 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019201 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229202 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019203 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169204 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229205
bnc691fda62016-08-12 00:43:169206 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529207 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589208 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239209 EXPECT_EQ(100, response->headers->GetContentLength());
9210 }
9211
9212 // ------------------------------------------------------------------------
9213
9214 // Transaction 5: request a URL in MyRealm, but the server rejects the
9215 // cached identity. Should invalidate and re-prompt.
9216 {
[email protected]1c773ea12009-04-28 19:58:429217 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239218 request.method = "GET";
bncce36dca22015-04-21 22:11:239219 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e2018-02-07 07:41:109220 request.traffic_annotation =
9221 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239222
bnc691fda62016-08-12 00:43:169223 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279224
[email protected]f9ee6b52008-11-08 06:46:239225 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239226 MockWrite(
9227 "GET /p/q/t HTTP/1.1\r\n"
9228 "Host: www.example.org\r\n"
9229 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239230 };
9231
9232 MockRead data_reads1[] = {
9233 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9234 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9235 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069236 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239237 };
9238
9239 // Resend with authorization from cache for MyRealm.
9240 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239241 MockWrite(
9242 "GET /p/q/t HTTP/1.1\r\n"
9243 "Host: www.example.org\r\n"
9244 "Connection: keep-alive\r\n"
9245 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239246 };
9247
9248 // Sever rejects the authorization.
9249 MockRead data_reads2[] = {
9250 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9251 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9252 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069253 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239254 };
9255
9256 // At this point we should prompt for new credentials for MyRealm.
9257 // Restart with username=foo3, password=foo4.
9258 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239259 MockWrite(
9260 "GET /p/q/t HTTP/1.1\r\n"
9261 "Host: www.example.org\r\n"
9262 "Connection: keep-alive\r\n"
9263 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239264 };
9265
9266 // Sever accepts the authorization.
9267 MockRead data_reads3[] = {
9268 MockRead("HTTP/1.0 200 OK\r\n"),
9269 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069270 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239271 };
9272
Ryan Sleevib8d7ea02018-05-07 20:01:019273 StaticSocketDataProvider data1(data_reads1, data_writes1);
9274 StaticSocketDataProvider data2(data_reads2, data_writes2);
9275 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079276 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9277 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9278 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239279
[email protected]49639fa2011-12-20 23:22:419280 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239281
tfarina42834112016-09-22 13:38:209282 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019283 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239284
9285 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019286 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239287
bnc691fda62016-08-12 00:43:169288 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419289 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169290 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019291 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229292 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019293 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169294 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229295
bnc691fda62016-08-12 00:43:169296 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529297 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589298 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239299
[email protected]49639fa2011-12-20 23:22:419300 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239301
bnc691fda62016-08-12 00:43:169302 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9303 callback3.callback());
robpercival214763f2016-07-01 23:27:019304 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239305
[email protected]0757e7702009-03-27 04:00:229306 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019307 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239308
bnc691fda62016-08-12 00:43:169309 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529310 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589311 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239312 EXPECT_EQ(100, response->headers->GetContentLength());
9313 }
9314}
[email protected]89ceba9a2009-03-21 03:46:069315
[email protected]3c32c5f2010-05-18 15:18:129316// Tests that nonce count increments when multiple auth attempts
9317// are started with the same nonce.
bncd16676a2016-07-20 16:23:019318TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:449319 HttpAuthHandlerDigest::Factory* digest_factory =
9320 new HttpAuthHandlerDigest::Factory();
9321 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
9322 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
9323 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:079324 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:099325 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:129326
9327 // Transaction 1: authenticate (foo, bar) on MyRealm1
9328 {
[email protected]3c32c5f2010-05-18 15:18:129329 HttpRequestInfo request;
9330 request.method = "GET";
bncce36dca22015-04-21 22:11:239331 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:109332 request.traffic_annotation =
9333 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129334
bnc691fda62016-08-12 00:43:169335 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279336
[email protected]3c32c5f2010-05-18 15:18:129337 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239338 MockWrite(
9339 "GET /x/y/z HTTP/1.1\r\n"
9340 "Host: www.example.org\r\n"
9341 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129342 };
9343
9344 MockRead data_reads1[] = {
9345 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9346 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
9347 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069348 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129349 };
9350
9351 // Resend with authorization (username=foo, password=bar)
9352 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239353 MockWrite(
9354 "GET /x/y/z HTTP/1.1\r\n"
9355 "Host: www.example.org\r\n"
9356 "Connection: keep-alive\r\n"
9357 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9358 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
9359 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
9360 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129361 };
9362
9363 // Sever accepts the authorization.
9364 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:089365 MockRead("HTTP/1.0 200 OK\r\n"),
9366 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129367 };
9368
Ryan Sleevib8d7ea02018-05-07 20:01:019369 StaticSocketDataProvider data1(data_reads1, data_writes1);
9370 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079371 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9372 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:129373
[email protected]49639fa2011-12-20 23:22:419374 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129375
tfarina42834112016-09-22 13:38:209376 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019377 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129378
9379 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019380 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129381
bnc691fda62016-08-12 00:43:169382 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529383 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589384 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:129385
[email protected]49639fa2011-12-20 23:22:419386 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:129387
bnc691fda62016-08-12 00:43:169388 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9389 callback2.callback());
robpercival214763f2016-07-01 23:27:019390 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129391
9392 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019393 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129394
bnc691fda62016-08-12 00:43:169395 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529396 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589397 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129398 }
9399
9400 // ------------------------------------------------------------------------
9401
9402 // Transaction 2: Request another resource in digestive's protection space.
9403 // This will preemptively add an Authorization header which should have an
9404 // "nc" value of 2 (as compared to 1 in the first use.
9405 {
[email protected]3c32c5f2010-05-18 15:18:129406 HttpRequestInfo request;
9407 request.method = "GET";
9408 // Note that Transaction 1 was at /x/y/z, so this is in the same
9409 // protection space as digest.
bncce36dca22015-04-21 22:11:239410 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:109411 request.traffic_annotation =
9412 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129413
bnc691fda62016-08-12 00:43:169414 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279415
[email protected]3c32c5f2010-05-18 15:18:129416 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239417 MockWrite(
9418 "GET /x/y/a/b HTTP/1.1\r\n"
9419 "Host: www.example.org\r\n"
9420 "Connection: keep-alive\r\n"
9421 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9422 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
9423 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
9424 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129425 };
9426
9427 // Sever accepts the authorization.
9428 MockRead data_reads1[] = {
9429 MockRead("HTTP/1.0 200 OK\r\n"),
9430 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069431 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129432 };
9433
Ryan Sleevib8d7ea02018-05-07 20:01:019434 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079435 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:129436
[email protected]49639fa2011-12-20 23:22:419437 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129438
tfarina42834112016-09-22 13:38:209439 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019440 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129441
9442 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019443 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129444
bnc691fda62016-08-12 00:43:169445 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529446 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589447 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129448 }
9449}
9450
[email protected]89ceba9a2009-03-21 03:46:069451// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:019452TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:069453 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:099454 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169455 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:069456
9457 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:449458 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:169459 trans.read_buf_len_ = 15;
9460 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:069461
9462 // Setup state in response_
bnc691fda62016-08-12 00:43:169463 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:589464 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:089465 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:579466 response->response_time = base::Time::Now();
9467 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:069468
9469 { // Setup state for response_.vary_data
9470 HttpRequestInfo request;
9471 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
9472 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:279473 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:439474 request.extra_headers.SetHeader("Foo", "1");
9475 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:509476 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:069477 }
9478
9479 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:169480 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:069481
9482 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:169483 EXPECT_FALSE(trans.read_buf_);
9484 EXPECT_EQ(0, trans.read_buf_len_);
9485 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:589486 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:529487 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:049488 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:089489 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:579490 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:069491}
9492
[email protected]bacff652009-03-31 17:50:339493// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:019494TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:339495 HttpRequestInfo request;
9496 request.method = "GET";
bncce36dca22015-04-21 22:11:239497 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109498 request.traffic_annotation =
9499 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339500
danakj1fd259a02016-04-16 03:17:099501 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169502 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279503
[email protected]bacff652009-03-31 17:50:339504 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239505 MockWrite(
9506 "GET / HTTP/1.1\r\n"
9507 "Host: www.example.org\r\n"
9508 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339509 };
9510
9511 MockRead data_reads[] = {
9512 MockRead("HTTP/1.0 200 OK\r\n"),
9513 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9514 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069515 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339516 };
9517
[email protected]5ecc992a42009-11-11 01:41:599518 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:019519 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069520 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9521 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339522
[email protected]bb88e1d32013-05-03 23:11:079523 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9524 session_deps_.socket_factory->AddSocketDataProvider(&data);
9525 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9526 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339527
[email protected]49639fa2011-12-20 23:22:419528 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339529
tfarina42834112016-09-22 13:38:209530 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019531 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339532
9533 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019534 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339535
bnc691fda62016-08-12 00:43:169536 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019537 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339538
9539 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019540 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339541
bnc691fda62016-08-12 00:43:169542 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339543
wezca1070932016-05-26 20:30:529544 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339545 EXPECT_EQ(100, response->headers->GetContentLength());
9546}
9547
9548// Test HTTPS connections to a site with a bad certificate, going through a
9549// proxy
bncd16676a2016-07-20 16:23:019550TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499551 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9552 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339553
9554 HttpRequestInfo request;
9555 request.method = "GET";
bncce36dca22015-04-21 22:11:239556 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109557 request.traffic_annotation =
9558 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339559
9560 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:179561 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9562 "Host: www.example.org:443\r\n"
9563 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339564 };
9565
9566 MockRead proxy_reads[] = {
9567 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069568 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:339569 };
9570
9571 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179572 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9573 "Host: www.example.org:443\r\n"
9574 "Proxy-Connection: keep-alive\r\n\r\n"),
9575 MockWrite("GET / HTTP/1.1\r\n"
9576 "Host: www.example.org\r\n"
9577 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339578 };
9579
9580 MockRead data_reads[] = {
9581 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9582 MockRead("HTTP/1.0 200 OK\r\n"),
9583 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9584 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069585 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339586 };
9587
Ryan Sleevib8d7ea02018-05-07 20:01:019588 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
9589 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069590 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9591 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339592
[email protected]bb88e1d32013-05-03 23:11:079593 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9594 session_deps_.socket_factory->AddSocketDataProvider(&data);
9595 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9596 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339597
[email protected]49639fa2011-12-20 23:22:419598 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339599
9600 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:079601 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:339602
danakj1fd259a02016-04-16 03:17:099603 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169604 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:339605
tfarina42834112016-09-22 13:38:209606 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019607 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339608
9609 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019610 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339611
bnc691fda62016-08-12 00:43:169612 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019613 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339614
9615 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019616 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339617
bnc691fda62016-08-12 00:43:169618 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339619
wezca1070932016-05-26 20:30:529620 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339621 EXPECT_EQ(100, response->headers->GetContentLength());
9622 }
9623}
9624
[email protected]2df19bb2010-08-25 20:13:469625
9626// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:019627TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599628 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499629 ProxyResolutionService::CreateFixedFromPacResult(
9630 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519631 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079632 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:469633
9634 HttpRequestInfo request;
9635 request.method = "GET";
bncce36dca22015-04-21 22:11:239636 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109637 request.traffic_annotation =
9638 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:469639
9640 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179641 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9642 "Host: www.example.org:443\r\n"
9643 "Proxy-Connection: keep-alive\r\n\r\n"),
9644 MockWrite("GET / HTTP/1.1\r\n"
9645 "Host: www.example.org\r\n"
9646 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:469647 };
9648
9649 MockRead data_reads[] = {
9650 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9651 MockRead("HTTP/1.1 200 OK\r\n"),
9652 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9653 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069654 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:469655 };
9656
Ryan Sleevib8d7ea02018-05-07 20:01:019657 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069658 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9659 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:469660
[email protected]bb88e1d32013-05-03 23:11:079661 session_deps_.socket_factory->AddSocketDataProvider(&data);
9662 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9663 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:469664
[email protected]49639fa2011-12-20 23:22:419665 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:469666
danakj1fd259a02016-04-16 03:17:099667 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169668 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:469669
tfarina42834112016-09-22 13:38:209670 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019671 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:469672
9673 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019674 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169675 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:469676
wezca1070932016-05-26 20:30:529677 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:469678
tbansal2ecbbc72016-10-06 17:15:479679 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:469680 EXPECT_TRUE(response->headers->IsKeepAlive());
9681 EXPECT_EQ(200, response->headers->response_code());
9682 EXPECT_EQ(100, response->headers->GetContentLength());
9683 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:209684
9685 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:169686 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:209687 TestLoadTimingNotReusedWithPac(load_timing_info,
9688 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:469689}
9690
Eric Roman695a7872019-04-16 21:53:299691// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:019692TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599693 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499694 ProxyResolutionService::CreateFixedFromPacResult(
9695 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519696 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079697 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:299698
Matt Menkeecfecfc72019-02-05 19:15:289699 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9700 session_deps_.host_resolver->set_ondemand_mode(true);
9701
[email protected]511f6f52010-12-17 03:58:299702 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:129703 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:299704 request.method = "GET";
bncce36dca22015-04-21 22:11:239705 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109706 request.traffic_annotation =
9707 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299708
9709 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:289710 MockWrite(ASYNC, 0,
9711 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:179712 "Host: www.example.org:443\r\n"
9713 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299714 };
9715
9716 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289717 // Pause on first read.
9718 MockRead(ASYNC, ERR_IO_PENDING, 1),
9719 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
9720 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
9721 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299722 };
9723
Matt Menkeecfecfc72019-02-05 19:15:289724 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069725 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299726
[email protected]bb88e1d32013-05-03 23:11:079727 session_deps_.socket_factory->AddSocketDataProvider(&data);
9728 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299729
[email protected]49639fa2011-12-20 23:22:419730 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299731
danakj1fd259a02016-04-16 03:17:099732 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169733 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299734
tfarina42834112016-09-22 13:38:209735 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019736 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289737 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
9738
9739 // Host resolution takes |kTimeIncrement|.
9740 FastForwardBy(kTimeIncrement);
9741 // Resolving the current request with |ResolveNow| will cause the pending
9742 // request to instantly complete, and the async connect will start as well.
9743 session_deps_.host_resolver->ResolveOnlyRequestNow();
9744
9745 // Connecting takes |kTimeIncrement|.
9746 FastForwardBy(kTimeIncrement);
9747 data.RunUntilPaused();
9748
9749 // The server takes |kTimeIncrement| to respond.
9750 FastForwardBy(kTimeIncrement);
9751 data.Resume();
[email protected]511f6f52010-12-17 03:58:299752
9753 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599754 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299755}
9756
Eric Roman74103c72019-02-21 00:23:129757// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
9758TEST_F(HttpNetworkTransactionTest,
9759 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
9760 base::HistogramTester histograms;
9761 session_deps_.proxy_resolution_service =
9762 ProxyResolutionService::CreateFixedFromPacResult(
9763 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9764 TestNetLog net_log;
9765 session_deps_.net_log = &net_log;
9766
9767 HttpRequestInfo request;
9768 request.method = "GET";
9769 request.url = GURL("https://www.example.org/");
9770 request.traffic_annotation =
9771 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9772
9773 MockWrite data_writes[] = {
9774 MockWrite(ASYNC, 0,
9775 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9776 "Host: www.example.org:443\r\n"
9777 "Proxy-Connection: keep-alive\r\n\r\n"),
9778 };
9779
9780 MockRead data_reads[] = {
9781 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9782 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9783 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9784 };
9785
9786 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9787 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9788
9789 session_deps_.socket_factory->AddSocketDataProvider(&data);
9790 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9791
9792 TestCompletionCallback callback;
9793
9794 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9795 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9796
9797 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9798 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9799
9800 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599801 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129802}
9803
9804// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
9805// request for main frames.
9806TEST_F(HttpNetworkTransactionTest,
9807 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
9808 base::HistogramTester histograms;
9809 session_deps_.proxy_resolution_service =
9810 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
9811 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9812 TestNetLog net_log;
9813 session_deps_.net_log = &net_log;
9814
9815 HttpRequestInfo request;
9816 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
9817 request.method = "GET";
9818 request.url = GURL("https://www.example.org/");
9819 request.traffic_annotation =
9820 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9821
9822 MockWrite data_writes[] = {
9823 MockWrite(ASYNC, 0,
9824 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9825 "Host: www.example.org:443\r\n"
9826 "Proxy-Connection: keep-alive\r\n\r\n"),
9827 };
9828
9829 MockRead data_reads[] = {
9830 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9831 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9832 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9833 };
9834
9835 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9836 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9837
9838 session_deps_.socket_factory->AddSocketDataProvider(&data);
9839 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9840
9841 TestCompletionCallback callback;
9842
9843 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9844 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9845
9846 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9847 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9848
9849 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599850 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129851}
9852
Eric Roman695a7872019-04-16 21:53:299853// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:129854// frames.
bncd16676a2016-07-20 16:23:019855TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:129856 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:499857 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9858 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:289859 TestNetLog net_log;
9860 session_deps_.net_log = &net_log;
9861
Matt Menkeecfecfc72019-02-05 19:15:289862 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9863 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:299864
9865 HttpRequestInfo request;
9866 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:129867 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:239868 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109869 request.traffic_annotation =
9870 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299871
Ryan Hamilton0239aac2018-05-19 00:03:139872 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049873 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9874 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139875 spdy::SpdySerializedFrame goaway(
9876 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299877 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419878 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:289879 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:299880 };
9881
9882 static const char* const kExtraHeaders[] = {
9883 "location",
9884 "http://login.example.com/",
9885 };
Ryan Hamilton0239aac2018-05-19 00:03:139886 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249887 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:299888 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289889 // Pause on first read.
9890 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
9891 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299892 };
9893
Matt Menkeecfecfc72019-02-05 19:15:289894 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069895 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369896 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299897
[email protected]bb88e1d32013-05-03 23:11:079898 session_deps_.socket_factory->AddSocketDataProvider(&data);
9899 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299900
[email protected]49639fa2011-12-20 23:22:419901 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299902
danakj1fd259a02016-04-16 03:17:099903 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169904 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299905
tfarina42834112016-09-22 13:38:209906 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019907 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289908 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:299909
Matt Menkeecfecfc72019-02-05 19:15:289910 // Host resolution takes |kTimeIncrement|.
9911 FastForwardBy(kTimeIncrement);
9912 // Resolving the current request with |ResolveNow| will cause the pending
9913 // request to instantly complete, and the async connect will start as well.
9914 session_deps_.host_resolver->ResolveOnlyRequestNow();
9915
9916 // Connecting takes |kTimeIncrement|.
9917 FastForwardBy(kTimeIncrement);
9918 data.RunUntilPaused();
9919
9920 FastForwardBy(kTimeIncrement);
9921 data.Resume();
[email protected]511f6f52010-12-17 03:58:299922 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599923 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299924}
9925
[email protected]4eddbc732012-08-09 05:40:179926// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019927TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499928 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9929 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299930
9931 HttpRequestInfo request;
9932 request.method = "GET";
bncce36dca22015-04-21 22:11:239933 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109934 request.traffic_annotation =
9935 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299936
9937 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179938 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9939 "Host: www.example.org:443\r\n"
9940 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299941 };
9942
9943 MockRead data_reads[] = {
9944 MockRead("HTTP/1.1 404 Not Found\r\n"),
9945 MockRead("Content-Length: 23\r\n\r\n"),
9946 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:069947 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:299948 };
9949
Ryan Sleevib8d7ea02018-05-07 20:01:019950 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069951 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299952
[email protected]bb88e1d32013-05-03 23:11:079953 session_deps_.socket_factory->AddSocketDataProvider(&data);
9954 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299955
[email protected]49639fa2011-12-20 23:22:419956 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299957
danakj1fd259a02016-04-16 03:17:099958 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169959 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299960
tfarina42834112016-09-22 13:38:209961 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019962 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299963
9964 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019965 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299966
ttuttle960fcbf2016-04-19 13:26:329967 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299968}
9969
[email protected]4eddbc732012-08-09 05:40:179970// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019971TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499972 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9973 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299974
9975 HttpRequestInfo request;
9976 request.method = "GET";
bncce36dca22015-04-21 22:11:239977 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109978 request.traffic_annotation =
9979 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299980
Ryan Hamilton0239aac2018-05-19 00:03:139981 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049982 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9983 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139984 spdy::SpdySerializedFrame rst(
9985 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299986 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419987 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:299988 };
9989
9990 static const char* const kExtraHeaders[] = {
9991 "location",
9992 "http://login.example.com/",
9993 };
Ryan Hamilton0239aac2018-05-19 00:03:139994 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249995 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:139996 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:199997 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:299998 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:419999 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1310000 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910001 };
10002
Ryan Sleevib8d7ea02018-05-07 20:01:0110003 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610004 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610005 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910006
[email protected]bb88e1d32013-05-03 23:11:0710007 session_deps_.socket_factory->AddSocketDataProvider(&data);
10008 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910009
[email protected]49639fa2011-12-20 23:22:4110010 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910011
danakj1fd259a02016-04-16 03:17:0910012 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610013 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910014
tfarina42834112016-09-22 13:38:2010015 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110016 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910017
10018 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110019 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910020
ttuttle960fcbf2016-04-19 13:26:3210021 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910022}
10023
[email protected]0c5fb722012-02-28 11:50:3510024// Test the request-challenge-retry sequence for basic auth, through
10025// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0110026TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3510027 HttpRequestInfo request;
10028 request.method = "GET";
bncce36dca22015-04-21 22:11:2310029 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3510030 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:2910031 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:1010032 request.traffic_annotation =
10033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3510034
10035 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5910036 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910037 ProxyResolutionService::CreateFixedFromPacResult(
10038 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110039 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710040 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0910041 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3510042
10043 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1310044 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410045 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10046 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310047 spdy::SpdySerializedFrame rst(
10048 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3810049 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3510050
bnc691fda62016-08-12 00:43:1610051 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3510052 // be issuing -- the final header line contains the credentials.
10053 const char* const kAuthCredentials[] = {
10054 "proxy-authorization", "Basic Zm9vOmJhcg==",
10055 };
Ryan Hamilton0239aac2018-05-19 00:03:1310056 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410057 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
10058 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2310059 HostPortPair("www.example.org", 443)));
10060 // fetch https://www.example.org/ via HTTP
10061 const char get[] =
10062 "GET / HTTP/1.1\r\n"
10063 "Host: www.example.org\r\n"
10064 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1310065 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1910066 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3510067
10068 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110069 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
10070 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3510071 };
10072
10073 // The proxy responds to the connect with a 407, using a persistent
10074 // connection.
thestig9d3bb0c2015-01-24 00:49:5110075 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3510076 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3510077 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
10078 };
Ryan Hamilton0239aac2018-05-19 00:03:1310079 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410080 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3510081
Ryan Hamilton0239aac2018-05-19 00:03:1310082 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3510083 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3510084 const char resp[] = "HTTP/1.1 200 OK\r\n"
10085 "Content-Length: 5\r\n\r\n";
10086
Ryan Hamilton0239aac2018-05-19 00:03:1310087 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1910088 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1310089 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1910090 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3510091 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110092 CreateMockRead(conn_auth_resp, 1, ASYNC),
10093 CreateMockRead(conn_resp, 4, ASYNC),
10094 CreateMockRead(wrapped_get_resp, 6, ASYNC),
10095 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1310096 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3510097 };
10098
Ryan Sleevib8d7ea02018-05-07 20:01:0110099 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710100 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3510101 // Negotiate SPDY to the proxy
10102 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610103 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710104 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3510105 // Vanilla SSL to the server
10106 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710107 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3510108
10109 TestCompletionCallback callback1;
10110
bnc87dcefc2017-05-25 12:47:5810111 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910112 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3510113
10114 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110115 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510116
10117 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110118 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5410119 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3510120 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0010121 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10122 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510123 ExpectLogContainsSomewhere(
10124 entries, pos,
mikecirone8b85c432016-09-08 19:11:0010125 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10126 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510127
10128 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210129 ASSERT_TRUE(response);
10130 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3510131 EXPECT_EQ(407, response->headers->response_code());
10132 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5810133 EXPECT_TRUE(response->auth_challenge.has_value());
10134 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3510135
10136 TestCompletionCallback callback2;
10137
10138 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
10139 callback2.callback());
robpercival214763f2016-07-01 23:27:0110140 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510141
10142 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110143 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3510144
10145 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210146 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3510147
10148 EXPECT_TRUE(response->headers->IsKeepAlive());
10149 EXPECT_EQ(200, response->headers->response_code());
10150 EXPECT_EQ(5, response->headers->GetContentLength());
10151 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10152
10153 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810154 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510155
[email protected]029c83b62013-01-24 05:28:2010156 LoadTimingInfo load_timing_info;
10157 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10158 TestLoadTimingNotReusedWithPac(load_timing_info,
10159 CONNECT_TIMING_HAS_SSL_TIMES);
10160
[email protected]0c5fb722012-02-28 11:50:3510161 trans.reset();
10162 session->CloseAllConnections();
10163}
10164
[email protected]7c6f7ba2012-04-03 04:09:2910165// Test that an explicitly trusted SPDY proxy can push a resource from an
10166// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0110167TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1510168 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910169 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510170 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10171 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2910172 HttpRequestInfo request;
10173 HttpRequestInfo push_request;
Ramin Halavatib5e433e2018-02-07 07:41:1010174 request.traffic_annotation =
10175 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910176
[email protected]7c6f7ba2012-04-03 04:09:2910177 request.method = "GET";
bncce36dca22015-04-21 22:11:2310178 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910179 push_request.method = "GET";
10180 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e2018-02-07 07:41:1010181 push_request.traffic_annotation =
10182 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910183
tbansal28e68f82016-02-04 02:56:1510184 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910185 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910186 ProxyResolutionService::CreateFixedFromPacResult(
10187 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110188 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710189 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010190
Eric Roman3d8546a2018-09-10 17:00:5210191 session_deps_.proxy_resolution_service->SetProxyDelegate(
10192 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010193
danakj1fd259a02016-04-16 03:17:0910194 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910195
Ryan Hamilton0239aac2018-05-19 00:03:1310196 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510197 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310198 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510199 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910200
10201 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110202 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510203 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910204 };
10205
Ryan Hamilton0239aac2018-05-19 00:03:1310206 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510207 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610208
Ryan Hamilton0239aac2018-05-19 00:03:1310209 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510210 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910211
Ryan Hamilton0239aac2018-05-19 00:03:1310212 spdy::SpdySerializedFrame stream1_body(
10213 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910214
Ryan Hamilton0239aac2018-05-19 00:03:1310215 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910216 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910217
10218 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610219 CreateMockRead(stream2_syn, 1, ASYNC),
10220 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510221 CreateMockRead(stream1_body, 4, ASYNC),
10222 CreateMockRead(stream2_body, 5, ASYNC),
10223 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910224 };
10225
Ryan Sleevib8d7ea02018-05-07 20:01:0110226 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710227 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910228 // Negotiate SPDY to the proxy
10229 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610230 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710231 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910232
bnc87dcefc2017-05-25 12:47:5810233 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910234 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910235 TestCompletionCallback callback;
10236 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110237 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910238
10239 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110240 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910241 const HttpResponseInfo* response = trans->GetResponseInfo();
10242
bnc87dcefc2017-05-25 12:47:5810243 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910244 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010245 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110246 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910247
10248 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110249 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910250 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10251
wezca1070932016-05-26 20:30:5210252 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910253 EXPECT_TRUE(response->headers->IsKeepAlive());
10254
10255 EXPECT_EQ(200, response->headers->response_code());
10256 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10257
10258 std::string response_data;
10259 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110260 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910261 EXPECT_EQ("hello!", response_data);
10262
[email protected]029c83b62013-01-24 05:28:2010263 LoadTimingInfo load_timing_info;
10264 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10265 TestLoadTimingNotReusedWithPac(load_timing_info,
10266 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10267
[email protected]7c6f7ba2012-04-03 04:09:2910268 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210269 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910270 EXPECT_EQ(200, push_response->headers->response_code());
10271
10272 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110273 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910274 EXPECT_EQ("pushed", response_data);
10275
[email protected]029c83b62013-01-24 05:28:2010276 LoadTimingInfo push_load_timing_info;
10277 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10278 TestLoadTimingReusedWithPac(push_load_timing_info);
10279 // The transactions should share a socket ID, despite being for different
10280 // origins.
10281 EXPECT_EQ(load_timing_info.socket_log_id,
10282 push_load_timing_info.socket_log_id);
10283
[email protected]7c6f7ba2012-04-03 04:09:2910284 trans.reset();
10285 push_trans.reset();
10286 session->CloseAllConnections();
10287}
10288
[email protected]8c843192012-04-05 07:15:0010289// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110290TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510291 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910292 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510293 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10294 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010295 HttpRequestInfo request;
10296
10297 request.method = "GET";
bncce36dca22015-04-21 22:11:2310298 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010299 request.traffic_annotation =
10300 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010301
Ramin Halavatica8d5252018-03-12 05:33:4910302 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10303 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110304 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710305 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010306
10307 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210308 session_deps_.proxy_resolution_service->SetProxyDelegate(
10309 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010310
danakj1fd259a02016-04-16 03:17:0910311 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010312
Ryan Hamilton0239aac2018-05-19 00:03:1310313 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510314 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010315
Ryan Hamilton0239aac2018-05-19 00:03:1310316 spdy::SpdySerializedFrame push_rst(
10317 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0010318
10319 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110320 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0010321 };
10322
Ryan Hamilton0239aac2018-05-19 00:03:1310323 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510324 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0010325
Ryan Hamilton0239aac2018-05-19 00:03:1310326 spdy::SpdySerializedFrame stream1_body(
10327 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0010328
Ryan Hamilton0239aac2018-05-19 00:03:1310329 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510330 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0010331
10332 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110333 CreateMockRead(stream1_reply, 1, ASYNC),
10334 CreateMockRead(stream2_syn, 2, ASYNC),
10335 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5910336 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0010337 };
10338
Ryan Sleevib8d7ea02018-05-07 20:01:0110339 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710340 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0010341 // Negotiate SPDY to the proxy
10342 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610343 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710344 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0010345
bnc87dcefc2017-05-25 12:47:5810346 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910347 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0010348 TestCompletionCallback callback;
10349 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110350 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0010351
10352 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110353 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010354 const HttpResponseInfo* response = trans->GetResponseInfo();
10355
wezca1070932016-05-26 20:30:5210356 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0010357 EXPECT_TRUE(response->headers->IsKeepAlive());
10358
10359 EXPECT_EQ(200, response->headers->response_code());
10360 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10361
10362 std::string response_data;
10363 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110364 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010365 EXPECT_EQ("hello!", response_data);
10366
10367 trans.reset();
10368 session->CloseAllConnections();
10369}
10370
tbansal8ef1d3e2016-02-03 04:05:4210371// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
10372// resources.
bncd16676a2016-07-20 16:23:0110373TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510374 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910375 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510376 proxy_delegate->set_trusted_spdy_proxy(
10377 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
10378
tbansal8ef1d3e2016-02-03 04:05:4210379 HttpRequestInfo request;
10380
10381 request.method = "GET";
10382 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010383 request.traffic_annotation =
10384 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210385
10386 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4910387 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10388 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210389 BoundTestNetLog log;
10390 session_deps_.net_log = log.bound().net_log();
10391
10392 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210393 session_deps_.proxy_resolution_service->SetProxyDelegate(
10394 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4210395
danakj1fd259a02016-04-16 03:17:0910396 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4210397
Ryan Hamilton0239aac2018-05-19 00:03:1310398 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510399 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310400 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510401 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4210402
10403 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110404 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510405 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4210406 };
10407
Ryan Hamilton0239aac2018-05-19 00:03:1310408 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1510409 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210410
Ryan Hamilton0239aac2018-05-19 00:03:1310411 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3310412 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4910413
Ryan Hamilton0239aac2018-05-19 00:03:1310414 spdy::SpdySerializedFrame stream1_body(
10415 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210416
Ryan Hamilton0239aac2018-05-19 00:03:1310417 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1510418 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210419
Ryan Hamilton0239aac2018-05-19 00:03:1310420 spdy::SpdySerializedFrame stream2_body(
10421 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210422
10423 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110424 CreateMockRead(stream1_reply, 1, ASYNC),
10425 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510426 CreateMockRead(stream1_body, 4, ASYNC),
10427 CreateMockRead(stream2_body, 5, ASYNC),
10428 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4210429 };
10430
Ryan Sleevib8d7ea02018-05-07 20:01:0110431 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4210432 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10433 // Negotiate SPDY to the proxy
10434 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610435 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4210436 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
10437
bnc87dcefc2017-05-25 12:47:5810438 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910439 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4210440 TestCompletionCallback callback;
10441 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110442 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4210443
10444 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110445 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210446 const HttpResponseInfo* response = trans->GetResponseInfo();
10447
wezca1070932016-05-26 20:30:5210448 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4210449 EXPECT_TRUE(response->headers->IsKeepAlive());
10450
10451 EXPECT_EQ(200, response->headers->response_code());
10452 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10453
10454 std::string response_data;
10455 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110456 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210457 EXPECT_EQ("hello!", response_data);
10458
10459 trans.reset();
10460 session->CloseAllConnections();
10461}
10462
[email protected]2df19bb2010-08-25 20:13:4610463// Test HTTPS connections to a site with a bad certificate, going through an
10464// HTTPS proxy
bncd16676a2016-07-20 16:23:0110465TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910466 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10467 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610468
10469 HttpRequestInfo request;
10470 request.method = "GET";
bncce36dca22015-04-21 22:11:2310471 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010472 request.traffic_annotation =
10473 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610474
10475 // Attempt to fetch the URL from a server with a bad cert
10476 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710477 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10478 "Host: www.example.org:443\r\n"
10479 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610480 };
10481
10482 MockRead bad_cert_reads[] = {
10483 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610484 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4610485 };
10486
10487 // Attempt to fetch the URL with a good cert
10488 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710489 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10490 "Host: www.example.org:443\r\n"
10491 "Proxy-Connection: keep-alive\r\n\r\n"),
10492 MockWrite("GET / HTTP/1.1\r\n"
10493 "Host: www.example.org\r\n"
10494 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610495 };
10496
10497 MockRead good_cert_reads[] = {
10498 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10499 MockRead("HTTP/1.0 200 OK\r\n"),
10500 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10501 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610502 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610503 };
10504
Ryan Sleevib8d7ea02018-05-07 20:01:0110505 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
10506 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0610507 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10508 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4610509
10510 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0710511 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10512 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10513 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4610514
10515 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0710516 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10517 session_deps_.socket_factory->AddSocketDataProvider(&data);
10518 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4610519
[email protected]49639fa2011-12-20 23:22:4110520 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610521
danakj1fd259a02016-04-16 03:17:0910522 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610523 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610524
tfarina42834112016-09-22 13:38:2010525 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610527
10528 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110529 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4610530
bnc691fda62016-08-12 00:43:1610531 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110532 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610533
10534 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110535 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4610536
bnc691fda62016-08-12 00:43:1610537 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610538
wezca1070932016-05-26 20:30:5210539 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610540 EXPECT_EQ(100, response->headers->GetContentLength());
10541}
10542
bncd16676a2016-07-20 16:23:0110543TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4210544 HttpRequestInfo request;
10545 request.method = "GET";
bncce36dca22015-04-21 22:11:2310546 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310547 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10548 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e2018-02-07 07:41:1010549 request.traffic_annotation =
10550 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210551
danakj1fd259a02016-04-16 03:17:0910552 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610553 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710554
[email protected]1c773ea12009-04-28 19:58:4210555 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310556 MockWrite(
10557 "GET / HTTP/1.1\r\n"
10558 "Host: www.example.org\r\n"
10559 "Connection: keep-alive\r\n"
10560 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210561 };
10562
10563 // Lastly, the server responds with the actual content.
10564 MockRead data_reads[] = {
10565 MockRead("HTTP/1.0 200 OK\r\n"),
10566 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10567 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610568 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210569 };
10570
Ryan Sleevib8d7ea02018-05-07 20:01:0110571 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710572 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210573
[email protected]49639fa2011-12-20 23:22:4110574 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210575
tfarina42834112016-09-22 13:38:2010576 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110577 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210578
10579 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110580 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210581}
10582
bncd16676a2016-07-20 16:23:0110583TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0010584 // Test user agent values, used both for the request header of the original
10585 // request, and the value returned by the HttpUserAgentSettings. nullptr means
10586 // no request header / no HttpUserAgentSettings object.
10587 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2910588
Matt Menked732ea42019-03-08 12:05:0010589 for (const char* setting_user_agent : kTestUserAgents) {
10590 if (!setting_user_agent) {
10591 session_deps_.http_user_agent_settings.reset();
10592 } else {
10593 session_deps_.http_user_agent_settings =
10594 std::make_unique<StaticHttpUserAgentSettings>(
10595 std::string() /* accept-language */, setting_user_agent);
10596 }
10597 session_deps_.proxy_resolution_service =
10598 ProxyResolutionService::CreateFixed("myproxy:70",
10599 TRAFFIC_ANNOTATION_FOR_TESTS);
10600 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10601 for (const char* request_user_agent : kTestUserAgents) {
10602 HttpRequestInfo request;
10603 request.method = "GET";
10604 request.url = GURL("https://www.example.org/");
10605 if (request_user_agent) {
10606 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10607 request_user_agent);
10608 }
10609 request.traffic_annotation =
10610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710611
Matt Menked732ea42019-03-08 12:05:0010612 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2910613
Matt Menked732ea42019-03-08 12:05:0010614 std::string expected_request;
10615 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
10616 expected_request =
10617 "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";
10620 } else {
10621 expected_request = base::StringPrintf(
10622 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10623 "Host: www.example.org:443\r\n"
10624 "Proxy-Connection: keep-alive\r\n"
10625 "User-Agent: %s\r\n\r\n",
10626 setting_user_agent);
10627 }
10628 MockWrite data_writes[] = {
10629 MockWrite(expected_request.c_str()),
10630 };
10631 MockRead data_reads[] = {
10632 // Return an error, so the transaction stops here (this test isn't
10633 // interested in the rest).
10634 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10635 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10636 MockRead("Proxy-Connection: close\r\n\r\n"),
10637 };
[email protected]da81f132010-08-18 23:39:2910638
Matt Menked732ea42019-03-08 12:05:0010639 StaticSocketDataProvider data(data_reads, data_writes);
10640 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2910641
Matt Menked732ea42019-03-08 12:05:0010642 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2910643
Matt Menked732ea42019-03-08 12:05:0010644 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10645 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10646
10647 rv = callback.WaitForResult();
10648 EXPECT_THAT(rv, IsOk());
10649 }
10650 }
[email protected]da81f132010-08-18 23:39:2910651}
10652
bncd16676a2016-07-20 16:23:0110653TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4210654 HttpRequestInfo request;
10655 request.method = "GET";
bncce36dca22015-04-21 22:11:2310656 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1610657 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
10658 "http://the.previous.site.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1010659 request.traffic_annotation =
10660 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210661
danakj1fd259a02016-04-16 03:17:0910662 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610663 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710664
[email protected]1c773ea12009-04-28 19:58:4210665 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310666 MockWrite(
10667 "GET / HTTP/1.1\r\n"
10668 "Host: www.example.org\r\n"
10669 "Connection: keep-alive\r\n"
10670 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210671 };
10672
10673 // Lastly, the server responds with the actual content.
10674 MockRead data_reads[] = {
10675 MockRead("HTTP/1.0 200 OK\r\n"),
10676 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10677 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610678 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210679 };
10680
Ryan Sleevib8d7ea02018-05-07 20:01:0110681 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710682 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210683
[email protected]49639fa2011-12-20 23:22:4110684 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210685
tfarina42834112016-09-22 13:38:2010686 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110687 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210688
10689 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110690 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210691}
10692
bncd16676a2016-07-20 16:23:0110693TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210694 HttpRequestInfo request;
10695 request.method = "POST";
bncce36dca22015-04-21 22:11:2310696 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010697 request.traffic_annotation =
10698 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210699
danakj1fd259a02016-04-16 03:17:0910700 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610701 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710702
[email protected]1c773ea12009-04-28 19:58:4210703 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310704 MockWrite(
10705 "POST / HTTP/1.1\r\n"
10706 "Host: www.example.org\r\n"
10707 "Connection: keep-alive\r\n"
10708 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210709 };
10710
10711 // Lastly, the server responds with the actual content.
10712 MockRead data_reads[] = {
10713 MockRead("HTTP/1.0 200 OK\r\n"),
10714 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10715 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610716 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210717 };
10718
Ryan Sleevib8d7ea02018-05-07 20:01:0110719 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710720 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210721
[email protected]49639fa2011-12-20 23:22:4110722 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210723
tfarina42834112016-09-22 13:38:2010724 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110725 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210726
10727 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110728 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210729}
10730
bncd16676a2016-07-20 16:23:0110731TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210732 HttpRequestInfo request;
10733 request.method = "PUT";
bncce36dca22015-04-21 22:11:2310734 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010735 request.traffic_annotation =
10736 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210737
danakj1fd259a02016-04-16 03:17:0910738 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610739 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710740
[email protected]1c773ea12009-04-28 19:58:4210741 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310742 MockWrite(
10743 "PUT / HTTP/1.1\r\n"
10744 "Host: www.example.org\r\n"
10745 "Connection: keep-alive\r\n"
10746 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210747 };
10748
10749 // Lastly, the server responds with the actual content.
10750 MockRead data_reads[] = {
10751 MockRead("HTTP/1.0 200 OK\r\n"),
10752 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10753 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610754 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210755 };
10756
Ryan Sleevib8d7ea02018-05-07 20:01:0110757 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710758 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210759
[email protected]49639fa2011-12-20 23:22:4110760 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210761
tfarina42834112016-09-22 13:38:2010762 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110763 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210764
10765 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110766 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210767}
10768
bncd16676a2016-07-20 16:23:0110769TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210770 HttpRequestInfo request;
10771 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2310772 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010773 request.traffic_annotation =
10774 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210775
danakj1fd259a02016-04-16 03:17:0910776 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610777 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710778
[email protected]1c773ea12009-04-28 19:58:4210779 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1310780 MockWrite("HEAD / HTTP/1.1\r\n"
10781 "Host: www.example.org\r\n"
10782 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210783 };
10784
10785 // Lastly, the server responds with the actual content.
10786 MockRead data_reads[] = {
10787 MockRead("HTTP/1.0 200 OK\r\n"),
10788 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10789 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610790 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210791 };
10792
Ryan Sleevib8d7ea02018-05-07 20:01:0110793 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710794 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210795
[email protected]49639fa2011-12-20 23:22:4110796 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210797
tfarina42834112016-09-22 13:38:2010798 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110799 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210800
10801 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110802 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210803}
10804
bncd16676a2016-07-20 16:23:0110805TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4210806 HttpRequestInfo request;
10807 request.method = "GET";
bncce36dca22015-04-21 22:11:2310808 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210809 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1010810 request.traffic_annotation =
10811 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210812
danakj1fd259a02016-04-16 03:17:0910813 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610814 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710815
[email protected]1c773ea12009-04-28 19:58:4210816 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310817 MockWrite(
10818 "GET / HTTP/1.1\r\n"
10819 "Host: www.example.org\r\n"
10820 "Connection: keep-alive\r\n"
10821 "Pragma: no-cache\r\n"
10822 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210823 };
10824
10825 // Lastly, the server responds with the actual content.
10826 MockRead data_reads[] = {
10827 MockRead("HTTP/1.0 200 OK\r\n"),
10828 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10829 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610830 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210831 };
10832
Ryan Sleevib8d7ea02018-05-07 20:01:0110833 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710834 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210835
[email protected]49639fa2011-12-20 23:22:4110836 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210837
tfarina42834112016-09-22 13:38:2010838 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110839 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210840
10841 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110842 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210843}
10844
bncd16676a2016-07-20 16:23:0110845TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4210846 HttpRequestInfo request;
10847 request.method = "GET";
bncce36dca22015-04-21 22:11:2310848 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210849 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1010850 request.traffic_annotation =
10851 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210852
danakj1fd259a02016-04-16 03:17:0910853 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610854 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710855
[email protected]1c773ea12009-04-28 19:58:4210856 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310857 MockWrite(
10858 "GET / HTTP/1.1\r\n"
10859 "Host: www.example.org\r\n"
10860 "Connection: keep-alive\r\n"
10861 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210862 };
10863
10864 // Lastly, the server responds with the actual content.
10865 MockRead data_reads[] = {
10866 MockRead("HTTP/1.0 200 OK\r\n"),
10867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10868 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610869 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210870 };
10871
Ryan Sleevib8d7ea02018-05-07 20:01:0110872 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710873 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210874
[email protected]49639fa2011-12-20 23:22:4110875 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210876
tfarina42834112016-09-22 13:38:2010877 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110878 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210879
10880 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110881 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210882}
10883
bncd16676a2016-07-20 16:23:0110884TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4210885 HttpRequestInfo request;
10886 request.method = "GET";
bncce36dca22015-04-21 22:11:2310887 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310888 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e2018-02-07 07:41:1010889 request.traffic_annotation =
10890 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210891
danakj1fd259a02016-04-16 03:17:0910892 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610893 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710894
[email protected]1c773ea12009-04-28 19:58:4210895 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310896 MockWrite(
10897 "GET / HTTP/1.1\r\n"
10898 "Host: www.example.org\r\n"
10899 "Connection: keep-alive\r\n"
10900 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210901 };
10902
10903 // Lastly, the server responds with the actual content.
10904 MockRead data_reads[] = {
10905 MockRead("HTTP/1.0 200 OK\r\n"),
10906 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10907 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610908 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210909 };
10910
Ryan Sleevib8d7ea02018-05-07 20:01:0110911 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710912 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210913
[email protected]49639fa2011-12-20 23:22:4110914 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210915
tfarina42834112016-09-22 13:38:2010916 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110917 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210918
10919 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110920 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210921}
10922
bncd16676a2016-07-20 16:23:0110923TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4710924 HttpRequestInfo request;
10925 request.method = "GET";
bncce36dca22015-04-21 22:11:2310926 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310927 request.extra_headers.SetHeader("referer", "www.foo.com");
10928 request.extra_headers.SetHeader("hEllo", "Kitty");
10929 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e2018-02-07 07:41:1010930 request.traffic_annotation =
10931 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4710932
danakj1fd259a02016-04-16 03:17:0910933 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610934 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710935
[email protected]270c6412010-03-29 22:02:4710936 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310937 MockWrite(
10938 "GET / HTTP/1.1\r\n"
10939 "Host: www.example.org\r\n"
10940 "Connection: keep-alive\r\n"
10941 "referer: www.foo.com\r\n"
10942 "hEllo: Kitty\r\n"
10943 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4710944 };
10945
10946 // Lastly, the server responds with the actual content.
10947 MockRead data_reads[] = {
10948 MockRead("HTTP/1.0 200 OK\r\n"),
10949 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10950 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610951 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4710952 };
10953
Ryan Sleevib8d7ea02018-05-07 20:01:0110954 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710955 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4710956
[email protected]49639fa2011-12-20 23:22:4110957 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4710958
tfarina42834112016-09-22 13:38:2010959 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110960 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4710961
10962 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110963 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4710964}
10965
bncd16676a2016-07-20 16:23:0110966TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710967 HttpRequestInfo request;
10968 request.method = "GET";
bncce36dca22015-04-21 22:11:2310969 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010970 request.traffic_annotation =
10971 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710972
Lily Houghton8c2f97d2018-01-22 05:06:5910973 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910974 ProxyResolutionService::CreateFixedFromPacResult(
10975 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110976 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710977 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210978
danakj1fd259a02016-04-16 03:17:0910979 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610980 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210981
[email protected]3cd17242009-06-23 02:59:0210982 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10983 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10984
10985 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410986 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10987 MockWrite("GET / HTTP/1.1\r\n"
10988 "Host: www.example.org\r\n"
10989 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210990
10991 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410992 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10993 MockRead("HTTP/1.0 200 OK\r\n"),
10994 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10995 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0210996
Ryan Sleevib8d7ea02018-05-07 20:01:0110997 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710998 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0210999
[email protected]49639fa2011-12-20 23:22:4111000 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211001
tfarina42834112016-09-22 13:38:2011002 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111003 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211004
11005 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111006 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211007
bnc691fda62016-08-12 00:43:1611008 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211009 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0211010
tbansal2ecbbc72016-10-06 17:15:4711011 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2011012 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611013 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011014 TestLoadTimingNotReusedWithPac(load_timing_info,
11015 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11016
[email protected]3cd17242009-06-23 02:59:0211017 std::string response_text;
bnc691fda62016-08-12 00:43:1611018 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111019 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211020 EXPECT_EQ("Payload", response_text);
11021}
11022
bncd16676a2016-07-20 16:23:0111023TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711024 HttpRequestInfo request;
11025 request.method = "GET";
bncce36dca22015-04-21 22:11:2311026 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011027 request.traffic_annotation =
11028 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711029
Lily Houghton8c2f97d2018-01-22 05:06:5911030 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911031 ProxyResolutionService::CreateFixedFromPacResult(
11032 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111033 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711034 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211035
danakj1fd259a02016-04-16 03:17:0911036 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611037 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211038
[email protected]3cd17242009-06-23 02:59:0211039 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
11040 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11041
11042 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311043 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2411044 base::size(write_buffer)),
11045 MockWrite("GET / HTTP/1.1\r\n"
11046 "Host: www.example.org\r\n"
11047 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211048
11049 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411050 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
11051 base::size(read_buffer)),
11052 MockRead("HTTP/1.0 200 OK\r\n"),
11053 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11054 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511055
Ryan Sleevib8d7ea02018-05-07 20:01:0111056 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711057 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511058
[email protected]8ddf8322012-02-23 18:08:0611059 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711060 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3511061
[email protected]49639fa2011-12-20 23:22:4111062 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511063
tfarina42834112016-09-22 13:38:2011064 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111065 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511066
11067 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111068 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511069
[email protected]029c83b62013-01-24 05:28:2011070 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611071 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011072 TestLoadTimingNotReusedWithPac(load_timing_info,
11073 CONNECT_TIMING_HAS_SSL_TIMES);
11074
bnc691fda62016-08-12 00:43:1611075 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211076 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711077 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511078
11079 std::string response_text;
bnc691fda62016-08-12 00:43:1611080 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111081 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511082 EXPECT_EQ("Payload", response_text);
11083}
11084
bncd16676a2016-07-20 16:23:0111085TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2011086 HttpRequestInfo request;
11087 request.method = "GET";
bncce36dca22015-04-21 22:11:2311088 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011089 request.traffic_annotation =
11090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2011091
Ramin Halavatica8d5252018-03-12 05:33:4911092 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11093 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111094 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711095 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2011096
danakj1fd259a02016-04-16 03:17:0911097 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611098 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2011099
11100 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11101 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11102
11103 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411104 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11105 MockWrite("GET / HTTP/1.1\r\n"
11106 "Host: www.example.org\r\n"
11107 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2011108
11109 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411110 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11111 MockRead("HTTP/1.0 200 OK\r\n"),
11112 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11113 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2011114
Ryan Sleevib8d7ea02018-05-07 20:01:0111115 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711116 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2011117
11118 TestCompletionCallback callback;
11119
tfarina42834112016-09-22 13:38:2011120 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111121 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2011122
11123 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111124 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011125
bnc691fda62016-08-12 00:43:1611126 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211127 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2011128
11129 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611130 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011131 TestLoadTimingNotReused(load_timing_info,
11132 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11133
11134 std::string response_text;
bnc691fda62016-08-12 00:43:1611135 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111136 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011137 EXPECT_EQ("Payload", response_text);
11138}
11139
bncd16676a2016-07-20 16:23:0111140TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711141 HttpRequestInfo request;
11142 request.method = "GET";
bncce36dca22015-04-21 22:11:2311143 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011144 request.traffic_annotation =
11145 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711146
Lily Houghton8c2f97d2018-01-22 05:06:5911147 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911148 ProxyResolutionService::CreateFixedFromPacResult(
11149 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111150 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711151 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511152
danakj1fd259a02016-04-16 03:17:0911153 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611154 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511155
[email protected]e0c27be2009-07-15 13:09:3511156 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11157 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711158 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311159 0x05, // Version
11160 0x01, // Command (CONNECT)
11161 0x00, // Reserved.
11162 0x03, // Address type (DOMAINNAME).
11163 0x0F, // Length of domain (15)
11164 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11165 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3711166 };
[email protected]e0c27be2009-07-15 13:09:3511167 const char kSOCKS5OkResponse[] =
11168 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
11169
11170 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411171 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
11172 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
11173 MockWrite("GET / HTTP/1.1\r\n"
11174 "Host: www.example.org\r\n"
11175 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511176
11177 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411178 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11179 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11180 MockRead("HTTP/1.0 200 OK\r\n"),
11181 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11182 MockRead("Payload"),
11183 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511184
Ryan Sleevib8d7ea02018-05-07 20:01:0111185 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711186 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511187
[email protected]49639fa2011-12-20 23:22:4111188 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511189
tfarina42834112016-09-22 13:38:2011190 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111191 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511192
11193 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111194 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511195
bnc691fda62016-08-12 00:43:1611196 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211197 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711198 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511199
[email protected]029c83b62013-01-24 05:28:2011200 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611201 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011202 TestLoadTimingNotReusedWithPac(load_timing_info,
11203 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11204
[email protected]e0c27be2009-07-15 13:09:3511205 std::string response_text;
bnc691fda62016-08-12 00:43:1611206 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111207 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511208 EXPECT_EQ("Payload", response_text);
11209}
11210
bncd16676a2016-07-20 16:23:0111211TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711212 HttpRequestInfo request;
11213 request.method = "GET";
bncce36dca22015-04-21 22:11:2311214 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011215 request.traffic_annotation =
11216 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711217
Lily Houghton8c2f97d2018-01-22 05:06:5911218 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911219 ProxyResolutionService::CreateFixedFromPacResult(
11220 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111221 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711222 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511223
danakj1fd259a02016-04-16 03:17:0911224 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611225 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511226
[email protected]e0c27be2009-07-15 13:09:3511227 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11228 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711229 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311230 0x05, // Version
11231 0x01, // Command (CONNECT)
11232 0x00, // Reserved.
11233 0x03, // Address type (DOMAINNAME).
11234 0x0F, // Length of domain (15)
11235 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11236 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711237 };
11238
[email protected]e0c27be2009-07-15 13:09:3511239 const char kSOCKS5OkResponse[] =
11240 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11241
11242 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411243 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311244 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411245 base::size(kSOCKS5OkRequest)),
11246 MockWrite("GET / HTTP/1.1\r\n"
11247 "Host: www.example.org\r\n"
11248 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511249
11250 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411251 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11252 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11253 MockRead("HTTP/1.0 200 OK\r\n"),
11254 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11255 MockRead("Payload"),
11256 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211257
Ryan Sleevib8d7ea02018-05-07 20:01:0111258 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711259 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211260
[email protected]8ddf8322012-02-23 18:08:0611261 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711262 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211263
[email protected]49639fa2011-12-20 23:22:4111264 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211265
tfarina42834112016-09-22 13:38:2011266 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111267 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211268
11269 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111270 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211271
bnc691fda62016-08-12 00:43:1611272 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211273 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711274 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211275
[email protected]029c83b62013-01-24 05:28:2011276 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611277 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011278 TestLoadTimingNotReusedWithPac(load_timing_info,
11279 CONNECT_TIMING_HAS_SSL_TIMES);
11280
[email protected]3cd17242009-06-23 02:59:0211281 std::string response_text;
bnc691fda62016-08-12 00:43:1611282 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111283 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211284 EXPECT_EQ("Payload", response_text);
11285}
11286
[email protected]448d4ca52012-03-04 04:12:2311287namespace {
11288
Matt Menkef6edce752019-03-19 17:21:5611289// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611290
Matt Menkef6edce752019-03-19 17:21:5611291struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611292 std::string proxy_server;
11293 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611294 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811295 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611296};
11297
Matt Menkef6edce752019-03-19 17:21:5611298std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711299 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911300 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611301
bnc525e175a2016-06-20 12:36:4011302 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311303 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111304 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211305 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111306 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211307 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0711308 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611309
11310 return session;
11311}
11312
Matt Menkef6edce752019-03-19 17:21:5611313int GroupIdTransactionHelper(const std::string& url,
11314 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611315 HttpRequestInfo request;
11316 request.method = "GET";
11317 request.url = GURL(url);
Ramin Halavatib5e433e2018-02-07 07:41:1011318 request.traffic_annotation =
11319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0611320
bnc691fda62016-08-12 00:43:1611321 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2711322
[email protected]49639fa2011-12-20 23:22:4111323 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0611324
11325 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2011326 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0611327}
11328
[email protected]448d4ca52012-03-04 04:12:2311329} // namespace
11330
Matt Menkef6edce752019-03-19 17:21:5611331TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
11332 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311333 {
Matt Menkef6edce752019-03-19 17:21:5611334 "", // unused
11335 "http://www.example.org/direct",
11336 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11337 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411338 PrivacyMode::PRIVACY_MODE_DISABLED,
11339 NetworkIsolationKey(),
11340 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611341 false,
bncce36dca22015-04-21 22:11:2311342 },
11343 {
Matt Menkef6edce752019-03-19 17:21:5611344 "", // unused
11345 "http://[2001:1418:13:1::25]/direct",
11346 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
11347 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411348 PrivacyMode::PRIVACY_MODE_DISABLED,
11349 NetworkIsolationKey(),
11350 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611351 false,
bncce36dca22015-04-21 22:11:2311352 },
[email protected]04e5be32009-06-26 20:00:3111353
bncce36dca22015-04-21 22:11:2311354 // SSL Tests
11355 {
Matt Menkef6edce752019-03-19 17:21:5611356 "", // unused
11357 "https://www.example.org/direct_ssl",
11358 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11359 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411360 PrivacyMode::PRIVACY_MODE_DISABLED,
11361 NetworkIsolationKey(),
11362 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611363 true,
bncce36dca22015-04-21 22:11:2311364 },
11365 {
Matt Menkef6edce752019-03-19 17:21:5611366 "", // unused
11367 "https://[2001:1418:13:1::25]/direct",
11368 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
11369 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411370 PrivacyMode::PRIVACY_MODE_DISABLED,
11371 NetworkIsolationKey(),
11372 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611373 true,
bncce36dca22015-04-21 22:11:2311374 },
11375 {
Matt Menkef6edce752019-03-19 17:21:5611376 "", // unused
11377 "https://host.with.alternate/direct",
11378 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11379 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411380 PrivacyMode::PRIVACY_MODE_DISABLED,
11381 NetworkIsolationKey(),
11382 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5611383 true,
bncce36dca22015-04-21 22:11:2311384 },
[email protected]2d731a32010-04-29 01:04:0611385 };
[email protected]2ff8b312010-04-26 22:20:5411386
Avi Drissman4365a4782018-12-28 19:26:2411387 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911388 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911389 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11390 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911391 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611392 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611393
mmenkee65e7af2015-10-13 17:16:4211394 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5611395 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611396 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911397 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011398 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
11399 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4811400 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611401
11402 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611403 GroupIdTransactionHelper(tests[i].url, session.get()));
11404 EXPECT_EQ(tests[i].expected_group_id,
11405 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2311406 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0611407 }
[email protected]2d731a32010-04-29 01:04:0611408}
11409
Matt Menkef6edce752019-03-19 17:21:5611410TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
11411 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311412 {
Matt Menke4802de62019-03-08 22:47:5011413 "http_proxy",
11414 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611415 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11416 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411417 PrivacyMode::PRIVACY_MODE_DISABLED,
11418 NetworkIsolationKey(),
11419 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011420 false,
bncce36dca22015-04-21 22:11:2311421 },
[email protected]2d731a32010-04-29 01:04:0611422
bncce36dca22015-04-21 22:11:2311423 // SSL Tests
11424 {
Matt Menke4802de62019-03-08 22:47:5011425 "http_proxy",
11426 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5611427 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11428 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411429 PrivacyMode::PRIVACY_MODE_DISABLED,
11430 NetworkIsolationKey(),
11431 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011432 true,
bncce36dca22015-04-21 22:11:2311433 },
[email protected]af3490e2010-10-16 21:02:2911434
bncce36dca22015-04-21 22:11:2311435 {
Matt Menke4802de62019-03-08 22:47:5011436 "http_proxy",
11437 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611438 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11439 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411440 PrivacyMode::PRIVACY_MODE_DISABLED,
11441 NetworkIsolationKey(),
11442 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011443 true,
bncce36dca22015-04-21 22:11:2311444 },
[email protected]2d731a32010-04-29 01:04:0611445 };
11446
Avi Drissman4365a4782018-12-28 19:26:2411447 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911448 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911449 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11450 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911451 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611452 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611453
mmenkee65e7af2015-10-13 17:16:4211454 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0611455
Matt Menkee8648fa2019-01-17 16:47:0711456 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
11457 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5611458 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3611459 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911460 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011461 mock_pool_manager->SetSocketPool(proxy_server,
11462 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4811463 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611464
11465 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611466 GroupIdTransactionHelper(tests[i].url, session.get()));
11467 EXPECT_EQ(tests[i].expected_group_id,
11468 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0611469 }
[email protected]2d731a32010-04-29 01:04:0611470}
11471
Matt Menkef6edce752019-03-19 17:21:5611472TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
11473 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311474 {
Matt Menke4802de62019-03-08 22:47:5011475 "socks4://socks_proxy:1080",
11476 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5611477 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11478 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411479 PrivacyMode::PRIVACY_MODE_DISABLED,
11480 NetworkIsolationKey(),
11481 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011482 false,
bncce36dca22015-04-21 22:11:2311483 },
11484 {
Matt Menke4802de62019-03-08 22:47:5011485 "socks5://socks_proxy:1080",
11486 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5611487 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11488 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3411489 PrivacyMode::PRIVACY_MODE_DISABLED,
11490 NetworkIsolationKey(),
11491 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011492 false,
bncce36dca22015-04-21 22:11:2311493 },
[email protected]2d731a32010-04-29 01:04:0611494
bncce36dca22015-04-21 22:11:2311495 // SSL Tests
11496 {
Matt Menke4802de62019-03-08 22:47:5011497 "socks4://socks_proxy:1080",
11498 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5611499 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11500 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411501 PrivacyMode::PRIVACY_MODE_DISABLED,
11502 NetworkIsolationKey(),
11503 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011504 true,
bncce36dca22015-04-21 22:11:2311505 },
11506 {
Matt Menke4802de62019-03-08 22:47:5011507 "socks5://socks_proxy:1080",
11508 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5611509 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11510 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411511 PrivacyMode::PRIVACY_MODE_DISABLED,
11512 NetworkIsolationKey(),
11513 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011514 true,
bncce36dca22015-04-21 22:11:2311515 },
[email protected]af3490e2010-10-16 21:02:2911516
bncce36dca22015-04-21 22:11:2311517 {
Matt Menke4802de62019-03-08 22:47:5011518 "socks4://socks_proxy:1080",
11519 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611520 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11521 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3411522 PrivacyMode::PRIVACY_MODE_DISABLED,
11523 NetworkIsolationKey(),
11524 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5011525 true,
bncce36dca22015-04-21 22:11:2311526 },
[email protected]04e5be32009-06-26 20:00:3111527 };
11528
Avi Drissman4365a4782018-12-28 19:26:2411529 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911530 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911531 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11532 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911533 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611534 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0211535
mmenkee65e7af2015-10-13 17:16:4211536 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3111537
Matt Menkee8648fa2019-01-17 16:47:0711538 ProxyServer proxy_server(
11539 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
11540 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5611541 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611542 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911543 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011544 mock_pool_manager->SetSocketPool(proxy_server,
11545 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4811546 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3111547
bnc691fda62016-08-12 00:43:1611548 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3111549
[email protected]2d731a32010-04-29 01:04:0611550 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611551 GroupIdTransactionHelper(tests[i].url, session.get()));
11552 EXPECT_EQ(tests[i].expected_group_id,
11553 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3111554 }
11555}
11556
bncd16676a2016-07-20 16:23:0111557TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2711558 HttpRequestInfo request;
11559 request.method = "GET";
bncce36dca22015-04-21 22:11:2311560 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011561 request.traffic_annotation =
11562 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711563
Ramin Halavatica8d5252018-03-12 05:33:4911564 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11565 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3211566
[email protected]69719062010-01-05 20:09:2111567 // This simulates failure resolving all hostnames; that means we will fail
11568 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0711569 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3211570
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]9172a982009-06-06 00:30:2511573
[email protected]49639fa2011-12-20 23:22:4111574 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2511575
tfarina42834112016-09-22 13:38:2011576 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111577 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2511578
[email protected]9172a982009-06-06 00:30:2511579 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111580 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2511581}
11582
[email protected]0877e3d2009-10-17 22:29:5711583// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0111584TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5711585 HttpRequestInfo request;
11586 request.method = "GET";
11587 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1011588 request.traffic_annotation =
11589 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711590
11591 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0611592 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711593 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111594 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0711595 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911596 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711597
[email protected]49639fa2011-12-20 23:22:4111598 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711599
bnc691fda62016-08-12 00:43:1611600 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711601
tfarina42834112016-09-22 13:38:2011602 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111603 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711604
11605 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111606 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5911607
11608 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611609 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911610 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711611}
11612
zmo9528c9f42015-08-04 22:12:0811613// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0111614TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5711615 HttpRequestInfo request;
11616 request.method = "GET";
11617 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1011618 request.traffic_annotation =
11619 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711620
11621 MockRead data_reads[] = {
11622 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0611623 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711624 };
11625
Ryan Sleevib8d7ea02018-05-07 20:01:0111626 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711627 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911628 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711629
[email protected]49639fa2011-12-20 23:22:4111630 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711631
bnc691fda62016-08-12 00:43:1611632 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711633
tfarina42834112016-09-22 13:38:2011634 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111635 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711636
11637 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111638 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811639
bnc691fda62016-08-12 00:43:1611640 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211641 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0811642
wezca1070932016-05-26 20:30:5211643 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0811644 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11645
11646 std::string response_data;
bnc691fda62016-08-12 00:43:1611647 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111648 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811649 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5911650
11651 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611652 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911653 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711654}
11655
11656// Make sure that a dropped connection while draining the body for auth
11657// restart does the right thing.
bncd16676a2016-07-20 16:23:0111658TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5711659 HttpRequestInfo request;
11660 request.method = "GET";
bncce36dca22015-04-21 22:11:2311661 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011662 request.traffic_annotation =
11663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711664
11665 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311666 MockWrite(
11667 "GET / HTTP/1.1\r\n"
11668 "Host: www.example.org\r\n"
11669 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711670 };
11671
11672 MockRead data_reads1[] = {
11673 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
11674 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11676 MockRead("Content-Length: 14\r\n\r\n"),
11677 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0611678 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711679 };
11680
Ryan Sleevib8d7ea02018-05-07 20:01:0111681 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0711682 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5711683
bnc691fda62016-08-12 00:43:1611684 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5711685 // be issuing -- the final header line contains the credentials.
11686 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311687 MockWrite(
11688 "GET / HTTP/1.1\r\n"
11689 "Host: www.example.org\r\n"
11690 "Connection: keep-alive\r\n"
11691 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711692 };
11693
11694 // Lastly, the server responds with the actual content.
11695 MockRead data_reads2[] = {
11696 MockRead("HTTP/1.1 200 OK\r\n"),
11697 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11698 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611699 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711700 };
11701
Ryan Sleevib8d7ea02018-05-07 20:01:0111702 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0711703 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0911704 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711705
[email protected]49639fa2011-12-20 23:22:4111706 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5711707
bnc691fda62016-08-12 00:43:1611708 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011709
tfarina42834112016-09-22 13:38:2011710 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111711 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711712
11713 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111714 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711715
bnc691fda62016-08-12 00:43:1611716 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211717 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811718 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5711719
[email protected]49639fa2011-12-20 23:22:4111720 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5711721
bnc691fda62016-08-12 00:43:1611722 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0111723 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711724
11725 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111726 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711727
bnc691fda62016-08-12 00:43:1611728 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211729 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811730 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5711731 EXPECT_EQ(100, response->headers->GetContentLength());
11732}
11733
11734// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0111735TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4911736 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11737 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711738
11739 HttpRequestInfo request;
11740 request.method = "GET";
bncce36dca22015-04-21 22:11:2311741 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011742 request.traffic_annotation =
11743 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711744
11745 MockRead proxy_reads[] = {
11746 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0611747 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5711748 };
11749
Ryan Sleevib8d7ea02018-05-07 20:01:0111750 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0611751 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5711752
[email protected]bb88e1d32013-05-03 23:11:0711753 session_deps_.socket_factory->AddSocketDataProvider(&data);
11754 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5711755
[email protected]49639fa2011-12-20 23:22:4111756 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711757
[email protected]bb88e1d32013-05-03 23:11:0711758 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5711759
danakj1fd259a02016-04-16 03:17:0911760 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611761 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711762
tfarina42834112016-09-22 13:38:2011763 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111764 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711765
11766 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111767 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5711768}
11769
bncd16676a2016-07-20 16:23:0111770TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4611771 HttpRequestInfo request;
11772 request.method = "GET";
bncce36dca22015-04-21 22:11:2311773 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011774 request.traffic_annotation =
11775 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4611776
danakj1fd259a02016-04-16 03:17:0911777 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611778 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711779
[email protected]e22e1362009-11-23 21:31:1211780 MockRead data_reads[] = {
11781 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611782 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1211783 };
[email protected]9492e4a2010-02-24 00:58:4611784
Ryan Sleevib8d7ea02018-05-07 20:01:0111785 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711786 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4611787
[email protected]49639fa2011-12-20 23:22:4111788 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4611789
tfarina42834112016-09-22 13:38:2011790 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111791 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4611792
robpercival214763f2016-07-01 23:27:0111793 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4611794
bnc691fda62016-08-12 00:43:1611795 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211796 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4611797
wezca1070932016-05-26 20:30:5211798 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4611799 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11800
11801 std::string response_data;
bnc691fda62016-08-12 00:43:1611802 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111803 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1211804}
11805
bncd16676a2016-07-20 16:23:0111806TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1511807 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5211808 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1411809 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2111810 UploadFileElementReader::ScopedOverridingContentLengthForTests
11811 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3311812
danakj1fd259a02016-04-16 03:17:0911813 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911814 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411815 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0711816 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211817 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711818
11819 HttpRequestInfo request;
11820 request.method = "POST";
bncce36dca22015-04-21 22:11:2311821 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711822 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1011823 request.traffic_annotation =
11824 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711825
danakj1fd259a02016-04-16 03:17:0911826 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611827 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3311828
11829 MockRead data_reads[] = {
11830 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11831 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0611832 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3311833 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111834 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711835 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3311836
[email protected]49639fa2011-12-20 23:22:4111837 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3311838
tfarina42834112016-09-22 13:38:2011839 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111840 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3311841
11842 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111843 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3311844
bnc691fda62016-08-12 00:43:1611845 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211846 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3311847
maksim.sisove869bf52016-06-23 17:11:5211848 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3311849
[email protected]dd3aa792013-07-16 19:10:2311850 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3311851}
11852
bncd16676a2016-07-20 16:23:0111853TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1511854 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5211855 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3611856 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4811857 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
11858 base::WriteFile(temp_file, temp_file_content.c_str(),
11859 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1111860 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3611861
danakj1fd259a02016-04-16 03:17:0911862 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911863 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411864 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0711865 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211866 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711867
11868 HttpRequestInfo request;
11869 request.method = "POST";
bncce36dca22015-04-21 22:11:2311870 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711871 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1011872 request.traffic_annotation =
11873 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711874
[email protected]999dd8c2013-11-12 06:45:5411875 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0911876 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611877 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3611878
Ryan Sleevib8d7ea02018-05-07 20:01:0111879 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0711880 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3611881
[email protected]49639fa2011-12-20 23:22:4111882 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3611883
tfarina42834112016-09-22 13:38:2011884 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111885 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3611886
11887 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111888 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3611889
[email protected]dd3aa792013-07-16 19:10:2311890 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3611891}
11892
bncd16676a2016-07-20 16:23:0111893TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0311894 class FakeUploadElementReader : public UploadElementReader {
11895 public:
Chris Watkins7a41d3552017-12-01 02:13:2711896 FakeUploadElementReader() = default;
11897 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0311898
Matt Menkecc1d3a902018-02-05 18:27:3311899 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0311900
11901 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3311902 int Init(CompletionOnceCallback callback) override {
11903 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0311904 return ERR_IO_PENDING;
11905 }
avibf0746c2015-12-09 19:53:1411906 uint64_t GetContentLength() const override { return 0; }
11907 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2011908 int Read(IOBuffer* buf,
11909 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3311910 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0311911 return ERR_FAILED;
11912 }
11913
11914 private:
Matt Menkecc1d3a902018-02-05 18:27:3311915 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0311916 };
11917
11918 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0911919 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11920 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2211921 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0311922
11923 HttpRequestInfo request;
11924 request.method = "POST";
bncce36dca22015-04-21 22:11:2311925 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0311926 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1011927 request.traffic_annotation =
11928 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0311929
danakj1fd259a02016-04-16 03:17:0911930 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5811931 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911932 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0311933
11934 StaticSocketDataProvider data;
11935 session_deps_.socket_factory->AddSocketDataProvider(&data);
11936
11937 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2011938 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111939 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5511940 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0311941
11942 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3311943 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
11944 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0311945
11946 // Return Init()'s result after the transaction gets destroyed.
11947 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3311948 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0311949}
11950
[email protected]aeefc9e82010-02-19 16:18:2711951// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0111952TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2711953 HttpRequestInfo request;
11954 request.method = "GET";
bncce36dca22015-04-21 22:11:2311955 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011956 request.traffic_annotation =
11957 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2711958
11959 // First transaction will request a resource and receive a Basic challenge
11960 // with realm="first_realm".
11961 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311962 MockWrite(
11963 "GET / HTTP/1.1\r\n"
11964 "Host: www.example.org\r\n"
11965 "Connection: keep-alive\r\n"
11966 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711967 };
11968 MockRead data_reads1[] = {
11969 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11970 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11971 "\r\n"),
11972 };
11973
bnc691fda62016-08-12 00:43:1611974 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2711975 // for first_realm. The server will reject and provide a challenge with
11976 // second_realm.
11977 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311978 MockWrite(
11979 "GET / HTTP/1.1\r\n"
11980 "Host: www.example.org\r\n"
11981 "Connection: keep-alive\r\n"
11982 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
11983 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711984 };
11985 MockRead data_reads2[] = {
11986 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11987 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
11988 "\r\n"),
11989 };
11990
11991 // This again fails, and goes back to first_realm. Make sure that the
11992 // entry is removed from cache.
11993 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2311994 MockWrite(
11995 "GET / HTTP/1.1\r\n"
11996 "Host: www.example.org\r\n"
11997 "Connection: keep-alive\r\n"
11998 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
11999 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712000 };
12001 MockRead data_reads3[] = {
12002 MockRead("HTTP/1.1 401 Unauthorized\r\n"
12003 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
12004 "\r\n"),
12005 };
12006
12007 // Try one last time (with the correct password) and get the resource.
12008 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2312009 MockWrite(
12010 "GET / HTTP/1.1\r\n"
12011 "Host: www.example.org\r\n"
12012 "Connection: keep-alive\r\n"
12013 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
12014 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2712015 };
12016 MockRead data_reads4[] = {
12017 MockRead("HTTP/1.1 200 OK\r\n"
12018 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5012019 "Content-Length: 5\r\n"
12020 "\r\n"
12021 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2712022 };
12023
Ryan Sleevib8d7ea02018-05-07 20:01:0112024 StaticSocketDataProvider data1(data_reads1, data_writes1);
12025 StaticSocketDataProvider data2(data_reads2, data_writes2);
12026 StaticSocketDataProvider data3(data_reads3, data_writes3);
12027 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0712028 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12029 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12030 session_deps_.socket_factory->AddSocketDataProvider(&data3);
12031 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2712032
[email protected]49639fa2011-12-20 23:22:4112033 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2712034
danakj1fd259a02016-04-16 03:17:0912035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612036 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012037
[email protected]aeefc9e82010-02-19 16:18:2712038 // Issue the first request with Authorize headers. There should be a
12039 // password prompt for first_realm waiting to be filled in after the
12040 // transaction completes.
tfarina42834112016-09-22 13:38:2012041 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112042 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712043 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112044 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612045 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212046 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812047 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212048 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412049 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312050 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412051 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912052 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712053
12054 // Issue the second request with an incorrect password. There should be a
12055 // password prompt for second_realm waiting to be filled in after the
12056 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4112057 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1612058 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
12059 callback2.callback());
robpercival214763f2016-07-01 23:27:0112060 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712061 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112062 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612063 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212064 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812065 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212066 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412067 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312068 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412069 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912070 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712071
12072 // Issue the third request with another incorrect password. There should be
12073 // a password prompt for first_realm waiting to be filled in. If the password
12074 // prompt is not present, it indicates that the HttpAuthCacheEntry for
12075 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4112076 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1612077 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
12078 callback3.callback());
robpercival214763f2016-07-01 23:27:0112079 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712080 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0112081 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612082 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212083 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812084 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212085 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412086 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312087 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412088 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912089 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712090
12091 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4112092 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1612093 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
12094 callback4.callback());
robpercival214763f2016-07-01 23:27:0112095 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712096 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0112097 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612098 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212099 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812100 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2712101}
12102
Bence Béky230ac612017-08-30 19:17:0812103// Regression test for https://crbug.com/754395.
12104TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
12105 MockRead data_reads[] = {
12106 MockRead("HTTP/1.1 200 OK\r\n"),
12107 MockRead(kAlternativeServiceHttpHeader),
12108 MockRead("\r\n"),
12109 MockRead("hello world"),
12110 MockRead(SYNCHRONOUS, OK),
12111 };
12112
12113 HttpRequestInfo request;
12114 request.method = "GET";
12115 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012116 request.traffic_annotation =
12117 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0812118
Ryan Sleevib8d7ea02018-05-07 20:01:0112119 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0812120 session_deps_.socket_factory->AddSocketDataProvider(&data);
12121
12122 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912123 ssl.ssl_info.cert =
12124 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12125 ASSERT_TRUE(ssl.ssl_info.cert);
12126 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0812127 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12128
12129 TestCompletionCallback callback;
12130
12131 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12132 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12133
12134 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12135 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12136
12137 url::SchemeHostPort test_server(request.url);
12138 HttpServerProperties* http_server_properties =
12139 session->http_server_properties();
12140 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912141 http_server_properties
12142 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12143 .empty());
Bence Béky230ac612017-08-30 19:17:0812144
12145 EXPECT_THAT(callback.WaitForResult(), IsOk());
12146
12147 const HttpResponseInfo* response = trans.GetResponseInfo();
12148 ASSERT_TRUE(response);
12149 ASSERT_TRUE(response->headers);
12150 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12151 EXPECT_FALSE(response->was_fetched_via_spdy);
12152 EXPECT_FALSE(response->was_alpn_negotiated);
12153
12154 std::string response_data;
12155 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12156 EXPECT_EQ("hello world", response_data);
12157
12158 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912159 http_server_properties
12160 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12161 .empty());
Bence Béky230ac612017-08-30 19:17:0812162}
12163
bncd16676a2016-07-20 16:23:0112164TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5212165 MockRead data_reads[] = {
12166 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312167 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212168 MockRead("\r\n"),
12169 MockRead("hello world"),
12170 MockRead(SYNCHRONOUS, OK),
12171 };
12172
12173 HttpRequestInfo request;
12174 request.method = "GET";
bncb26024382016-06-29 02:39:4512175 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012176 request.traffic_annotation =
12177 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212178
Ryan Sleevib8d7ea02018-05-07 20:01:0112179 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212180 session_deps_.socket_factory->AddSocketDataProvider(&data);
12181
bncb26024382016-06-29 02:39:4512182 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912183 ssl.ssl_info.cert =
12184 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12185 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512186 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12187
bncc958faa2015-07-31 18:14:5212188 TestCompletionCallback callback;
12189
danakj1fd259a02016-04-16 03:17:0912190 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612191 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212192
tfarina42834112016-09-22 13:38:2012193 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112194 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212195
bncb26024382016-06-29 02:39:4512196 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012197 HttpServerProperties* http_server_properties =
12198 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412199 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912200 http_server_properties
12201 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12202 .empty());
bncc958faa2015-07-31 18:14:5212203
robpercival214763f2016-07-01 23:27:0112204 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212205
bnc691fda62016-08-12 00:43:1612206 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212207 ASSERT_TRUE(response);
12208 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212209 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12210 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212211 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212212
12213 std::string response_data;
bnc691fda62016-08-12 00:43:1612214 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212215 EXPECT_EQ("hello world", response_data);
12216
zhongyic4de03032017-05-19 04:07:3412217 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912218 http_server_properties->GetAlternativeServiceInfos(test_server,
12219 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412220 ASSERT_EQ(1u, alternative_service_info_vector.size());
12221 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12222 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412223 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212224}
12225
Matt Menke3233d8f22019-08-20 21:01:4912226TEST_F(HttpNetworkTransactionTest,
12227 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
12228 base::test::ScopedFeatureList feature_list;
12229 feature_list.InitWithFeatures(
12230 // enabled_features
12231 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
12232 // Need to partition connections by NetworkIsolationKey for
12233 // SpdySessionKeys to include NetworkIsolationKeys.
12234 features::kPartitionConnectionsByNetworkIsolationKey},
12235 // disabled_features
12236 {});
12237 // Since HttpServerProperties caches the feature value, have to create a new
12238 // one.
12239 session_deps_.http_server_properties =
12240 std::make_unique<HttpServerProperties>();
12241
12242 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
12243 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
12244 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
12245 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
12246
12247 MockRead data_reads[] = {
12248 MockRead("HTTP/1.1 200 OK\r\n"),
12249 MockRead(kAlternativeServiceHttpHeader),
12250 MockRead("\r\n"),
12251 MockRead("hello world"),
12252 MockRead(SYNCHRONOUS, OK),
12253 };
12254
12255 HttpRequestInfo request;
12256 request.method = "GET";
12257 request.url = GURL("https://www.example.org/");
12258 request.traffic_annotation =
12259 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12260 request.network_isolation_key = kNetworkIsolationKey1;
12261
12262 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12263 session_deps_.socket_factory->AddSocketDataProvider(&data);
12264
12265 SSLSocketDataProvider ssl(ASYNC, OK);
12266 ssl.ssl_info.cert =
12267 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12268 ASSERT_TRUE(ssl.ssl_info.cert);
12269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12270
12271 TestCompletionCallback callback;
12272
12273 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12274 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12275
12276 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12277 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12278
12279 url::SchemeHostPort test_server(request.url);
12280 HttpServerProperties* http_server_properties =
12281 session->http_server_properties();
12282 EXPECT_TRUE(
12283 http_server_properties
12284 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
12285 .empty());
12286
12287 EXPECT_THAT(callback.WaitForResult(), IsOk());
12288
12289 const HttpResponseInfo* response = trans.GetResponseInfo();
12290 ASSERT_TRUE(response);
12291 ASSERT_TRUE(response->headers);
12292 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12293 EXPECT_FALSE(response->was_fetched_via_spdy);
12294 EXPECT_FALSE(response->was_alpn_negotiated);
12295
12296 std::string response_data;
12297 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12298 EXPECT_EQ("hello world", response_data);
12299
12300 AlternativeServiceInfoVector alternative_service_info_vector =
12301 http_server_properties->GetAlternativeServiceInfos(test_server,
12302 kNetworkIsolationKey1);
12303 ASSERT_EQ(1u, alternative_service_info_vector.size());
12304 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12305 EXPECT_EQ(alternative_service,
12306 alternative_service_info_vector[0].alternative_service());
12307
12308 // Make sure the alternative service information is only associated with
12309 // kNetworkIsolationKey1.
12310 EXPECT_TRUE(
12311 http_server_properties
12312 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12313 .empty());
12314 EXPECT_TRUE(
12315 http_server_properties
12316 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
12317 .empty());
12318}
12319
bnce3dd56f2016-06-01 10:37:1112320// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0112321TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112322 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1112323 MockRead data_reads[] = {
12324 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312325 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1112326 MockRead("\r\n"),
12327 MockRead("hello world"),
12328 MockRead(SYNCHRONOUS, OK),
12329 };
12330
12331 HttpRequestInfo request;
12332 request.method = "GET";
12333 request.url = GURL("http://www.example.org/");
12334 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012335 request.traffic_annotation =
12336 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112337
Ryan Sleevib8d7ea02018-05-07 20:01:0112338 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112339 session_deps_.socket_factory->AddSocketDataProvider(&data);
12340
12341 TestCompletionCallback callback;
12342
12343 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612344 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112345
12346 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012347 HttpServerProperties* http_server_properties =
12348 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412349 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912350 http_server_properties
12351 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12352 .empty());
bnce3dd56f2016-06-01 10:37:1112353
tfarina42834112016-09-22 13:38:2012354 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112355 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12356 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1112357
bnc691fda62016-08-12 00:43:1612358 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1112359 ASSERT_TRUE(response);
12360 ASSERT_TRUE(response->headers);
12361 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12362 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212363 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1112364
12365 std::string response_data;
bnc691fda62016-08-12 00:43:1612366 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1112367 EXPECT_EQ("hello world", response_data);
12368
zhongyic4de03032017-05-19 04:07:3412369 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912370 http_server_properties
12371 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12372 .empty());
bnce3dd56f2016-06-01 10:37:1112373}
12374
bnca86731e2017-04-17 12:31:2812375// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2512376// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0112377TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2512378 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2812379 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4512380
bnc8bef8da22016-05-30 01:28:2512381 HttpRequestInfo request;
12382 request.method = "GET";
bncb26024382016-06-29 02:39:4512383 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2512384 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012385 request.traffic_annotation =
12386 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2512387
12388 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12389 StaticSocketDataProvider first_data;
12390 first_data.set_connect_data(mock_connect);
12391 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512392 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612393 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512394 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2512395
12396 MockRead data_reads[] = {
12397 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12398 MockRead(ASYNC, OK),
12399 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112400 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2512401 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12402
12403 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12404
bnc525e175a2016-06-20 12:36:4012405 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2512406 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112407 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
12408 444);
bnc8bef8da22016-05-30 01:28:2512409 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112410 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712411 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12412 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2512413
bnc691fda62016-08-12 00:43:1612414 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2512415 TestCompletionCallback callback;
12416
tfarina42834112016-09-22 13:38:2012417 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2512418 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112419 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2512420}
12421
bnce3dd56f2016-06-01 10:37:1112422// Regression test for https://crbug.com/615497:
12423// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0112424TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112425 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1112426 HttpRequestInfo request;
12427 request.method = "GET";
12428 request.url = GURL("http://www.example.org/");
12429 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012430 request.traffic_annotation =
12431 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112432
12433 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12434 StaticSocketDataProvider first_data;
12435 first_data.set_connect_data(mock_connect);
12436 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
12437
12438 MockRead data_reads[] = {
12439 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12440 MockRead(ASYNC, OK),
12441 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112442 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112443 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12444
12445 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12446
bnc525e175a2016-06-20 12:36:4012447 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1112448 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112449 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1112450 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112451 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712452 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12453 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1112454
bnc691fda62016-08-12 00:43:1612455 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112456 TestCompletionCallback callback;
12457
tfarina42834112016-09-22 13:38:2012458 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1112459 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112460 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1112461}
12462
bncd16676a2016-07-20 16:23:0112463TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0812464 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0912465 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012466 HttpServerProperties* http_server_properties =
12467 session->http_server_properties();
bncb26024382016-06-29 02:39:4512468 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2112469 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0812470 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112471 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712472 test_server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212473 session->params().quic_params.supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4912474 EXPECT_EQ(1u,
12475 http_server_properties
12476 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12477 .size());
bnc4f575852015-10-14 18:35:0812478
12479 // Send a clear header.
12480 MockRead data_reads[] = {
12481 MockRead("HTTP/1.1 200 OK\r\n"),
12482 MockRead("Alt-Svc: clear\r\n"),
12483 MockRead("\r\n"),
12484 MockRead("hello world"),
12485 MockRead(SYNCHRONOUS, OK),
12486 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112487 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0812488 session_deps_.socket_factory->AddSocketDataProvider(&data);
12489
bncb26024382016-06-29 02:39:4512490 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912491 ssl.ssl_info.cert =
12492 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12493 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512494 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12495
bnc4f575852015-10-14 18:35:0812496 HttpRequestInfo request;
12497 request.method = "GET";
bncb26024382016-06-29 02:39:4512498 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012499 request.traffic_annotation =
12500 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0812501
12502 TestCompletionCallback callback;
12503
bnc691fda62016-08-12 00:43:1612504 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0812505
tfarina42834112016-09-22 13:38:2012506 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112507 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0812508
bnc691fda62016-08-12 00:43:1612509 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212510 ASSERT_TRUE(response);
12511 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0812512 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12513 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212514 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0812515
12516 std::string response_data;
bnc691fda62016-08-12 00:43:1612517 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0812518 EXPECT_EQ("hello world", response_data);
12519
zhongyic4de03032017-05-19 04:07:3412520 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912521 http_server_properties
12522 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12523 .empty());
bnc4f575852015-10-14 18:35:0812524}
12525
bncd16676a2016-07-20 16:23:0112526TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5212527 MockRead data_reads[] = {
12528 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312529 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
12530 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5212531 MockRead("hello world"),
12532 MockRead(SYNCHRONOUS, OK),
12533 };
12534
12535 HttpRequestInfo request;
12536 request.method = "GET";
bncb26024382016-06-29 02:39:4512537 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012538 request.traffic_annotation =
12539 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212540
Ryan Sleevib8d7ea02018-05-07 20:01:0112541 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212542 session_deps_.socket_factory->AddSocketDataProvider(&data);
12543
bncb26024382016-06-29 02:39:4512544 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912545 ssl.ssl_info.cert =
12546 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12547 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512548 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12549
bncc958faa2015-07-31 18:14:5212550 TestCompletionCallback callback;
12551
danakj1fd259a02016-04-16 03:17:0912552 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612553 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212554
tfarina42834112016-09-22 13:38:2012555 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112556 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212557
bncb26024382016-06-29 02:39:4512558 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4012559 HttpServerProperties* http_server_properties =
12560 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412561 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912562 http_server_properties
12563 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12564 .empty());
bncc958faa2015-07-31 18:14:5212565
robpercival214763f2016-07-01 23:27:0112566 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212567
bnc691fda62016-08-12 00:43:1612568 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212569 ASSERT_TRUE(response);
12570 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212571 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12572 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212573 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212574
12575 std::string response_data;
bnc691fda62016-08-12 00:43:1612576 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212577 EXPECT_EQ("hello world", response_data);
12578
zhongyic4de03032017-05-19 04:07:3412579 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912580 http_server_properties->GetAlternativeServiceInfos(test_server,
12581 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412582 ASSERT_EQ(2u, alternative_service_info_vector.size());
12583
12584 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
12585 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412586 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412587 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
12588 1234);
12589 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5412590 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5212591}
12592
bncd16676a2016-07-20 16:23:0112593TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612594 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212595 HostPortPair alternative("alternative.example.org", 443);
12596 std::string origin_url = "https://origin.example.org:443";
12597 std::string alternative_url = "https://alternative.example.org:443";
12598
12599 // Negotiate HTTP/1.1 with alternative.example.org.
12600 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612601 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212602 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12603
12604 // HTTP/1.1 data for request.
12605 MockWrite http_writes[] = {
12606 MockWrite("GET / HTTP/1.1\r\n"
12607 "Host: alternative.example.org\r\n"
12608 "Connection: keep-alive\r\n\r\n"),
12609 };
12610
12611 MockRead http_reads[] = {
12612 MockRead("HTTP/1.1 200 OK\r\n"
12613 "Content-Type: text/html; charset=iso-8859-1\r\n"
12614 "Content-Length: 40\r\n\r\n"
12615 "first HTTP/1.1 response from alternative"),
12616 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112617 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212618 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12619
12620 StaticSocketDataProvider data_refused;
12621 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12622 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12623
zhongyi3d4a55e72016-04-22 20:36:4612624 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0912625 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012626 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212627 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112628 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0212629 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112630 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712631 server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212632 HttpNetworkSession::Params().quic_params.supported_versions);
zhongyi48704c182015-12-07 07:52:0212633 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0512634 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
12635 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0212636
zhongyi48704c182015-12-07 07:52:0212637 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612638 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212639 request.method = "GET";
12640 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1012641 request.traffic_annotation =
12642 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12643
zhongyi48704c182015-12-07 07:52:0212644 TestCompletionCallback callback;
12645 NetErrorDetails details;
12646 EXPECT_FALSE(details.quic_broken);
12647
tfarina42834112016-09-22 13:38:2012648 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612649 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212650 EXPECT_TRUE(details.quic_broken);
12651}
12652
bncd16676a2016-07-20 16:23:0112653TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612654 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212655 HostPortPair alternative1("alternative1.example.org", 443);
12656 HostPortPair alternative2("alternative2.example.org", 443);
12657 std::string origin_url = "https://origin.example.org:443";
12658 std::string alternative_url1 = "https://alternative1.example.org:443";
12659 std::string alternative_url2 = "https://alternative2.example.org:443";
12660
12661 // Negotiate HTTP/1.1 with alternative1.example.org.
12662 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612663 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212664 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12665
12666 // HTTP/1.1 data for request.
12667 MockWrite http_writes[] = {
12668 MockWrite("GET / HTTP/1.1\r\n"
12669 "Host: alternative1.example.org\r\n"
12670 "Connection: keep-alive\r\n\r\n"),
12671 };
12672
12673 MockRead http_reads[] = {
12674 MockRead("HTTP/1.1 200 OK\r\n"
12675 "Content-Type: text/html; charset=iso-8859-1\r\n"
12676 "Content-Length: 40\r\n\r\n"
12677 "first HTTP/1.1 response from alternative1"),
12678 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112679 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212680 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12681
12682 StaticSocketDataProvider data_refused;
12683 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12684 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12685
danakj1fd259a02016-04-16 03:17:0912686 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012687 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212688 session->http_server_properties();
12689
zhongyi3d4a55e72016-04-22 20:36:4612690 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0212691 AlternativeServiceInfoVector alternative_service_info_vector;
12692 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12693
bnc3472afd2016-11-17 15:27:2112694 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2112695 alternative_service_info_vector.push_back(
12696 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12697 alternative_service1, expiration,
Nick Harper72ade192019-07-17 03:30:4212698 session->params().quic_params.supported_versions));
bnc3472afd2016-11-17 15:27:2112699 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2112700 alternative_service_info_vector.push_back(
12701 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12702 alternative_service2, expiration,
Nick Harper72ade192019-07-17 03:30:4212703 session->params().quic_params.supported_versions));
zhongyi48704c182015-12-07 07:52:0212704
12705 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4912706 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0212707
12708 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0512709 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
12710 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4912711 EXPECT_EQ(2u, http_server_properties
12712 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
12713 .size());
zhongyi48704c182015-12-07 07:52:0212714
zhongyi48704c182015-12-07 07:52:0212715 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612716 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212717 request.method = "GET";
12718 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1012719 request.traffic_annotation =
12720 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12721
zhongyi48704c182015-12-07 07:52:0212722 TestCompletionCallback callback;
12723 NetErrorDetails details;
12724 EXPECT_FALSE(details.quic_broken);
12725
tfarina42834112016-09-22 13:38:2012726 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612727 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212728 EXPECT_FALSE(details.quic_broken);
12729}
12730
bncd16676a2016-07-20 16:23:0112731TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4212732 HttpRequestInfo request;
12733 request.method = "GET";
bncb26024382016-06-29 02:39:4512734 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012735 request.traffic_annotation =
12736 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4212737
[email protected]d973e99a2012-02-17 21:02:3612738 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4212739 StaticSocketDataProvider first_data;
12740 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712741 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512742 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612743 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4212745
12746 MockRead data_reads[] = {
12747 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12748 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612749 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4212750 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112751 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712752 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4212753
danakj1fd259a02016-04-16 03:17:0912754 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4212755
bnc525e175a2016-06-20 12:36:4012756 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312757 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4612758 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1112759 // Port must be < 1024, or the header will be ignored (since initial port was
12760 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2112761 // Port is ignored by MockConnect anyway.
12762 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12763 666);
bnc7dc7e1b42015-07-28 14:43:1212764 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112765 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712766 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4212767
bnc691fda62016-08-12 00:43:1612768 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112769 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4212770
tfarina42834112016-09-22 13:38:2012771 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112772 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12773 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4212774
bnc691fda62016-08-12 00:43:1612775 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212776 ASSERT_TRUE(response);
12777 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4212778 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12779
12780 std::string response_data;
bnc691fda62016-08-12 00:43:1612781 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4212782 EXPECT_EQ("hello world", response_data);
12783
zhongyic4de03032017-05-19 04:07:3412784 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912785 http_server_properties->GetAlternativeServiceInfos(server,
12786 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412787 ASSERT_EQ(1u, alternative_service_info_vector.size());
12788 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412789 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0512790 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
12791 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4212792}
12793
bnc55ff9da2015-08-19 18:42:3512794// Ensure that we are not allowed to redirect traffic via an alternate protocol
12795// to an unrestricted (port >= 1024) when the original traffic was on a
12796// restricted port (port < 1024). Ensure that we can redirect in all other
12797// cases.
bncd16676a2016-07-20 16:23:0112798TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1112799 HttpRequestInfo restricted_port_request;
12800 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512801 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112802 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012803 restricted_port_request.traffic_annotation =
12804 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112805
[email protected]d973e99a2012-02-17 21:02:3612806 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112807 StaticSocketDataProvider first_data;
12808 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712809 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112810
12811 MockRead data_reads[] = {
12812 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12813 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612814 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112815 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112816 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712817 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512818 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612819 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512820 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112821
danakj1fd259a02016-04-16 03:17:0912822 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112823
bnc525e175a2016-06-20 12:36:4012824 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312825 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112826 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112827 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12828 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212829 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112830 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712831 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12832 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112833
bnc691fda62016-08-12 00:43:1612834 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112835 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112836
tfarina42834112016-09-22 13:38:2012837 int rv = trans.Start(&restricted_port_request, callback.callback(),
12838 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112839 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112840 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0112841 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1912842}
[email protected]3912662a32011-10-04 00:51:1112843
bnc55ff9da2015-08-19 18:42:3512844// Ensure that we are allowed to redirect traffic via an alternate protocol to
12845// an unrestricted (port >= 1024) when the original traffic was on a restricted
12846// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0112847TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0712848 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1912849
12850 HttpRequestInfo restricted_port_request;
12851 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512852 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1912853 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012854 restricted_port_request.traffic_annotation =
12855 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1912856
12857 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12858 StaticSocketDataProvider first_data;
12859 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712860 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1912861
12862 MockRead data_reads[] = {
12863 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12864 MockRead("hello world"),
12865 MockRead(ASYNC, OK),
12866 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112867 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712868 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512869 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612870 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512871 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1912872
danakj1fd259a02016-04-16 03:17:0912873 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1912874
bnc525e175a2016-06-20 12:36:4012875 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1912876 session->http_server_properties();
12877 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112878 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12879 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212880 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112881 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712882 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12883 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1912884
bnc691fda62016-08-12 00:43:1612885 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1912886 TestCompletionCallback callback;
12887
tfarina42834112016-09-22 13:38:2012888 EXPECT_EQ(ERR_IO_PENDING,
12889 trans.Start(&restricted_port_request, callback.callback(),
12890 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1912891 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0112892 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112893}
12894
bnc55ff9da2015-08-19 18:42:3512895// Ensure that we are not allowed to redirect traffic via an alternate protocol
12896// to an unrestricted (port >= 1024) when the original traffic was on a
12897// restricted port (port < 1024). Ensure that we can redirect in all other
12898// cases.
bncd16676a2016-07-20 16:23:0112899TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1112900 HttpRequestInfo restricted_port_request;
12901 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512902 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112903 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012904 restricted_port_request.traffic_annotation =
12905 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112906
[email protected]d973e99a2012-02-17 21:02:3612907 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112908 StaticSocketDataProvider first_data;
12909 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712910 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112911
12912 MockRead data_reads[] = {
12913 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12914 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612915 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112916 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112917 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712918 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112919
bncb26024382016-06-29 02:39:4512920 SSLSocketDataProvider ssl(ASYNC, OK);
12921 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12922
danakj1fd259a02016-04-16 03:17:0912923 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112924
bnc525e175a2016-06-20 12:36:4012925 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312926 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112927 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112928 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12929 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212930 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112931 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712932 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12933 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112934
bnc691fda62016-08-12 00:43:1612935 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112936 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112937
tfarina42834112016-09-22 13:38:2012938 int rv = trans.Start(&restricted_port_request, callback.callback(),
12939 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112940 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112941 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112942 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112943}
12944
bnc55ff9da2015-08-19 18:42:3512945// Ensure that we are not allowed to redirect traffic via an alternate protocol
12946// to an unrestricted (port >= 1024) when the original traffic was on a
12947// restricted port (port < 1024). Ensure that we can redirect in all other
12948// cases.
bncd16676a2016-07-20 16:23:0112949TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1112950 HttpRequestInfo unrestricted_port_request;
12951 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512952 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112953 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012954 unrestricted_port_request.traffic_annotation =
12955 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112956
[email protected]d973e99a2012-02-17 21:02:3612957 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112958 StaticSocketDataProvider first_data;
12959 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712960 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112961
12962 MockRead data_reads[] = {
12963 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12964 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612965 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112966 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112967 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712968 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512969 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612970 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512971 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112972
danakj1fd259a02016-04-16 03:17:0912973 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112974
bnc525e175a2016-06-20 12:36:4012975 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312976 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112977 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112978 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12979 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212980 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112981 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712982 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
12983 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112984
bnc691fda62016-08-12 00:43:1612985 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112986 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112987
bnc691fda62016-08-12 00:43:1612988 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012989 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112990 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112991 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112992 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112993}
12994
bnc55ff9da2015-08-19 18:42:3512995// Ensure that we are not allowed to redirect traffic via an alternate protocol
12996// to an unrestricted (port >= 1024) when the original traffic was on a
12997// restricted port (port < 1024). Ensure that we can redirect in all other
12998// cases.
bncd16676a2016-07-20 16:23:0112999TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1113000 HttpRequestInfo unrestricted_port_request;
13001 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513002 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1113003 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013004 unrestricted_port_request.traffic_annotation =
13005 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113006
[email protected]d973e99a2012-02-17 21:02:3613007 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113008 StaticSocketDataProvider first_data;
13009 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713010 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113011
13012 MockRead data_reads[] = {
13013 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13014 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613015 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113016 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113017 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713018 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1113019
bncb26024382016-06-29 02:39:4513020 SSLSocketDataProvider ssl(ASYNC, OK);
13021 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13022
danakj1fd259a02016-04-16 03:17:0913023 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113024
bnc525e175a2016-06-20 12:36:4013025 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313026 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2213027 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2113028 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13029 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213030 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113031 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713032 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13033 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113034
bnc691fda62016-08-12 00:43:1613035 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113036 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113037
bnc691fda62016-08-12 00:43:1613038 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013039 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113040 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113041 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0113042 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113043}
13044
bnc55ff9da2015-08-19 18:42:3513045// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2113046// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
13047// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0113048TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0213049 HttpRequestInfo request;
13050 request.method = "GET";
bncce36dca22015-04-21 22:11:2313051 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013052 request.traffic_annotation =
13053 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0213054
13055 // The alternate protocol request will error out before we attempt to connect,
13056 // so only the standard HTTP request will try to connect.
13057 MockRead data_reads[] = {
13058 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13059 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613060 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0213061 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113062 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713063 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0213064
danakj1fd259a02016-04-16 03:17:0913065 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0213066
bnc525e175a2016-06-20 12:36:4013067 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0213068 session->http_server_properties();
13069 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2113070 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13071 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1213072 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113073 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713074 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13075 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0213076
bnc691fda62016-08-12 00:43:1613077 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0213078 TestCompletionCallback callback;
13079
tfarina42834112016-09-22 13:38:2013080 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113081 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0213082 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0113083 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213084
bnc691fda62016-08-12 00:43:1613085 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213086 ASSERT_TRUE(response);
13087 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0213088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13089
13090 std::string response_data;
bnc691fda62016-08-12 00:43:1613091 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213092 EXPECT_EQ("hello world", response_data);
13093}
13094
bncd16676a2016-07-20 16:23:0113095TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5413096 HttpRequestInfo request;
13097 request.method = "GET";
bncb26024382016-06-29 02:39:4513098 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013099 request.traffic_annotation =
13100 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413101
13102 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213103 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313104 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213105 MockRead("\r\n"),
13106 MockRead("hello world"),
13107 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13108 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5413109
Ryan Sleevib8d7ea02018-05-07 20:01:0113110 StaticSocketDataProvider first_transaction(data_reads,
13111 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713112 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513113 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613114 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513115 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413116
bnc032658ba2016-09-26 18:17:1513117 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413118
Ryan Hamilton0239aac2018-05-19 00:03:1313119 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513120 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113121 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413122
Raul Tambre94493c652019-03-11 17:18:3513123 spdy::SpdySerializedFrame resp(
13124 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313125 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413126 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113127 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413128 };
13129
Ryan Sleevib8d7ea02018-05-07 20:01:0113130 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713131 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413132
[email protected]d973e99a2012-02-17 21:02:3613133 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113134 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513135 hanging_non_alternate_protocol_socket.set_connect_data(
13136 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713137 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513138 &hanging_non_alternate_protocol_socket);
13139
[email protected]49639fa2011-12-20 23:22:4113140 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413141
danakj1fd259a02016-04-16 03:17:0913142 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813143 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913144 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413145
tfarina42834112016-09-22 13:38:2013146 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113147 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13148 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413149
13150 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213151 ASSERT_TRUE(response);
13152 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413153 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13154
13155 std::string response_data;
robpercival214763f2016-07-01 23:27:0113156 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413157 EXPECT_EQ("hello world", response_data);
13158
bnc87dcefc2017-05-25 12:47:5813159 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913160 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413161
tfarina42834112016-09-22 13:38:2013162 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113163 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13164 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413165
13166 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213167 ASSERT_TRUE(response);
13168 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213169 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313170 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213171 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413172
robpercival214763f2016-07-01 23:27:0113173 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413174 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5413175}
13176
bncd16676a2016-07-20 16:23:0113177TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5513178 HttpRequestInfo request;
13179 request.method = "GET";
bncb26024382016-06-29 02:39:4513180 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013181 request.traffic_annotation =
13182 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513183
bncb26024382016-06-29 02:39:4513184 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5513185 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213186 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313187 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213188 MockRead("\r\n"),
13189 MockRead("hello world"),
13190 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13191 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513192 };
13193
Ryan Sleevib8d7ea02018-05-07 20:01:0113194 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4513195 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5513196
bncb26024382016-06-29 02:39:4513197 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913198 ssl_http11.ssl_info.cert =
13199 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13200 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4513201 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
13202
13203 // Second transaction starts an alternative and a non-alternative Job.
13204 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3613205 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113206 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1813207 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1813208 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
13209
Ryan Sleevib8d7ea02018-05-07 20:01:0113210 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1813211 hanging_socket2.set_connect_data(never_finishing_connect);
13212 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5513213
bncb26024382016-06-29 02:39:4513214 // Third transaction starts an alternative and a non-alternative job.
13215 // The non-alternative job hangs, but the alternative one succeeds.
13216 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1313217 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4513218 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1313219 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4513220 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5513221 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113222 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5513223 };
Raul Tambre94493c652019-03-11 17:18:3513224 spdy::SpdySerializedFrame resp1(
13225 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313226 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3513227 spdy::SpdySerializedFrame resp2(
13228 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1313229 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5513230 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113231 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
13232 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1313233 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5513234 };
13235
Ryan Sleevib8d7ea02018-05-07 20:01:0113236 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713237 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5513238
bnc032658ba2016-09-26 18:17:1513239 AddSSLSocketData();
bncb26024382016-06-29 02:39:4513240
Ryan Sleevib8d7ea02018-05-07 20:01:0113241 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1813242 hanging_socket3.set_connect_data(never_finishing_connect);
13243 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5513244
danakj1fd259a02016-04-16 03:17:0913245 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4113246 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5013247 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513248
tfarina42834112016-09-22 13:38:2013249 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113250 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13251 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513252
13253 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5213254 ASSERT_TRUE(response);
13255 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513256 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13257
13258 std::string response_data;
robpercival214763f2016-07-01 23:27:0113259 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513260 EXPECT_EQ("hello world", response_data);
13261
[email protected]49639fa2011-12-20 23:22:4113262 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5013263 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013264 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113265 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513266
[email protected]49639fa2011-12-20 23:22:4113267 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5013268 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013269 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113270 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513271
robpercival214763f2016-07-01 23:27:0113272 EXPECT_THAT(callback2.WaitForResult(), IsOk());
13273 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513274
13275 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5213276 ASSERT_TRUE(response);
13277 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213278 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513279 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213280 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113281 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513282 EXPECT_EQ("hello!", response_data);
13283
13284 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5213285 ASSERT_TRUE(response);
13286 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213287 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513288 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213289 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113290 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513291 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5513292}
13293
bncd16676a2016-07-20 16:23:0113294TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5313295 session_deps_.host_resolver->set_synchronous_mode(true);
13296
[email protected]2d6728692011-03-12 01:39:5513297 HttpRequestInfo request;
13298 request.method = "GET";
bncb26024382016-06-29 02:39:4513299 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013300 request.traffic_annotation =
13301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513302
13303 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213304 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313305 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213306 MockRead("\r\n"),
13307 MockRead("hello world"),
13308 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13309 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513310 };
13311
Ryan Sleevib8d7ea02018-05-07 20:01:0113312 StaticSocketDataProvider first_transaction(data_reads,
13313 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713314 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513315
[email protected]8ddf8322012-02-23 18:08:0613316 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913317 ssl.ssl_info.cert =
13318 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13319 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0713320 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513321
[email protected]d973e99a2012-02-17 21:02:3613322 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113323 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513324 hanging_alternate_protocol_socket.set_connect_data(
13325 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713326 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513327 &hanging_alternate_protocol_socket);
13328
bncb26024382016-06-29 02:39:4513329 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0113330 StaticSocketDataProvider second_transaction(data_reads,
13331 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1813332 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4513333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513334
[email protected]49639fa2011-12-20 23:22:4113335 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5513336
danakj1fd259a02016-04-16 03:17:0913337 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813338 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913339 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513340
tfarina42834112016-09-22 13:38:2013341 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113342 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13343 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513344
13345 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213346 ASSERT_TRUE(response);
13347 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513348 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13349
13350 std::string response_data;
robpercival214763f2016-07-01 23:27:0113351 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513352 EXPECT_EQ("hello world", response_data);
13353
bnc87dcefc2017-05-25 12:47:5813354 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913355 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513356
tfarina42834112016-09-22 13:38:2013357 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13359 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513360
13361 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213362 ASSERT_TRUE(response);
13363 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513364 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13365 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213366 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5513367
robpercival214763f2016-07-01 23:27:0113368 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513369 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5513370}
13371
bnc2e884782016-08-11 19:45:1913372// Test that proxy is resolved using the origin url,
13373// regardless of the alternative server.
13374TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
13375 // Configure proxy to bypass www.example.org, which is the origin URL.
13376 ProxyConfig proxy_config;
13377 proxy_config.proxy_rules().ParseFromString("myproxy:70");
13378 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4913379 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
13380 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1913381
13382 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1913383 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1913384 &capturing_proxy_resolver);
13385
13386 TestNetLog net_log;
13387
Bence Béky53a5aef2018-03-29 21:54:1213388 session_deps_.proxy_resolution_service =
13389 std::make_unique<ProxyResolutionService>(
13390 std::move(proxy_config_service), std::move(proxy_resolver_factory),
13391 &net_log);
bnc2e884782016-08-11 19:45:1913392
13393 session_deps_.net_log = &net_log;
13394
13395 // Configure alternative service with a hostname that is not bypassed by the
13396 // proxy.
13397 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13398 HttpServerProperties* http_server_properties =
13399 session->http_server_properties();
13400 url::SchemeHostPort server("https", "www.example.org", 443);
13401 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2113402 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1913403 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113404 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713405 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1913406
13407 // Non-alternative job should hang.
13408 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113409 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1913410 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
13411 session_deps_.socket_factory->AddSocketDataProvider(
13412 &hanging_alternate_protocol_socket);
13413
bnc032658ba2016-09-26 18:17:1513414 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1913415
13416 HttpRequestInfo request;
13417 request.method = "GET";
13418 request.url = GURL("https://www.example.org/");
13419 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013420 request.traffic_annotation =
13421 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1913422
Ryan Hamilton0239aac2018-05-19 00:03:1313423 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1913424 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
13425
13426 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
13427
Ryan Hamilton0239aac2018-05-19 00:03:1313428 spdy::SpdySerializedFrame resp(
13429 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
13430 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1913431 MockRead spdy_reads[] = {
13432 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
13433 };
13434
Ryan Sleevib8d7ea02018-05-07 20:01:0113435 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1913436 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
13437
13438 TestCompletionCallback callback;
13439
13440 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13441
tfarina42834112016-09-22 13:38:2013442 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1913443 EXPECT_THAT(callback.GetResult(rv), IsOk());
13444
13445 const HttpResponseInfo* response = trans.GetResponseInfo();
13446 ASSERT_TRUE(response);
13447 ASSERT_TRUE(response->headers);
13448 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
13449 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213450 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1913451
13452 std::string response_data;
13453 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13454 EXPECT_EQ("hello!", response_data);
13455
13456 // Origin host bypasses proxy, no resolution should have happened.
13457 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
13458}
13459
bncd16676a2016-07-20 16:23:0113460TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1113461 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4213462 proxy_config.set_auto_detect(true);
13463 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1113464
sammc5dd160c2015-04-02 02:43:1313465 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4913466 session_deps_.proxy_resolution_service =
13467 std::make_unique<ProxyResolutionService>(
13468 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
13469 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
13470 std::make_unique<CapturingProxyResolverFactory>(
13471 &capturing_proxy_resolver),
13472 nullptr);
vishal.b62985ca92015-04-17 08:45:5113473 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0713474 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1113475
13476 HttpRequestInfo request;
13477 request.method = "GET";
bncb26024382016-06-29 02:39:4513478 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013479 request.traffic_annotation =
13480 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1113481
13482 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213483 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313484 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213485 MockRead("\r\n"),
13486 MockRead("hello world"),
13487 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13488 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1113489 };
13490
Ryan Sleevib8d7ea02018-05-07 20:01:0113491 StaticSocketDataProvider first_transaction(data_reads,
13492 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713493 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513494 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613495 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513496 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1113497
bnc032658ba2016-09-26 18:17:1513498 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1113499
Ryan Hamilton0239aac2018-05-19 00:03:1313500 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513501 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1113502 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313503 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2513504 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13505 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1313506 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4113507 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1113508 };
13509
[email protected]d911f1b2010-05-05 22:39:4213510 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
13511
Raul Tambre94493c652019-03-11 17:18:3513512 spdy::SpdySerializedFrame resp(
13513 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313514 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1113515 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113516 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
13517 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1113518 };
13519
Ryan Sleevib8d7ea02018-05-07 20:01:0113520 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713521 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1113522
[email protected]d973e99a2012-02-17 21:02:3613523 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113524 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513525 hanging_non_alternate_protocol_socket.set_connect_data(
13526 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713527 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513528 &hanging_non_alternate_protocol_socket);
13529
[email protected]49639fa2011-12-20 23:22:4113530 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1113531
danakj1fd259a02016-04-16 03:17:0913532 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813533 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913534 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113535
tfarina42834112016-09-22 13:38:2013536 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4113537 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13538 EXPECT_THAT(callback.WaitForResult(), IsOk());
13539
13540 const HttpResponseInfo* response = trans->GetResponseInfo();
13541 ASSERT_TRUE(response);
13542 ASSERT_TRUE(response->headers);
13543 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
13544 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213545 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4113546
13547 std::string response_data;
13548 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
13549 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1113550
bnc87dcefc2017-05-25 12:47:5813551 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913552 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113553
tfarina42834112016-09-22 13:38:2013554 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113555 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13556 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1113557
mmenkea2dcd3bf2016-08-16 21:49:4113558 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213559 ASSERT_TRUE(response);
13560 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213561 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313562 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213563 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1113564
robpercival214763f2016-07-01 23:27:0113565 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1113566 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4513567 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
13568 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313569 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2313570 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313571 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1113572
[email protected]029c83b62013-01-24 05:28:2013573 LoadTimingInfo load_timing_info;
13574 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
13575 TestLoadTimingNotReusedWithPac(load_timing_info,
13576 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1113577}
[email protected]631f1322010-04-30 17:59:1113578
bncd16676a2016-07-20 16:23:0113579TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4813580 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5413581 HttpRequestInfo request;
13582 request.method = "GET";
bncb26024382016-06-29 02:39:4513583 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013584 request.traffic_annotation =
13585 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413586
13587 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213588 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313589 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213590 MockRead("\r\n"),
13591 MockRead("hello world"),
13592 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5413593 };
13594
Ryan Sleevib8d7ea02018-05-07 20:01:0113595 StaticSocketDataProvider first_transaction(data_reads,
13596 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713597 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513598 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613599 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413601
bnc032658ba2016-09-26 18:17:1513602 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413603
Ryan Hamilton0239aac2018-05-19 00:03:1313604 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513605 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113606 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413607
Raul Tambre94493c652019-03-11 17:18:3513608 spdy::SpdySerializedFrame resp(
13609 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313610 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413611 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113612 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413613 };
13614
Ryan Sleevib8d7ea02018-05-07 20:01:0113615 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713616 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413617
[email protected]83039bb2011-12-09 18:43:5513618 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413619
danakj1fd259a02016-04-16 03:17:0913620 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5413621
bnc87dcefc2017-05-25 12:47:5813622 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913623 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413624
tfarina42834112016-09-22 13:38:2013625 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113626 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13627 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413628
13629 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213630 ASSERT_TRUE(response);
13631 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413632 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13633
13634 std::string response_data;
robpercival214763f2016-07-01 23:27:0113635 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413636 EXPECT_EQ("hello world", response_data);
13637
13638 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2513639 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4013640 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1113641 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3413642 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
13643 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2713644 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5213645 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3813646
bnc87dcefc2017-05-25 12:47:5813647 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913648 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413649
tfarina42834112016-09-22 13:38:2013650 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113651 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13652 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413653
13654 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213655 ASSERT_TRUE(response);
13656 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213657 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313658 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213659 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413660
robpercival214763f2016-07-01 23:27:0113661 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413662 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4213663}
13664
[email protected]044de0642010-06-17 10:42:1513665// GenerateAuthToken is a mighty big test.
13666// It tests all permutation of GenerateAuthToken behavior:
13667// - Synchronous and Asynchronous completion.
13668// - OK or error on completion.
13669// - Direct connection, non-authenticating proxy, and authenticating proxy.
13670// - HTTP or HTTPS backend (to include proxy tunneling).
13671// - Non-authenticating and authenticating backend.
13672//
[email protected]fe3b7dc2012-02-03 19:52:0913673// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1513674// problems generating an auth token for an authenticating proxy, we don't
13675// need to test all permutations of the backend server).
13676//
13677// The test proceeds by going over each of the configuration cases, and
13678// potentially running up to three rounds in each of the tests. The TestConfig
13679// specifies both the configuration for the test as well as the expectations
13680// for the results.
bncd16676a2016-07-20 16:23:0113681TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5013682 static const char kServer[] = "http://www.example.com";
13683 static const char kSecureServer[] = "https://www.example.com";
13684 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1513685
13686 enum AuthTiming {
13687 AUTH_NONE,
13688 AUTH_SYNC,
13689 AUTH_ASYNC,
13690 };
13691
13692 const MockWrite kGet(
13693 "GET / HTTP/1.1\r\n"
13694 "Host: www.example.com\r\n"
13695 "Connection: keep-alive\r\n\r\n");
13696 const MockWrite kGetProxy(
13697 "GET http://www.example.com/ HTTP/1.1\r\n"
13698 "Host: www.example.com\r\n"
13699 "Proxy-Connection: keep-alive\r\n\r\n");
13700 const MockWrite kGetAuth(
13701 "GET / HTTP/1.1\r\n"
13702 "Host: www.example.com\r\n"
13703 "Connection: keep-alive\r\n"
13704 "Authorization: auth_token\r\n\r\n");
13705 const MockWrite kGetProxyAuth(
13706 "GET http://www.example.com/ HTTP/1.1\r\n"
13707 "Host: www.example.com\r\n"
13708 "Proxy-Connection: keep-alive\r\n"
13709 "Proxy-Authorization: auth_token\r\n\r\n");
13710 const MockWrite kGetAuthThroughProxy(
13711 "GET http://www.example.com/ HTTP/1.1\r\n"
13712 "Host: www.example.com\r\n"
13713 "Proxy-Connection: keep-alive\r\n"
13714 "Authorization: auth_token\r\n\r\n");
13715 const MockWrite kGetAuthWithProxyAuth(
13716 "GET http://www.example.com/ HTTP/1.1\r\n"
13717 "Host: www.example.com\r\n"
13718 "Proxy-Connection: keep-alive\r\n"
13719 "Proxy-Authorization: auth_token\r\n"
13720 "Authorization: auth_token\r\n\r\n");
13721 const MockWrite kConnect(
13722 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713723 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513724 "Proxy-Connection: keep-alive\r\n\r\n");
13725 const MockWrite kConnectProxyAuth(
13726 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713727 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513728 "Proxy-Connection: keep-alive\r\n"
13729 "Proxy-Authorization: auth_token\r\n\r\n");
13730
13731 const MockRead kSuccess(
13732 "HTTP/1.1 200 OK\r\n"
13733 "Content-Type: text/html; charset=iso-8859-1\r\n"
13734 "Content-Length: 3\r\n\r\n"
13735 "Yes");
13736 const MockRead kFailure(
13737 "Should not be called.");
13738 const MockRead kServerChallenge(
13739 "HTTP/1.1 401 Unauthorized\r\n"
13740 "WWW-Authenticate: Mock realm=server\r\n"
13741 "Content-Type: text/html; charset=iso-8859-1\r\n"
13742 "Content-Length: 14\r\n\r\n"
13743 "Unauthorized\r\n");
13744 const MockRead kProxyChallenge(
13745 "HTTP/1.1 407 Unauthorized\r\n"
13746 "Proxy-Authenticate: Mock realm=proxy\r\n"
13747 "Proxy-Connection: close\r\n"
13748 "Content-Type: text/html; charset=iso-8859-1\r\n"
13749 "Content-Length: 14\r\n\r\n"
13750 "Unauthorized\r\n");
13751 const MockRead kProxyConnected(
13752 "HTTP/1.1 200 Connection Established\r\n\r\n");
13753
13754 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
13755 // no constructors, but the C++ compiler on Windows warns about
13756 // unspecified data in compound literals. So, moved to using constructors,
13757 // and TestRound's created with the default constructor should not be used.
13758 struct TestRound {
13759 TestRound()
Raul Tambre94493c652019-03-11 17:18:3513760 : expected_rv(ERR_UNEXPECTED),
13761 extra_write(nullptr),
13762 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4313763 TestRound(const MockWrite& write_arg,
13764 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1513765 int expected_rv_arg)
13766 : write(write_arg),
13767 read(read_arg),
13768 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3513769 extra_write(nullptr),
13770 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1513771 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
13772 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0113773 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1513774 : write(write_arg),
13775 read(read_arg),
13776 expected_rv(expected_rv_arg),
13777 extra_write(extra_write_arg),
13778 extra_read(extra_read_arg) {
13779 }
13780 MockWrite write;
13781 MockRead read;
13782 int expected_rv;
13783 const MockWrite* extra_write;
13784 const MockRead* extra_read;
13785 };
13786
13787 static const int kNoSSL = 500;
13788
13789 struct TestConfig {
asanka463ca4262016-11-16 02:34:3113790 int line_number;
thestig9d3bb0c2015-01-24 00:49:5113791 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1513792 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3113793 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5113794 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1513795 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3113796 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1513797 int num_auth_rounds;
13798 int first_ssl_round;
asankae2257db2016-10-11 22:03:1613799 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1513800 } test_configs[] = {
asankac93076192016-10-03 15:46:0213801 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113802 {__LINE__,
13803 nullptr,
asankac93076192016-10-03 15:46:0213804 AUTH_NONE,
13805 OK,
13806 kServer,
13807 AUTH_NONE,
13808 OK,
13809 1,
13810 kNoSSL,
13811 {TestRound(kGet, kSuccess, OK)}},
13812 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113813 {__LINE__,
13814 nullptr,
asankac93076192016-10-03 15:46:0213815 AUTH_NONE,
13816 OK,
13817 kServer,
13818 AUTH_SYNC,
13819 OK,
13820 2,
13821 kNoSSL,
13822 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513823 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113824 {__LINE__,
13825 nullptr,
asankac93076192016-10-03 15:46:0213826 AUTH_NONE,
13827 OK,
13828 kServer,
13829 AUTH_SYNC,
13830 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613831 3,
13832 kNoSSL,
13833 {TestRound(kGet, kServerChallenge, OK),
13834 TestRound(kGet, kServerChallenge, OK),
13835 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113836 {__LINE__,
13837 nullptr,
asankae2257db2016-10-11 22:03:1613838 AUTH_NONE,
13839 OK,
13840 kServer,
13841 AUTH_SYNC,
13842 ERR_UNSUPPORTED_AUTH_SCHEME,
13843 2,
13844 kNoSSL,
13845 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113846 {__LINE__,
13847 nullptr,
asankae2257db2016-10-11 22:03:1613848 AUTH_NONE,
13849 OK,
13850 kServer,
13851 AUTH_SYNC,
13852 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
13853 2,
13854 kNoSSL,
13855 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113856 {__LINE__,
13857 kProxy,
asankae2257db2016-10-11 22:03:1613858 AUTH_SYNC,
13859 ERR_FAILED,
13860 kServer,
13861 AUTH_NONE,
13862 OK,
13863 2,
13864 kNoSSL,
13865 {TestRound(kGetProxy, kProxyChallenge, OK),
13866 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113867 {__LINE__,
13868 kProxy,
asankae2257db2016-10-11 22:03:1613869 AUTH_ASYNC,
13870 ERR_FAILED,
13871 kServer,
13872 AUTH_NONE,
13873 OK,
13874 2,
13875 kNoSSL,
13876 {TestRound(kGetProxy, kProxyChallenge, OK),
13877 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113878 {__LINE__,
13879 nullptr,
asankae2257db2016-10-11 22:03:1613880 AUTH_NONE,
13881 OK,
13882 kServer,
13883 AUTH_SYNC,
13884 ERR_FAILED,
asankac93076192016-10-03 15:46:0213885 2,
13886 kNoSSL,
13887 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613888 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113889 {__LINE__,
13890 nullptr,
asankae2257db2016-10-11 22:03:1613891 AUTH_NONE,
13892 OK,
13893 kServer,
13894 AUTH_ASYNC,
13895 ERR_FAILED,
13896 2,
13897 kNoSSL,
13898 {TestRound(kGet, kServerChallenge, OK),
13899 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113900 {__LINE__,
13901 nullptr,
asankac93076192016-10-03 15:46:0213902 AUTH_NONE,
13903 OK,
13904 kServer,
13905 AUTH_ASYNC,
13906 OK,
13907 2,
13908 kNoSSL,
13909 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513910 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113911 {__LINE__,
13912 nullptr,
asankac93076192016-10-03 15:46:0213913 AUTH_NONE,
13914 OK,
13915 kServer,
13916 AUTH_ASYNC,
13917 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613918 3,
asankac93076192016-10-03 15:46:0213919 kNoSSL,
13920 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613921 // The second round uses a HttpAuthHandlerMock that always succeeds.
13922 TestRound(kGet, kServerChallenge, OK),
13923 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213924 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113925 {__LINE__,
13926 kProxy,
asankac93076192016-10-03 15:46:0213927 AUTH_NONE,
13928 OK,
13929 kServer,
13930 AUTH_NONE,
13931 OK,
13932 1,
13933 kNoSSL,
13934 {TestRound(kGetProxy, kSuccess, OK)}},
13935 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113936 {__LINE__,
13937 kProxy,
asankac93076192016-10-03 15:46:0213938 AUTH_NONE,
13939 OK,
13940 kServer,
13941 AUTH_SYNC,
13942 OK,
13943 2,
13944 kNoSSL,
13945 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513946 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113947 {__LINE__,
13948 kProxy,
asankac93076192016-10-03 15:46:0213949 AUTH_NONE,
13950 OK,
13951 kServer,
13952 AUTH_SYNC,
13953 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613954 3,
asankac93076192016-10-03 15:46:0213955 kNoSSL,
13956 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613957 TestRound(kGetProxy, kServerChallenge, OK),
13958 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113959 {__LINE__,
13960 kProxy,
asankac93076192016-10-03 15:46:0213961 AUTH_NONE,
13962 OK,
13963 kServer,
13964 AUTH_ASYNC,
13965 OK,
13966 2,
13967 kNoSSL,
13968 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513969 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113970 {__LINE__,
13971 kProxy,
asankac93076192016-10-03 15:46:0213972 AUTH_NONE,
13973 OK,
13974 kServer,
13975 AUTH_ASYNC,
13976 ERR_INVALID_AUTH_CREDENTIALS,
13977 2,
13978 kNoSSL,
13979 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613980 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213981 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113982 {__LINE__,
13983 kProxy,
asankac93076192016-10-03 15:46:0213984 AUTH_SYNC,
13985 OK,
13986 kServer,
13987 AUTH_NONE,
13988 OK,
13989 2,
13990 kNoSSL,
13991 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513992 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113993 {__LINE__,
13994 kProxy,
asankac93076192016-10-03 15:46:0213995 AUTH_SYNC,
13996 ERR_INVALID_AUTH_CREDENTIALS,
13997 kServer,
13998 AUTH_NONE,
13999 OK,
14000 2,
14001 kNoSSL,
14002 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614003 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114004 {__LINE__,
14005 kProxy,
asankac93076192016-10-03 15:46:0214006 AUTH_ASYNC,
14007 OK,
14008 kServer,
14009 AUTH_NONE,
14010 OK,
14011 2,
14012 kNoSSL,
14013 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514014 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114015 {__LINE__,
14016 kProxy,
asankac93076192016-10-03 15:46:0214017 AUTH_ASYNC,
14018 ERR_INVALID_AUTH_CREDENTIALS,
14019 kServer,
14020 AUTH_NONE,
14021 OK,
14022 2,
14023 kNoSSL,
14024 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614025 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114026 {__LINE__,
14027 kProxy,
14028 AUTH_ASYNC,
14029 ERR_INVALID_AUTH_CREDENTIALS,
14030 kServer,
14031 AUTH_NONE,
14032 OK,
14033 3,
14034 kNoSSL,
14035 {TestRound(kGetProxy, kProxyChallenge, OK),
14036 TestRound(kGetProxy, kProxyChallenge, OK),
14037 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214038 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114039 {__LINE__,
14040 kProxy,
asankac93076192016-10-03 15:46:0214041 AUTH_SYNC,
14042 OK,
14043 kServer,
14044 AUTH_SYNC,
14045 OK,
14046 3,
14047 kNoSSL,
14048 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514049 TestRound(kGetProxyAuth, kServerChallenge, OK),
14050 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114051 {__LINE__,
14052 kProxy,
asankac93076192016-10-03 15:46:0214053 AUTH_SYNC,
14054 OK,
14055 kServer,
14056 AUTH_SYNC,
14057 ERR_INVALID_AUTH_CREDENTIALS,
14058 3,
14059 kNoSSL,
14060 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514061 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614062 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114063 {__LINE__,
14064 kProxy,
asankac93076192016-10-03 15:46:0214065 AUTH_ASYNC,
14066 OK,
14067 kServer,
14068 AUTH_SYNC,
14069 OK,
14070 3,
14071 kNoSSL,
14072 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514073 TestRound(kGetProxyAuth, kServerChallenge, OK),
14074 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114075 {__LINE__,
14076 kProxy,
asankac93076192016-10-03 15:46:0214077 AUTH_ASYNC,
14078 OK,
14079 kServer,
14080 AUTH_SYNC,
14081 ERR_INVALID_AUTH_CREDENTIALS,
14082 3,
14083 kNoSSL,
14084 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514085 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614086 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114087 {__LINE__,
14088 kProxy,
asankac93076192016-10-03 15:46:0214089 AUTH_SYNC,
14090 OK,
14091 kServer,
14092 AUTH_ASYNC,
14093 OK,
14094 3,
14095 kNoSSL,
14096 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514097 TestRound(kGetProxyAuth, kServerChallenge, OK),
14098 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114099 {__LINE__,
14100 kProxy,
14101 AUTH_SYNC,
14102 ERR_INVALID_AUTH_CREDENTIALS,
14103 kServer,
14104 AUTH_ASYNC,
14105 OK,
14106 4,
14107 kNoSSL,
14108 {TestRound(kGetProxy, kProxyChallenge, OK),
14109 TestRound(kGetProxy, kProxyChallenge, OK),
14110 TestRound(kGetProxyAuth, kServerChallenge, OK),
14111 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
14112 {__LINE__,
14113 kProxy,
asankac93076192016-10-03 15:46:0214114 AUTH_SYNC,
14115 OK,
14116 kServer,
14117 AUTH_ASYNC,
14118 ERR_INVALID_AUTH_CREDENTIALS,
14119 3,
14120 kNoSSL,
14121 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514122 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614123 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114124 {__LINE__,
14125 kProxy,
asankac93076192016-10-03 15:46:0214126 AUTH_ASYNC,
14127 OK,
14128 kServer,
14129 AUTH_ASYNC,
14130 OK,
14131 3,
14132 kNoSSL,
14133 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514134 TestRound(kGetProxyAuth, kServerChallenge, OK),
14135 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114136 {__LINE__,
14137 kProxy,
asankac93076192016-10-03 15:46:0214138 AUTH_ASYNC,
14139 OK,
14140 kServer,
14141 AUTH_ASYNC,
14142 ERR_INVALID_AUTH_CREDENTIALS,
14143 3,
14144 kNoSSL,
14145 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514146 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614147 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114148 {__LINE__,
14149 kProxy,
14150 AUTH_ASYNC,
14151 ERR_INVALID_AUTH_CREDENTIALS,
14152 kServer,
14153 AUTH_ASYNC,
14154 ERR_INVALID_AUTH_CREDENTIALS,
14155 4,
14156 kNoSSL,
14157 {TestRound(kGetProxy, kProxyChallenge, OK),
14158 TestRound(kGetProxy, kProxyChallenge, OK),
14159 TestRound(kGetProxyAuth, kServerChallenge, OK),
14160 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214161 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114162 {__LINE__,
14163 nullptr,
asankac93076192016-10-03 15:46:0214164 AUTH_NONE,
14165 OK,
14166 kSecureServer,
14167 AUTH_NONE,
14168 OK,
14169 1,
14170 0,
14171 {TestRound(kGet, kSuccess, OK)}},
14172 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114173 {__LINE__,
14174 nullptr,
asankac93076192016-10-03 15:46:0214175 AUTH_NONE,
14176 OK,
14177 kSecureServer,
14178 AUTH_SYNC,
14179 OK,
14180 2,
14181 0,
14182 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514183 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114184 {__LINE__,
14185 nullptr,
asankac93076192016-10-03 15:46:0214186 AUTH_NONE,
14187 OK,
14188 kSecureServer,
14189 AUTH_SYNC,
14190 ERR_INVALID_AUTH_CREDENTIALS,
14191 2,
14192 0,
asankae2257db2016-10-11 22:03:1614193 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114194 {__LINE__,
14195 nullptr,
asankac93076192016-10-03 15:46:0214196 AUTH_NONE,
14197 OK,
14198 kSecureServer,
14199 AUTH_ASYNC,
14200 OK,
14201 2,
14202 0,
14203 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514204 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114205 {__LINE__,
14206 nullptr,
asankac93076192016-10-03 15:46:0214207 AUTH_NONE,
14208 OK,
14209 kSecureServer,
14210 AUTH_ASYNC,
14211 ERR_INVALID_AUTH_CREDENTIALS,
14212 2,
14213 0,
asankae2257db2016-10-11 22:03:1614214 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214215 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114216 {__LINE__,
14217 kProxy,
asankac93076192016-10-03 15:46:0214218 AUTH_NONE,
14219 OK,
14220 kSecureServer,
14221 AUTH_NONE,
14222 OK,
14223 1,
14224 0,
14225 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
14226 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114227 {__LINE__,
14228 kProxy,
asankac93076192016-10-03 15:46:0214229 AUTH_NONE,
14230 OK,
14231 kSecureServer,
14232 AUTH_SYNC,
14233 OK,
14234 2,
14235 0,
14236 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514237 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114238 {__LINE__,
14239 kProxy,
asankac93076192016-10-03 15:46:0214240 AUTH_NONE,
14241 OK,
14242 kSecureServer,
14243 AUTH_SYNC,
14244 ERR_INVALID_AUTH_CREDENTIALS,
14245 2,
14246 0,
14247 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614248 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114249 {__LINE__,
14250 kProxy,
asankac93076192016-10-03 15:46:0214251 AUTH_NONE,
14252 OK,
14253 kSecureServer,
14254 AUTH_ASYNC,
14255 OK,
14256 2,
14257 0,
14258 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514259 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114260 {__LINE__,
14261 kProxy,
asankac93076192016-10-03 15:46:0214262 AUTH_NONE,
14263 OK,
14264 kSecureServer,
14265 AUTH_ASYNC,
14266 ERR_INVALID_AUTH_CREDENTIALS,
14267 2,
14268 0,
14269 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614270 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214271 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114272 {__LINE__,
14273 kProxy,
asankac93076192016-10-03 15:46:0214274 AUTH_SYNC,
14275 OK,
14276 kSecureServer,
14277 AUTH_NONE,
14278 OK,
14279 2,
14280 1,
14281 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514282 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114283 {__LINE__,
14284 kProxy,
asankac93076192016-10-03 15:46:0214285 AUTH_SYNC,
14286 ERR_INVALID_AUTH_CREDENTIALS,
14287 kSecureServer,
14288 AUTH_NONE,
14289 OK,
14290 2,
14291 kNoSSL,
14292 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614293 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114294 {__LINE__,
14295 kProxy,
asankae2257db2016-10-11 22:03:1614296 AUTH_SYNC,
14297 ERR_UNSUPPORTED_AUTH_SCHEME,
14298 kSecureServer,
14299 AUTH_NONE,
14300 OK,
14301 2,
14302 kNoSSL,
14303 {TestRound(kConnect, kProxyChallenge, OK),
14304 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114305 {__LINE__,
14306 kProxy,
asankae2257db2016-10-11 22:03:1614307 AUTH_SYNC,
14308 ERR_UNEXPECTED,
14309 kSecureServer,
14310 AUTH_NONE,
14311 OK,
14312 2,
14313 kNoSSL,
14314 {TestRound(kConnect, kProxyChallenge, OK),
14315 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3114316 {__LINE__,
14317 kProxy,
asankac93076192016-10-03 15:46:0214318 AUTH_ASYNC,
14319 OK,
14320 kSecureServer,
14321 AUTH_NONE,
14322 OK,
14323 2,
14324 1,
14325 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514326 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114327 {__LINE__,
14328 kProxy,
asankac93076192016-10-03 15:46:0214329 AUTH_ASYNC,
14330 ERR_INVALID_AUTH_CREDENTIALS,
14331 kSecureServer,
14332 AUTH_NONE,
14333 OK,
14334 2,
14335 kNoSSL,
14336 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614337 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0214338 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114339 {__LINE__,
14340 kProxy,
asankac93076192016-10-03 15:46:0214341 AUTH_SYNC,
14342 OK,
14343 kSecureServer,
14344 AUTH_SYNC,
14345 OK,
14346 3,
14347 1,
14348 {TestRound(kConnect, kProxyChallenge, OK),
14349 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14350 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514351 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114352 {__LINE__,
14353 kProxy,
asankac93076192016-10-03 15:46:0214354 AUTH_SYNC,
14355 OK,
14356 kSecureServer,
14357 AUTH_SYNC,
14358 ERR_INVALID_AUTH_CREDENTIALS,
14359 3,
14360 1,
14361 {TestRound(kConnect, kProxyChallenge, OK),
14362 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14363 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614364 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114365 {__LINE__,
14366 kProxy,
asankac93076192016-10-03 15:46:0214367 AUTH_ASYNC,
14368 OK,
14369 kSecureServer,
14370 AUTH_SYNC,
14371 OK,
14372 3,
14373 1,
14374 {TestRound(kConnect, kProxyChallenge, OK),
14375 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14376 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514377 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114378 {__LINE__,
14379 kProxy,
asankac93076192016-10-03 15:46:0214380 AUTH_ASYNC,
14381 OK,
14382 kSecureServer,
14383 AUTH_SYNC,
14384 ERR_INVALID_AUTH_CREDENTIALS,
14385 3,
14386 1,
14387 {TestRound(kConnect, kProxyChallenge, OK),
14388 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14389 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614390 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114391 {__LINE__,
14392 kProxy,
asankac93076192016-10-03 15:46:0214393 AUTH_SYNC,
14394 OK,
14395 kSecureServer,
14396 AUTH_ASYNC,
14397 OK,
14398 3,
14399 1,
14400 {TestRound(kConnect, kProxyChallenge, OK),
14401 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14402 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514403 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114404 {__LINE__,
14405 kProxy,
asankac93076192016-10-03 15:46:0214406 AUTH_SYNC,
14407 OK,
14408 kSecureServer,
14409 AUTH_ASYNC,
14410 ERR_INVALID_AUTH_CREDENTIALS,
14411 3,
14412 1,
14413 {TestRound(kConnect, kProxyChallenge, OK),
14414 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14415 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614416 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114417 {__LINE__,
14418 kProxy,
asankac93076192016-10-03 15:46:0214419 AUTH_ASYNC,
14420 OK,
14421 kSecureServer,
14422 AUTH_ASYNC,
14423 OK,
14424 3,
14425 1,
14426 {TestRound(kConnect, kProxyChallenge, OK),
14427 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14428 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514429 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114430 {__LINE__,
14431 kProxy,
asankac93076192016-10-03 15:46:0214432 AUTH_ASYNC,
14433 OK,
14434 kSecureServer,
14435 AUTH_ASYNC,
14436 ERR_INVALID_AUTH_CREDENTIALS,
14437 3,
14438 1,
14439 {TestRound(kConnect, kProxyChallenge, OK),
14440 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14441 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614442 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114443 {__LINE__,
14444 kProxy,
14445 AUTH_ASYNC,
14446 ERR_INVALID_AUTH_CREDENTIALS,
14447 kSecureServer,
14448 AUTH_ASYNC,
14449 ERR_INVALID_AUTH_CREDENTIALS,
14450 4,
14451 2,
14452 {TestRound(kConnect, kProxyChallenge, OK),
14453 TestRound(kConnect, kProxyChallenge, OK),
14454 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14455 &kServerChallenge),
14456 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1514457 };
14458
asanka463ca4262016-11-16 02:34:3114459 for (const auto& test_config : test_configs) {
14460 SCOPED_TRACE(::testing::Message() << "Test config at "
14461 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0814462 HttpAuthHandlerMock::Factory* auth_factory(
14463 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714464 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4914465 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2614466
14467 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1514468 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3114469 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0814470 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14471 std::string auth_challenge = "Mock realm=proxy";
14472 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2414473 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14474 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0814475 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2014476 empty_ssl_info, origin,
14477 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814478 auth_handler->SetGenerateExpectation(
14479 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114480 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0814481 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
14482 }
[email protected]044de0642010-06-17 10:42:1514483 }
14484 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0014485 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1514486 std::string auth_challenge = "Mock realm=server";
14487 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2414488 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14489 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1514490 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014491 empty_ssl_info, origin,
14492 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514493 auth_handler->SetGenerateExpectation(
14494 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114495 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0814496 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1614497
14498 // The second handler always succeeds. It should only be used where there
14499 // are multiple auth sessions for server auth in the same network
14500 // transaction using the same auth scheme.
14501 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1914502 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1614503 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
14504 empty_ssl_info, origin,
14505 NetLogWithSource());
14506 second_handler->SetGenerateExpectation(true, OK);
14507 auth_factory->AddMockHandler(second_handler.release(),
14508 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1514509 }
14510 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5914511 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914512 ProxyResolutionService::CreateFixed(test_config.proxy_url,
14513 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514514 } else {
Bence Béky53a5aef2018-03-29 21:54:1214515 session_deps_.proxy_resolution_service =
14516 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1514517 }
14518
14519 HttpRequestInfo request;
14520 request.method = "GET";
14521 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e2018-02-07 07:41:1014522 request.traffic_annotation =
14523 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514524
danakj1fd259a02016-04-16 03:17:0914525 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1514526
rchcb68dc62015-05-21 04:45:3614527 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
14528
14529 std::vector<std::vector<MockRead>> mock_reads(1);
14530 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1514531 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214532 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1514533 const TestRound& read_write_round = test_config.rounds[round];
14534
14535 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3614536 mock_reads.back().push_back(read_write_round.read);
14537 mock_writes.back().push_back(read_write_round.write);
14538
14539 // kProxyChallenge uses Proxy-Connection: close which means that the
14540 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5414541 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3614542 mock_reads.push_back(std::vector<MockRead>());
14543 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1514544 }
14545
rchcb68dc62015-05-21 04:45:3614546 if (read_write_round.extra_read) {
14547 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1514548 }
rchcb68dc62015-05-21 04:45:3614549 if (read_write_round.extra_write) {
14550 mock_writes.back().push_back(*read_write_round.extra_write);
14551 }
[email protected]044de0642010-06-17 10:42:1514552
14553 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1514554 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0714555 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1514556 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3614557 }
[email protected]044de0642010-06-17 10:42:1514558
danakj1fd259a02016-04-16 03:17:0914559 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3614560 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1914561 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0114562 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3614563 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3214564 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3614565 }
14566
mmenkecc2298e2015-12-07 18:20:1814567 // Transaction must be created after DataProviders, so it's destroyed before
14568 // they are as well.
14569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14570
rchcb68dc62015-05-21 04:45:3614571 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214572 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3614573 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1514574 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4114575 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1514576 int rv;
14577 if (round == 0) {
tfarina42834112016-09-22 13:38:2014578 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514579 } else {
[email protected]49639fa2011-12-20 23:22:4114580 rv = trans.RestartWithAuth(
14581 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1514582 }
14583 if (rv == ERR_IO_PENDING)
14584 rv = callback.WaitForResult();
14585
14586 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1614587 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5014588 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5514589 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1514590 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
14591 continue;
14592 }
14593 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5814594 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1514595 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5814596 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1614597 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1514598 }
14599 }
[email protected]e5ae96a2010-04-14 20:12:4514600 }
14601}
14602
bncd16676a2016-07-20 16:23:0114603TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1414604 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1414605 HttpAuthHandlerMock::Factory* auth_factory(
14606 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714607 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1214608 session_deps_.proxy_resolution_service =
14609 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0714610 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1414611
14612 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14613 auth_handler->set_connection_based(true);
14614 std::string auth_challenge = "Mock realm=server";
14615 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2414616 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14617 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4914618 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1414619 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014620 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814621 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1414622
[email protected]c871bce92010-07-15 21:51:1414623 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3514624 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1414625 HttpRequestInfo request;
14626 request.method = "GET";
14627 request.url = origin;
Ramin Halavatib5e433e2018-02-07 07:41:1014628 request.traffic_annotation =
14629 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2714630
danakj1fd259a02016-04-16 03:17:0914631 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1014632
14633 // Use a TCP Socket Pool with only one connection per group. This is used
14634 // to validate that the TCP socket is not released to the pool between
14635 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4214636 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3614637 CommonConnectJobParams common_connect_job_params(
14638 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2814639 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5914640 50, // Max sockets for pool
14641 1, // Max sockets per group
14642 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3614643 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5214644 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1914645 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4014646 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
14647 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4814648 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1014649
bnc691fda62016-08-12 00:43:1614650 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114651 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1414652
14653 const MockWrite kGet(
14654 "GET / HTTP/1.1\r\n"
14655 "Host: www.example.com\r\n"
14656 "Connection: keep-alive\r\n\r\n");
14657 const MockWrite kGetAuth(
14658 "GET / HTTP/1.1\r\n"
14659 "Host: www.example.com\r\n"
14660 "Connection: keep-alive\r\n"
14661 "Authorization: auth_token\r\n\r\n");
14662
14663 const MockRead kServerChallenge(
14664 "HTTP/1.1 401 Unauthorized\r\n"
14665 "WWW-Authenticate: Mock realm=server\r\n"
14666 "Content-Type: text/html; charset=iso-8859-1\r\n"
14667 "Content-Length: 14\r\n\r\n"
14668 "Unauthorized\r\n");
14669 const MockRead kSuccess(
14670 "HTTP/1.1 200 OK\r\n"
14671 "Content-Type: text/html; charset=iso-8859-1\r\n"
14672 "Content-Length: 3\r\n\r\n"
14673 "Yes");
14674
14675 MockWrite writes[] = {
14676 // First round
14677 kGet,
14678 // Second round
14679 kGetAuth,
14680 // Third round
14681 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3014682 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1014683 kGetAuth,
14684 // Competing request
14685 kGet,
[email protected]c871bce92010-07-15 21:51:1414686 };
14687 MockRead reads[] = {
14688 // First round
14689 kServerChallenge,
14690 // Second round
14691 kServerChallenge,
14692 // Third round
[email protected]eca50e122010-09-11 14:03:3014693 kServerChallenge,
14694 // Fourth round
[email protected]c871bce92010-07-15 21:51:1414695 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1014696 // Competing response
14697 kSuccess,
[email protected]c871bce92010-07-15 21:51:1414698 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114699 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0714700 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1414701
Matt Menkef6edce752019-03-19 17:21:5614702 const ClientSocketPool::GroupId kSocketGroup(
14703 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3414704 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
14705 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1014706
14707 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1414708 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2014709 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1414710 if (rv == ERR_IO_PENDING)
14711 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114712 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614713 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214714 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814715 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314716 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114717 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14718 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414719
[email protected]7ef4cbbb2011-02-06 11:19:1014720 // In between rounds, another request comes in for the same domain.
14721 // It should not be able to grab the TCP socket that trans has already
14722 // claimed.
bnc691fda62016-08-12 00:43:1614723 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114724 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2014725 rv = trans_compete.Start(&request, callback_compete.callback(),
14726 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114727 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1014728 // callback_compete.WaitForResult at this point would stall forever,
14729 // since the HttpNetworkTransaction does not release the request back to
14730 // the pool until after authentication completes.
14731
14732 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1414733 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614734 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414735 if (rv == ERR_IO_PENDING)
14736 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114737 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614738 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214739 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814740 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314741 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114742 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14743 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414744
[email protected]7ef4cbbb2011-02-06 11:19:1014745 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1414746 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614747 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414748 if (rv == ERR_IO_PENDING)
14749 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114750 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614751 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214752 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814753 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314754 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114755 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14756 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3014757
[email protected]7ef4cbbb2011-02-06 11:19:1014758 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3014759 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614760 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3014761 if (rv == ERR_IO_PENDING)
14762 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114763 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614764 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214765 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814766 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314767 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014768
asanka463ca4262016-11-16 02:34:3114769 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
14770 // auth handler should transition to a DONE state in concert with the remote
14771 // server. But that's not something we can test here with a mock handler.
14772 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
14773 auth_handler->state());
14774
[email protected]7ef4cbbb2011-02-06 11:19:1014775 // Read the body since the fourth round was successful. This will also
14776 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4414777 scoped_refptr<IOBufferWithSize> io_buf =
14778 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1614779 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014780 if (rv == ERR_IO_PENDING)
14781 rv = callback.WaitForResult();
14782 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614783 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014784 EXPECT_EQ(0, rv);
14785 // There are still 0 idle sockets, since the trans_compete transaction
14786 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314787 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014788
14789 // The competing request can now finish. Wait for the headers and then
14790 // read the body.
14791 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0114792 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614793 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014794 if (rv == ERR_IO_PENDING)
14795 rv = callback.WaitForResult();
14796 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614797 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014798 EXPECT_EQ(0, rv);
14799
14800 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314801 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1414802}
14803
[email protected]65041fa2010-05-21 06:56:5314804// This tests the case that a request is issued via http instead of spdy after
14805// npn is negotiated.
bncd16676a2016-07-20 16:23:0114806TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5314807 HttpRequestInfo request;
14808 request.method = "GET";
bncce36dca22015-04-21 22:11:2314809 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014810 request.traffic_annotation =
14811 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5314812
14813 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314814 MockWrite(
14815 "GET / HTTP/1.1\r\n"
14816 "Host: www.example.org\r\n"
14817 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5314818 };
14819
14820 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214821 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314822 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214823 MockRead("\r\n"),
14824 MockRead("hello world"),
14825 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5314826 };
14827
[email protected]8ddf8322012-02-23 18:08:0614828 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614829 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5314830
[email protected]bb88e1d32013-05-03 23:11:0714831 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5314832
Ryan Sleevib8d7ea02018-05-07 20:01:0114833 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0714834 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5314835
[email protected]49639fa2011-12-20 23:22:4114836 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5314837
danakj1fd259a02016-04-16 03:17:0914838 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614839 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5314840
tfarina42834112016-09-22 13:38:2014841 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5314842
robpercival214763f2016-07-01 23:27:0114843 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14844 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5314845
bnc691fda62016-08-12 00:43:1614846 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214847 ASSERT_TRUE(response);
14848 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5314849 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14850
14851 std::string response_data;
bnc691fda62016-08-12 00:43:1614852 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5314853 EXPECT_EQ("hello world", response_data);
14854
14855 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214856 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5314857}
[email protected]26ef6582010-06-24 02:30:4714858
bnc55ff9da2015-08-19 18:42:3514859// Simulate the SSL handshake completing with an NPN negotiation followed by an
14860// immediate server closing of the socket.
14861// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0114862TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4714863 HttpRequestInfo request;
14864 request.method = "GET";
bncce36dca22015-04-21 22:11:2314865 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014866 request.traffic_annotation =
14867 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4714868
[email protected]8ddf8322012-02-23 18:08:0614869 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614870 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0714871 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4714872
Ryan Hamilton0239aac2018-05-19 00:03:1314873 spdy::SpdySerializedFrame req(
14874 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114875 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4714876
14877 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614878 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4714879 };
14880
Ryan Sleevib8d7ea02018-05-07 20:01:0114881 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714882 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4714883
[email protected]49639fa2011-12-20 23:22:4114884 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4714885
danakj1fd259a02016-04-16 03:17:0914886 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614887 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4714888
tfarina42834112016-09-22 13:38:2014889 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114890 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14891 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4714892}
[email protected]65d34382010-07-01 18:12:2614893
[email protected]795cbf82013-07-22 09:37:2714894// A subclass of HttpAuthHandlerMock that records the request URL when
14895// it gets it. This is needed since the auth handler may get destroyed
14896// before we get a chance to query it.
14897class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
14898 public:
14899 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
14900
Chris Watkins7a41d3552017-12-01 02:13:2714901 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2714902
14903 protected:
dchengb03027d2014-10-21 12:00:2014904 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
14905 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0914906 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2014907 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2714908 *url_ = request->url;
14909 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0914910 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2714911 }
14912
14913 private:
14914 GURL* url_;
14915};
14916
[email protected]8e6441ca2010-08-19 05:56:3814917// Test that if we cancel the transaction as the connection is completing, that
14918// everything tears down correctly.
bncd16676a2016-07-20 16:23:0114919TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3814920 // Setup everything about the connection to complete synchronously, so that
14921 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
14922 // for is the callback from the HttpStreamRequest.
14923 // Then cancel the transaction.
14924 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3614925 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3814926 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614927 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
14928 MockRead(SYNCHRONOUS, "hello world"),
14929 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3814930 };
14931
[email protected]8e6441ca2010-08-19 05:56:3814932 HttpRequestInfo request;
14933 request.method = "GET";
bncce36dca22015-04-21 22:11:2314934 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014935 request.traffic_annotation =
14936 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3814937
danakj1fd259a02016-04-16 03:17:0914938 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814939 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914940 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2714941
Ryan Sleevib8d7ea02018-05-07 20:01:0114942 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3814943 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714944 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3814945
[email protected]49639fa2011-12-20 23:22:4114946 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3814947
vishal.b62985ca92015-04-17 08:45:5114948 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4114949 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114950 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3814951 trans.reset(); // Cancel the transaction here.
14952
fdoray92e35a72016-06-10 15:54:5514953 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3014954}
14955
[email protected]ecab6e052014-05-16 14:58:1214956// Test that if a transaction is cancelled after receiving the headers, the
14957// stream is drained properly and added back to the socket pool. The main
14958// purpose of this test is to make sure that an HttpStreamParser can be read
14959// from after the HttpNetworkTransaction and the objects it owns have been
14960// deleted.
14961// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0114962TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1214963 MockRead data_reads[] = {
14964 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
14965 MockRead(ASYNC, "Content-Length: 2\r\n"),
14966 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
14967 MockRead(ASYNC, "1"),
14968 // 2 async reads are necessary to trigger a ReadResponseBody call after the
14969 // HttpNetworkTransaction has been deleted.
14970 MockRead(ASYNC, "2"),
14971 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
14972 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114973 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1214974 session_deps_.socket_factory->AddSocketDataProvider(&data);
14975
danakj1fd259a02016-04-16 03:17:0914976 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1214977
14978 {
14979 HttpRequestInfo request;
14980 request.method = "GET";
bncce36dca22015-04-21 22:11:2314981 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014982 request.traffic_annotation =
14983 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1214984
dcheng48459ac22014-08-26 00:46:4114985 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1214986 TestCompletionCallback callback;
14987
tfarina42834112016-09-22 13:38:2014988 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114989 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1214990 callback.WaitForResult();
14991
14992 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214993 ASSERT_TRUE(response);
14994 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1214995 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14996
14997 // The transaction and HttpRequestInfo are deleted.
14998 }
14999
15000 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5515001 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1215002
15003 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4115004 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1215005}
15006
[email protected]76a505b2010-08-25 06:23:0015007// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0115008TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915009 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915010 ProxyResolutionService::CreateFixedFromPacResult(
15011 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115012 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715013 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915014 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015015
[email protected]76a505b2010-08-25 06:23:0015016 HttpRequestInfo request;
15017 request.method = "GET";
bncce36dca22015-04-21 22:11:2315018 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015019 request.traffic_annotation =
15020 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015021
15022 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2315023 MockWrite(
15024 "GET http://www.example.org/ HTTP/1.1\r\n"
15025 "Host: www.example.org\r\n"
15026 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015027 };
15028
15029 MockRead data_reads1[] = {
15030 MockRead("HTTP/1.1 200 OK\r\n"),
15031 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15032 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615033 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015034 };
15035
Ryan Sleevib8d7ea02018-05-07 20:01:0115036 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715037 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0015038
[email protected]49639fa2011-12-20 23:22:4115039 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015040
bnc691fda62016-08-12 00:43:1615041 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915042 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615043 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915044 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15045 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015046
bnc691fda62016-08-12 00:43:1615047 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115048 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015049
15050 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115051 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0015052
bnc691fda62016-08-12 00:43:1615053 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215054 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015055
15056 EXPECT_TRUE(response->headers->IsKeepAlive());
15057 EXPECT_EQ(200, response->headers->response_code());
15058 EXPECT_EQ(100, response->headers->GetContentLength());
15059 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715060 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15061 HostPortPair::FromString("myproxy:70")),
15062 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915063 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15064 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15065 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0015066 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2015067
15068 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615069 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015070 TestLoadTimingNotReusedWithPac(load_timing_info,
15071 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0015072}
15073
15074// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0115075TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915076 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915077 ProxyResolutionService::CreateFixedFromPacResult(
15078 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115079 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715080 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915081 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015082
[email protected]76a505b2010-08-25 06:23:0015083 HttpRequestInfo request;
15084 request.method = "GET";
bncce36dca22015-04-21 22:11:2315085 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015086 request.traffic_annotation =
15087 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015088
15089 // Since we have proxy, should try to establish tunnel.
15090 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715091 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15092 "Host: www.example.org:443\r\n"
15093 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015094
rsleevidb16bb02015-11-12 23:47:1715095 MockWrite("GET / HTTP/1.1\r\n"
15096 "Host: www.example.org\r\n"
15097 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015098 };
15099
15100 MockRead data_reads1[] = {
15101 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15102
15103 MockRead("HTTP/1.1 200 OK\r\n"),
15104 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15105 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615106 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015107 };
15108
Ryan Sleevib8d7ea02018-05-07 20:01:0115109 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715110 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615111 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715112 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015113
[email protected]49639fa2011-12-20 23:22:4115114 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015115
bnc691fda62016-08-12 00:43:1615116 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915117 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615118 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915119 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15120 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015121
bnc691fda62016-08-12 00:43:1615122 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115123 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015124
15125 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115126 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415127 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015128 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015129 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15130 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015131 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015132 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015133 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15134 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015135
bnc691fda62016-08-12 00:43:1615136 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215137 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015138
15139 EXPECT_TRUE(response->headers->IsKeepAlive());
15140 EXPECT_EQ(200, response->headers->response_code());
15141 EXPECT_EQ(100, response->headers->GetContentLength());
15142 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15143 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715144 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15145 HostPortPair::FromString("myproxy:70")),
15146 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915147 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15148 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15149 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2015150
15151 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615152 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015153 TestLoadTimingNotReusedWithPac(load_timing_info,
15154 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0015155}
15156
rsleevidb16bb02015-11-12 23:47:1715157// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
15158// literal host.
bncd16676a2016-07-20 16:23:0115159TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5915160 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915161 ProxyResolutionService::CreateFixedFromPacResult(
15162 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715163 BoundTestNetLog log;
15164 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915165 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1715166
15167 HttpRequestInfo request;
15168 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1515169 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e2018-02-07 07:41:1015170 request.traffic_annotation =
15171 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715172
15173 // Since we have proxy, should try to establish tunnel.
15174 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1515175 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
15176 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1715177 "Proxy-Connection: keep-alive\r\n\r\n"),
15178
15179 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1515180 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1715181 "Connection: keep-alive\r\n\r\n"),
15182 };
15183
15184 MockRead data_reads1[] = {
15185 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15186
15187 MockRead("HTTP/1.1 200 OK\r\n"),
15188 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15189 MockRead("Content-Length: 100\r\n\r\n"),
15190 MockRead(SYNCHRONOUS, OK),
15191 };
15192
Ryan Sleevib8d7ea02018-05-07 20:01:0115193 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1715194 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15195 SSLSocketDataProvider ssl(ASYNC, OK);
15196 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15197
15198 TestCompletionCallback callback1;
15199
bnc691fda62016-08-12 00:43:1615200 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1715201
bnc691fda62016-08-12 00:43:1615202 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115203 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1715204
15205 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115206 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415207 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1715208 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015209 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15210 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715211 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015212 entries, pos,
15213 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15214 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715215
bnc691fda62016-08-12 00:43:1615216 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215217 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1715218
15219 EXPECT_TRUE(response->headers->IsKeepAlive());
15220 EXPECT_EQ(200, response->headers->response_code());
15221 EXPECT_EQ(100, response->headers->GetContentLength());
15222 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15223 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715224 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15225 HostPortPair::FromString("myproxy:70")),
15226 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1715227
15228 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615229 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1715230 TestLoadTimingNotReusedWithPac(load_timing_info,
15231 CONNECT_TIMING_HAS_SSL_TIMES);
15232}
15233
[email protected]76a505b2010-08-25 06:23:0015234// Test a basic HTTPS GET request through a proxy, but the server hangs up
15235// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0115236TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4915237 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15238 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115239 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715240 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915241 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015242
[email protected]76a505b2010-08-25 06:23:0015243 HttpRequestInfo request;
15244 request.method = "GET";
bncce36dca22015-04-21 22:11:2315245 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015246 request.traffic_annotation =
15247 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015248
15249 // Since we have proxy, should try to establish tunnel.
15250 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715251 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15252 "Host: www.example.org:443\r\n"
15253 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015254
rsleevidb16bb02015-11-12 23:47:1715255 MockWrite("GET / HTTP/1.1\r\n"
15256 "Host: www.example.org\r\n"
15257 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015258 };
15259
15260 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0015261 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615262 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0015263 };
15264
Ryan Sleevib8d7ea02018-05-07 20:01:0115265 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715266 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615267 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715268 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015269
[email protected]49639fa2011-12-20 23:22:4115270 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015271
bnc691fda62016-08-12 00:43:1615272 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5015273
bnc691fda62016-08-12 00:43:1615274 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115275 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015276
15277 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115278 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5415279 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015280 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015281 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15282 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015283 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015284 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015285 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15286 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015287}
15288
[email protected]749eefa82010-09-13 22:14:0315289// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0115290TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1315291 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4915292 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115293 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0315294
Raul Tambre94493c652019-03-11 17:18:3515295 spdy::SpdySerializedFrame resp(
15296 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315297 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0315298 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115299 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0315300 };
15301
Ryan Sleevib8d7ea02018-05-07 20:01:0115302 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715303 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0315304
[email protected]8ddf8322012-02-23 18:08:0615305 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615306 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715307 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0315308
danakj1fd259a02016-04-16 03:17:0915309 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315310
15311 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315312 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015313 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115314 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3415315 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
15316 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2715317 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5215318 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0315319
15320 HttpRequestInfo request;
15321 request.method = "GET";
bncce36dca22015-04-21 22:11:2315322 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015323 request.traffic_annotation =
15324 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0315325
bnc691fda62016-08-12 00:43:1615326 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0315327
[email protected]41d64e82013-07-03 22:44:2615328 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015329 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15331 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0315332}
15333
[email protected]73b8dd222010-11-11 19:55:2415334// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1615335// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0215336void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0715337 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2915338 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715339 request_info.url = GURL("https://www.example.com/");
15340 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915341 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015342 request_info.traffic_annotation =
15343 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715344
[email protected]8ddf8322012-02-23 18:08:0615345 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2915346 MockWrite data_writes[] = {
15347 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2415348 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115349 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715350 session_deps_.socket_factory->AddSocketDataProvider(&data);
15351 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2415352
danakj1fd259a02016-04-16 03:17:0915353 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615354 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2415355
[email protected]49639fa2011-12-20 23:22:4115356 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015357 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2915358 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2415359 rv = callback.WaitForResult();
15360 ASSERT_EQ(error, rv);
15361}
15362
bncd16676a2016-07-20 16:23:0115363TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2415364 // Just check a grab bag of cert errors.
15365 static const int kErrors[] = {
15366 ERR_CERT_COMMON_NAME_INVALID,
15367 ERR_CERT_AUTHORITY_INVALID,
15368 ERR_CERT_DATE_INVALID,
15369 };
Avi Drissman4365a4782018-12-28 19:26:2415370 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0615371 CheckErrorIsPassedBack(kErrors[i], ASYNC);
15372 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2415373 }
15374}
15375
[email protected]bd0b6772011-01-11 19:59:3015376// Ensure that a client certificate is removed from the SSL client auth
15377// cache when:
15378// 1) No proxy is involved.
15379// 2) TLS False Start is disabled.
15380// 3) The initial TLS handshake requests a client certificate.
15381// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115382TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915383 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715384 request_info.url = GURL("https://www.example.com/");
15385 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915386 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015387 request_info.traffic_annotation =
15388 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715389
David Benjamin1c4b6d012019-07-08 17:12:5715390 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115391 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015392
15393 // [ssl_]data1 contains the data for the first SSL handshake. When a
15394 // CertificateRequest is received for the first time, the handshake will
15395 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2915396 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015397 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715398 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115399 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715400 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015401
15402 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
15403 // False Start is not being used, the result of the SSL handshake will be
15404 // returned as part of the SSLClientSocket::Connect() call. This test
15405 // matches the result of a server sending a handshake_failure alert,
15406 // rather than a Finished message, because it requires a client
15407 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2915408 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3015409 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715410 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0115411 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0715412 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015413
15414 // [ssl_]data3 contains the data for the third SSL handshake. When a
15415 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1315416 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
15417 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3015418 // of the HttpNetworkTransaction. Because this test failure is due to
15419 // requiring a client certificate, this fallback handshake should also
15420 // fail.
ttuttle859dc7a2015-04-23 19:42:2915421 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1315422 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3015423 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715424 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115425 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0715426 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015427
[email protected]80c75f682012-05-26 16:22:1715428 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
15429 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4215430 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
15431 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1715432 // of the HttpNetworkTransaction. Because this test failure is due to
15433 // requiring a client certificate, this fallback handshake should also
15434 // fail.
ttuttle859dc7a2015-04-23 19:42:2915435 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1715436 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715437 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115438 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0715439 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715440
danakj1fd259a02016-04-16 03:17:0915441 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615442 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015443
[email protected]bd0b6772011-01-11 19:59:3015444 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4115445 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015446 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115447 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015448
15449 // Complete the SSL handshake, which should abort due to requiring a
15450 // client certificate.
15451 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115452 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015453
15454 // Indicate that no certificate should be supplied. From the perspective
15455 // of SSLClientCertCache, NULL is just as meaningful as a real
15456 // certificate, so this is the same as supply a
15457 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515458 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115459 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015460
15461 // Ensure the certificate was added to the client auth cache before
15462 // allowing the connection to continue restarting.
15463 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415464 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115465 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415466 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215467 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015468
15469 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715470 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15471 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015472 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115473 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015474
15475 // Ensure that the client certificate is removed from the cache on a
15476 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4115477 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415478 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015479}
15480
15481// Ensure that a client certificate is removed from the SSL client auth
15482// cache when:
15483// 1) No proxy is involved.
15484// 2) TLS False Start is enabled.
15485// 3) The initial TLS handshake requests a client certificate.
15486// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115487TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915488 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715489 request_info.url = GURL("https://www.example.com/");
15490 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915491 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015492 request_info.traffic_annotation =
15493 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715494
David Benjamin1c4b6d012019-07-08 17:12:5715495 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115496 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015497
15498 // When TLS False Start is used, SSLClientSocket::Connect() calls will
15499 // return successfully after reading up to the peer's Certificate message.
15500 // This is to allow the caller to call SSLClientSocket::Write(), which can
15501 // enqueue application data to be sent in the same packet as the
15502 // ChangeCipherSpec and Finished messages.
15503 // The actual handshake will be finished when SSLClientSocket::Read() is
15504 // called, which expects to process the peer's ChangeCipherSpec and
15505 // Finished messages. If there was an error negotiating with the peer,
15506 // such as due to the peer requiring a client certificate when none was
15507 // supplied, the alert sent by the peer won't be processed until Read() is
15508 // called.
15509
15510 // Like the non-False Start case, when a client certificate is requested by
15511 // the peer, the handshake is aborted during the Connect() call.
15512 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2915513 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015514 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715515 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115516 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715517 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015518
15519 // When a client certificate is supplied, Connect() will not be aborted
15520 // when the peer requests the certificate. Instead, the handshake will
15521 // artificially succeed, allowing the caller to write the HTTP request to
15522 // the socket. The handshake messages are not processed until Read() is
15523 // called, which then detects that the handshake was aborted, due to the
15524 // peer sending a handshake_failure because it requires a client
15525 // certificate.
ttuttle859dc7a2015-04-23 19:42:2915526 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015527 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715528 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2915529 MockRead data2_reads[] = {
15530 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3015531 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115532 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715533 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015534
15535 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1715536 // the data for the SSL handshake once the TLSv1.1 connection falls back to
15537 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915538 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015539 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715540 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115541 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715542 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015543
[email protected]80c75f682012-05-26 16:22:1715544 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
15545 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915546 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1715547 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715548 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115549 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715550 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715551
[email protected]7799de12013-05-30 05:52:5115552 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2915553 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5115554 ssl_data5.cert_request_info = cert_request.get();
15555 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0115556 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5115557 session_deps_.socket_factory->AddSocketDataProvider(&data5);
15558
danakj1fd259a02016-04-16 03:17:0915559 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615560 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015561
[email protected]bd0b6772011-01-11 19:59:3015562 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4115563 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015564 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115565 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015566
15567 // Complete the SSL handshake, which should abort due to requiring a
15568 // client certificate.
15569 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115570 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015571
15572 // Indicate that no certificate should be supplied. From the perspective
15573 // of SSLClientCertCache, NULL is just as meaningful as a real
15574 // certificate, so this is the same as supply a
15575 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515576 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115577 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015578
15579 // Ensure the certificate was added to the client auth cache before
15580 // allowing the connection to continue restarting.
15581 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415582 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115583 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415584 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215585 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015586
[email protected]bd0b6772011-01-11 19:59:3015587 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715588 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15589 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015590 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115591 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015592
15593 // Ensure that the client certificate is removed from the cache on a
15594 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4115595 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415596 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015597}
15598
[email protected]8c405132011-01-11 22:03:1815599// Ensure that a client certificate is removed from the SSL client auth
15600// cache when:
15601// 1) An HTTPS proxy is involved.
15602// 3) The HTTPS proxy requests a client certificate.
15603// 4) The client supplies an invalid/unacceptable certificate for the
15604// proxy.
bncd16676a2016-07-20 16:23:0115605TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4915606 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15607 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115608 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715609 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1815610
David Benjamin3b94b0f2019-04-25 23:07:5215611 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115612 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1815613
David Benjamin3b94b0f2019-04-25 23:07:5215614 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
15615 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2915616 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1815617 requests[0].url = GURL("https://www.example.com/");
15618 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915619 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015620 requests[0].traffic_annotation =
15621 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815622
David Benjamin3b94b0f2019-04-25 23:07:5215623 // HTTPS requests are tunneled.
15624 MockWrite https_writes[] = {
15625 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
15626 "Host: www.example.com:443\r\n"
15627 "Proxy-Connection: keep-alive\r\n\r\n"),
15628 };
15629
[email protected]8c405132011-01-11 22:03:1815630 requests[1].url = GURL("http://www.example.com/");
15631 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915632 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015633 requests[1].traffic_annotation =
15634 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815635
David Benjamin3b94b0f2019-04-25 23:07:5215636 // HTTP requests are not.
15637 MockWrite http_writes[] = {
15638 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
15639 "Host: www.example.com\r\n"
15640 "Proxy-Connection: keep-alive\r\n\r\n"),
15641 };
[email protected]8c405132011-01-11 22:03:1815642
David Benjamin3b94b0f2019-04-25 23:07:5215643 // When the server rejects the client certificate, it will close the
15644 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
15645 // TLS 1.2 with False Start), the error is returned out of the first Read().
15646 for (bool reject_in_connect : {true, false}) {
15647 SCOPED_TRACE(reject_in_connect);
15648 // Client certificate errors are typically signaled with
15649 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
15650 // protocol error.
15651 for (Error reject_error :
15652 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
15653 SCOPED_TRACE(reject_error);
15654 // Tunneled and non-tunneled requests are handled differently. Test both.
15655 for (const HttpRequestInfo& request : requests) {
15656 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1815657
David Benjamin3b94b0f2019-04-25 23:07:5215658 session_deps_.socket_factory =
15659 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1815660
David Benjamin3b94b0f2019-04-25 23:07:5215661 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
15662 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
15663 // for proxies. Rather than represending the endpoint
15664 // (www.example.com:443), they represent failures with the HTTPS proxy
15665 // (proxy:70).
15666 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
15667 ssl_data1.cert_request_info = cert_request.get();
15668 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15669 StaticSocketDataProvider data1;
15670 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1815671
David Benjamin3b94b0f2019-04-25 23:07:5215672 base::Optional<SSLSocketDataProvider> ssl_data2;
15673 base::Optional<StaticSocketDataProvider> data2;
15674 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
15675 if (reject_in_connect) {
15676 ssl_data2.emplace(ASYNC, reject_error);
15677 // There are no reads or writes.
15678 data2.emplace();
15679 } else {
15680 ssl_data2.emplace(ASYNC, OK);
15681 // We will get one Write() in before observing the error in Read().
15682 if (request.url.SchemeIsCryptographic()) {
15683 data2.emplace(error_in_read, https_writes);
15684 } else {
15685 data2.emplace(error_in_read, http_writes);
15686 }
15687 }
15688 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1815689
David Benjamin3b94b0f2019-04-25 23:07:5215690 session_deps_.socket_factory->AddSSLSocketDataProvider(
15691 &ssl_data2.value());
15692 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1815693
David Benjamin3b94b0f2019-04-25 23:07:5215694 std::unique_ptr<HttpNetworkSession> session =
15695 CreateSession(&session_deps_);
15696 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15697
15698 // Begin the SSL handshake with the proxy.
15699 TestCompletionCallback callback;
15700 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15701 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15702
15703 // Complete the SSL handshake, which should abort due to requiring a
15704 // client certificate.
15705 rv = callback.WaitForResult();
15706 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15707
15708 // Indicate that no certificate should be supplied. From the
15709 // perspective of SSLClientCertCache, NULL is just as meaningful as a
15710 // real certificate, so this is the same as supply a
15711 // legitimate-but-unacceptable certificate.
15712 rv =
15713 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
15714 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15715
15716 // Ensure the certificate was added to the client auth cache before
15717 // allowing the connection to continue restarting.
15718 scoped_refptr<X509Certificate> client_cert;
15719 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115720 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215721 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15722 ASSERT_FALSE(client_cert);
15723 // Ensure the certificate was NOT cached for the endpoint. This only
15724 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4115725 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215726 HostPortPair("www.example.com", 443), &client_cert,
15727 &client_private_key));
15728
15729 // Restart the handshake. This will consume ssl_data2. The result code
15730 // is checked against what ssl_data2 should return.
15731 rv = callback.WaitForResult();
15732 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
15733 IsError(reject_error)));
15734
15735 // Now that the new handshake has failed, ensure that the client
15736 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4115737 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215738 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4115739 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215740 HostPortPair("www.example.com", 443), &client_cert,
15741 &client_private_key));
15742 }
15743 }
[email protected]8c405132011-01-11 22:03:1815744 }
15745}
15746
David Benjamin1a0566082019-04-30 07:36:1915747// Test that HttpNetworkTransaction correctly handles (mocked) certificate
15748// requests during a TLS renegotiation.
15749TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
15750 HttpRequestInfo request_info;
15751 request_info.url = GURL("https://www.example.com/");
15752 request_info.method = "GET";
15753 request_info.load_flags = LOAD_NORMAL;
15754 request_info.traffic_annotation =
15755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15756
15757 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
15758 cert_request->host_and_port = HostPortPair("www.example.com", 443);
15759
15760 std::unique_ptr<FakeClientCertIdentity> identity =
15761 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
15762 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
15763 ASSERT_TRUE(identity);
15764
15765 // The first connection's handshake succeeds, but we get
15766 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
15767 SSLSocketDataProvider ssl_data1(ASYNC, OK);
15768 ssl_data1.cert_request_info = cert_request.get();
15769 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15770 MockWrite data1_writes[] = {
15771 MockWrite("GET / HTTP/1.1\r\n"
15772 "Host: www.example.com\r\n"
15773 "Connection: keep-alive\r\n\r\n"),
15774 };
15775 MockRead data1_reads[] = {
15776 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
15777 };
15778 StaticSocketDataProvider data1(data1_reads, data1_writes);
15779 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15780
15781 // After supplying with certificate, we restart the request from the top,
15782 // which succeeds this time.
15783 SSLSocketDataProvider ssl_data2(ASYNC, OK);
15784 ssl_data2.expected_send_client_cert = true;
15785 ssl_data2.expected_client_cert = identity->certificate();
15786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
15787 MockWrite data2_writes[] = {
15788 MockWrite("GET / HTTP/1.1\r\n"
15789 "Host: www.example.com\r\n"
15790 "Connection: keep-alive\r\n\r\n"),
15791 };
15792 MockRead data2_reads[] = {
15793 MockRead("HTTP/1.1 200 OK\r\n"
15794 "Content-Length: 0\r\n\r\n"),
15795 };
15796 StaticSocketDataProvider data2(data2_reads, data2_writes);
15797 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15798
15799 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
15800 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15801
15802 TestCompletionCallback callback;
15803 int rv = callback.GetResult(
15804 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
15805 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15806
15807 rv = trans.RestartWithCertificate(identity->certificate(),
15808 identity->ssl_private_key(),
15809 callback.callback());
15810 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15811
15812 // Ensure the certificate was added to the client auth cache
15813 // allowing the connection to continue restarting.
15814 scoped_refptr<X509Certificate> client_cert;
15815 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115816 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1915817 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15818 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15819
15820 // Complete the handshake. The request now succeeds.
15821 rv = callback.WaitForResult();
15822 ASSERT_THAT(rv, IsError(OK));
15823 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
15824
15825 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4115826 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1915827 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15828 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15829}
15830
bncd16676a2016-07-20 16:23:0115831TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4615832 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915833 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915834 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615835
bnc032658ba2016-09-26 18:17:1515836 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615837
Ryan Hamilton0239aac2018-05-19 00:03:1315838 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915839 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815840 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315841 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715842 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615843 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115844 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615845 };
Ryan Hamilton0239aac2018-05-19 00:03:1315846 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515847 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315848 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115849 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315850 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515851 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315852 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115853 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615854 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115855 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15856 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315857 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615858 };
15859
eroman36d84e54432016-03-17 03:23:0215860 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215861 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115862 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715863 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615864
[email protected]aa22b242011-11-16 18:58:2915865 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615866 HttpRequestInfo request1;
15867 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315868 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615869 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015870 request1.traffic_annotation =
15871 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015872 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615873
tfarina42834112016-09-22 13:38:2015874 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115875 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15876 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615877
15878 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215879 ASSERT_TRUE(response);
15880 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215881 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615882
15883 std::string response_data;
robpercival214763f2016-07-01 23:27:0115884 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615885 EXPECT_EQ("hello!", response_data);
15886
bnca4d611d2016-09-22 19:55:3715887 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315888 rv = session_deps_.host_resolver->LoadIntoCache(
15889 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0115890 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4615891
15892 HttpRequestInfo request2;
15893 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715894 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4615895 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015896 request2.traffic_annotation =
15897 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015898 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615899
tfarina42834112016-09-22 13:38:2015900 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115901 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15902 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615903
15904 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215905 ASSERT_TRUE(response);
15906 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215907 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615908 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215909 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115910 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615911 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4615912}
15913
bncd16676a2016-07-20 16:23:0115914TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0215915 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915916 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915917 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0215918
bnc032658ba2016-09-26 18:17:1515919 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0215920
Ryan Hamilton0239aac2018-05-19 00:03:1315921 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915922 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815923 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315924 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715925 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0215926 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115927 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0215928 };
Ryan Hamilton0239aac2018-05-19 00:03:1315929 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515930 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315931 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115932 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315933 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515934 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315935 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115936 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0215937 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115938 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15939 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315940 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0215941 };
15942
eroman36d84e54432016-03-17 03:23:0215943 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215944 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115945 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715946 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0215947
15948 TestCompletionCallback callback;
15949 HttpRequestInfo request1;
15950 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315951 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0215952 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015953 request1.traffic_annotation =
15954 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015955 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215956
tfarina42834112016-09-22 13:38:2015957 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115958 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15959 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215960
15961 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215962 ASSERT_TRUE(response);
15963 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215964 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215965
15966 std::string response_data;
robpercival214763f2016-07-01 23:27:0115967 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215968 EXPECT_EQ("hello!", response_data);
15969
15970 HttpRequestInfo request2;
15971 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715972 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0215973 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015974 request2.traffic_annotation =
15975 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015976 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215977
tfarina42834112016-09-22 13:38:2015978 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15980 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215981
15982 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215983 ASSERT_TRUE(response);
15984 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215985 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215986 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215987 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115988 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215989 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0215990}
15991
bnc8016c1f2017-03-31 02:11:2915992// Regression test for https://crbug.com/546991.
15993// The server might not be able to serve an IP pooled request, and might send a
15994// 421 Misdirected Request response status to indicate this.
15995// HttpNetworkTransaction should reset the request and retry without IP pooling.
15996TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
15997 // Two hosts resolve to the same IP address.
15998 const std::string ip_addr = "1.2.3.4";
15999 IPAddress ip;
16000 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16001 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16002
Jeremy Roman0579ed62017-08-29 15:56:1916003 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2916004 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16005 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16006
16007 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16008
16009 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316010 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2916011 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16012 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316013 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2916014 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316015 spdy::SpdySerializedFrame rst(
16016 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2916017 MockWrite writes1[] = {
16018 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16019 CreateMockWrite(rst, 6),
16020 };
16021
16022 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316023 spdy::SpdySerializedFrame resp1(
16024 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16025 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16026 spdy::SpdyHeaderBlock response_headers;
16027 response_headers[spdy::kHttp2StatusHeader] = "421";
16028 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2916029 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
16030 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16031 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16032
16033 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116034 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2916035 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16036
16037 AddSSLSocketData();
16038
16039 // Retry the second request on a second connection.
16040 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316041 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2916042 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16043 MockWrite writes2[] = {
16044 CreateMockWrite(req3, 0),
16045 };
16046
Ryan Hamilton0239aac2018-05-19 00:03:1316047 spdy::SpdySerializedFrame resp3(
16048 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
16049 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2916050 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16051 MockRead(ASYNC, 0, 3)};
16052
16053 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116054 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2916055 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16056
16057 AddSSLSocketData();
16058
16059 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316060 int rv = session_deps_.host_resolver->LoadIntoCache(
16061 HostPortPair("mail.example.com", 443), base::nullopt);
bnc8016c1f2017-03-31 02:11:2916062 EXPECT_THAT(rv, IsOk());
16063
16064 HttpRequestInfo request1;
16065 request1.method = "GET";
16066 request1.url = GURL("https://www.example.org/");
16067 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016068 request1.traffic_annotation =
16069 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916070 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16071
Eric Orthf4db66a2019-02-19 21:35:3316072 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2916073 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16074 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16075 rv = callback.WaitForResult();
16076 EXPECT_THAT(rv, IsOk());
16077
16078 const HttpResponseInfo* response = trans1.GetResponseInfo();
16079 ASSERT_TRUE(response);
16080 ASSERT_TRUE(response->headers);
16081 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16082 EXPECT_TRUE(response->was_fetched_via_spdy);
16083 EXPECT_TRUE(response->was_alpn_negotiated);
16084 std::string response_data;
16085 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16086 EXPECT_EQ("hello!", response_data);
16087
16088 HttpRequestInfo request2;
16089 request2.method = "GET";
16090 request2.url = GURL("https://mail.example.org/");
16091 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016092 request2.traffic_annotation =
16093 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916094 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16095
16096 BoundTestNetLog log;
16097 rv = trans2.Start(&request2, callback.callback(), log.bound());
16098 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16099 rv = callback.WaitForResult();
16100 EXPECT_THAT(rv, IsOk());
16101
16102 response = trans2.GetResponseInfo();
16103 ASSERT_TRUE(response);
16104 ASSERT_TRUE(response->headers);
16105 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16106 EXPECT_TRUE(response->was_fetched_via_spdy);
16107 EXPECT_TRUE(response->was_alpn_negotiated);
16108 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16109 EXPECT_EQ("hello!", response_data);
16110
Eric Roman79cc7552019-07-19 02:17:5416111 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5916112 ExpectLogContainsSomewhere(
16113 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2916114 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5916115}
16116
16117// Test that HTTP 421 responses are properly returned to the caller if received
16118// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
16119// portions of the response.
16120TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
16121 // Two hosts resolve to the same IP address.
16122 const std::string ip_addr = "1.2.3.4";
16123 IPAddress ip;
16124 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16125 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16126
Jeremy Roman0579ed62017-08-29 15:56:1916127 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5916128 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16129 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16130
16131 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16132
16133 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316134 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5916135 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16136 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316137 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5916138 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316139 spdy::SpdySerializedFrame rst(
16140 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5916141 MockWrite writes1[] = {
16142 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16143 CreateMockWrite(rst, 6),
16144 };
16145
16146 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316147 spdy::SpdySerializedFrame resp1(
16148 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16149 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16150 spdy::SpdyHeaderBlock response_headers;
16151 response_headers[spdy::kHttp2StatusHeader] = "421";
16152 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5916153 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
16154 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16155 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16156
16157 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116158 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5916159 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16160
16161 AddSSLSocketData();
16162
16163 // Retry the second request on a second connection. It returns 421 Misdirected
16164 // Retry again.
16165 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316166 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5916167 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16168 MockWrite writes2[] = {
16169 CreateMockWrite(req3, 0),
16170 };
16171
Ryan Hamilton0239aac2018-05-19 00:03:1316172 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5916173 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1316174 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5916175 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16176 MockRead(ASYNC, 0, 3)};
16177
16178 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116179 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5916180 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16181
16182 AddSSLSocketData();
16183
16184 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316185 int rv = session_deps_.host_resolver->LoadIntoCache(
16186 HostPortPair("mail.example.com", 443), base::nullopt);
davidbence688ae2017-05-04 15:12:5916187 EXPECT_THAT(rv, IsOk());
16188
16189 HttpRequestInfo request1;
16190 request1.method = "GET";
16191 request1.url = GURL("https://www.example.org/");
16192 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016193 request1.traffic_annotation =
16194 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916195 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16196
Eric Orthf4db66a2019-02-19 21:35:3316197 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5916198 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16199 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16200 rv = callback.WaitForResult();
16201 EXPECT_THAT(rv, IsOk());
16202
16203 const HttpResponseInfo* response = trans1.GetResponseInfo();
16204 ASSERT_TRUE(response);
16205 ASSERT_TRUE(response->headers);
16206 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16207 EXPECT_TRUE(response->was_fetched_via_spdy);
16208 EXPECT_TRUE(response->was_alpn_negotiated);
16209 std::string response_data;
16210 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16211 EXPECT_EQ("hello!", response_data);
16212
16213 HttpRequestInfo request2;
16214 request2.method = "GET";
16215 request2.url = GURL("https://mail.example.org/");
16216 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016217 request2.traffic_annotation =
16218 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916219 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16220
16221 BoundTestNetLog log;
16222 rv = trans2.Start(&request2, callback.callback(), log.bound());
16223 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16224 rv = callback.WaitForResult();
16225 EXPECT_THAT(rv, IsOk());
16226
16227 // After a retry, the 421 Misdirected Request is reported back up to the
16228 // caller.
16229 response = trans2.GetResponseInfo();
16230 ASSERT_TRUE(response);
16231 ASSERT_TRUE(response->headers);
16232 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
16233 EXPECT_TRUE(response->was_fetched_via_spdy);
16234 EXPECT_TRUE(response->was_alpn_negotiated);
16235 EXPECT_TRUE(response->ssl_info.cert);
16236 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16237 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2916238}
16239
bncd16676a2016-07-20 16:23:0116240TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1316241 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3416242 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
16243 session_deps_.host_resolver =
16244 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0916245 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616246
bnc032658ba2016-09-26 18:17:1516247 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616248
Ryan Hamilton0239aac2018-05-19 00:03:1316249 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916250 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816251 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316252 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716253 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616254 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116255 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616256 };
Ryan Hamilton0239aac2018-05-19 00:03:1316257 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516258 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316259 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116260 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316261 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516262 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316263 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116264 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616265 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116266 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16267 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316268 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616269 };
16270
eroman36d84e54432016-03-17 03:23:0216271 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216272 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116273 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716274 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616275
[email protected]aa22b242011-11-16 18:58:2916276 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616277 HttpRequestInfo request1;
16278 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316279 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616280 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016281 request1.traffic_annotation =
16282 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016283 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616284
tfarina42834112016-09-22 13:38:2016285 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116286 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16287 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616288
16289 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216290 ASSERT_TRUE(response);
16291 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216292 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616293
16294 std::string response_data;
robpercival214763f2016-07-01 23:27:0116295 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616296 EXPECT_EQ("hello!", response_data);
16297
16298 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316299 rv = session_deps_.host_resolver->LoadIntoCache(
16300 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116301 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616302
16303 HttpRequestInfo request2;
16304 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716305 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616306 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016307 request2.traffic_annotation =
16308 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016309 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616310
tfarina42834112016-09-22 13:38:2016311 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116312 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16313 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616314
16315 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216316 ASSERT_TRUE(response);
16317 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216318 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616319 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216320 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116321 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616322 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616323}
16324
bncd16676a2016-07-20 16:23:0116325TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2316326 const std::string https_url = "https://www.example.org:8080/";
16327 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416328
16329 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1316330 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916331 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0416332
16333 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116334 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0416335 };
16336
Raul Tambre94493c652019-03-11 17:18:3516337 spdy::SpdySerializedFrame resp1(
16338 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316339 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116340 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5916341 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0416342
Ryan Sleevib8d7ea02018-05-07 20:01:0116343 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416344 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716345 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416346
16347 // HTTP GET for the HTTP URL
16348 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1316349 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3416350 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2316351 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3416352 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0416353 };
16354
16355 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1316356 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
16357 MockRead(ASYNC, 2, "hello"),
16358 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0416359 };
16360
Ryan Sleevib8d7ea02018-05-07 20:01:0116361 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0416362
[email protected]8450d722012-07-02 19:14:0416363 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616364 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716365 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16366 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16367 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0416368
danakj1fd259a02016-04-16 03:17:0916369 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0416370
16371 // Start the first transaction to set up the SpdySession
16372 HttpRequestInfo request1;
16373 request1.method = "GET";
16374 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416375 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016376 request1.traffic_annotation =
16377 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016378 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416379 TestCompletionCallback callback1;
16380 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016381 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516382 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416383
robpercival214763f2016-07-01 23:27:0116384 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416385 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16386
16387 // Now, start the HTTP request
16388 HttpRequestInfo request2;
16389 request2.method = "GET";
16390 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416391 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016392 request2.traffic_annotation =
16393 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016394 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416395 TestCompletionCallback callback2;
16396 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016397 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516398 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416399
robpercival214763f2016-07-01 23:27:0116400 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416401 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16402}
16403
bnc5452e2a2015-05-08 16:27:4216404// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
16405// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0116406TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2516407 url::SchemeHostPort server("https", "www.example.org", 443);
16408 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4216409
bnc8bef8da22016-05-30 01:28:2516410 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4216411 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616412 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16414
16415 // No data should be read from the alternative, because HTTP/1.1 is
16416 // negotiated.
16417 StaticSocketDataProvider data;
16418 session_deps_.socket_factory->AddSocketDataProvider(&data);
16419
16420 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4616421 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4216422 // mocked. This way the request relies on the alternate Job.
16423 StaticSocketDataProvider data_refused;
16424 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16425 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16426
zhongyi3d4a55e72016-04-22 20:36:4616427 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916428 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016429 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216430 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116431 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216432 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116433 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716434 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216435
bnc5452e2a2015-05-08 16:27:4216436 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4616437 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216438 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2516439 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e2018-02-07 07:41:1016440 request.traffic_annotation =
16441 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216442 TestCompletionCallback callback;
16443
16444 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5216445 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2016446 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5216447 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4216448}
16449
bnc40448a532015-05-11 19:13:1416450// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4616451// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1416452// succeeds, the request should succeed, even if the latter fails because
16453// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0116454TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2516455 url::SchemeHostPort server("https", "www.example.org", 443);
16456 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1416457
16458 // Negotiate HTTP/1.1 with alternative.
16459 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616460 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416461 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
16462
16463 // No data should be read from the alternative, because HTTP/1.1 is
16464 // negotiated.
16465 StaticSocketDataProvider data;
16466 session_deps_.socket_factory->AddSocketDataProvider(&data);
16467
zhongyi3d4a55e72016-04-22 20:36:4616468 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1416469 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616470 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416471 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
16472
16473 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2516474 MockWrite("GET / HTTP/1.1\r\n"
16475 "Host: www.example.org\r\n"
16476 "Connection: keep-alive\r\n\r\n"),
16477 MockWrite("GET /second HTTP/1.1\r\n"
16478 "Host: www.example.org\r\n"
16479 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1416480 };
16481
16482 MockRead http_reads[] = {
16483 MockRead("HTTP/1.1 200 OK\r\n"),
16484 MockRead("Content-Type: text/html\r\n"),
16485 MockRead("Content-Length: 6\r\n\r\n"),
16486 MockRead("foobar"),
16487 MockRead("HTTP/1.1 200 OK\r\n"),
16488 MockRead("Content-Type: text/html\r\n"),
16489 MockRead("Content-Length: 7\r\n\r\n"),
16490 MockRead("another"),
16491 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116492 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1416493 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16494
zhongyi3d4a55e72016-04-22 20:36:4616495 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916496 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016497 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1416498 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116499 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216500 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116501 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716502 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1416503
16504 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16505 HttpRequestInfo request1;
16506 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2516507 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1416508 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016509 request1.traffic_annotation =
16510 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416511 TestCompletionCallback callback1;
16512
tfarina42834112016-09-22 13:38:2016513 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416514 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116515 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416516
16517 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216518 ASSERT_TRUE(response1);
16519 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1416520 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
16521
16522 std::string response_data1;
robpercival214763f2016-07-01 23:27:0116523 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1416524 EXPECT_EQ("foobar", response_data1);
16525
16526 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
16527 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0516528 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
16529 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1416530
zhongyi3d4a55e72016-04-22 20:36:4616531 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1416532 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4616533 // to server.
bnc40448a532015-05-11 19:13:1416534 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16535 HttpRequestInfo request2;
16536 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2516537 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1416538 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016539 request2.traffic_annotation =
16540 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416541 TestCompletionCallback callback2;
16542
tfarina42834112016-09-22 13:38:2016543 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416544 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116545 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416546
16547 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216548 ASSERT_TRUE(response2);
16549 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1416550 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
16551
16552 std::string response_data2;
robpercival214763f2016-07-01 23:27:0116553 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1416554 EXPECT_EQ("another", response_data2);
16555}
16556
bnc5452e2a2015-05-08 16:27:4216557// Alternative service requires HTTP/2 (or SPDY), but there is already a
16558// HTTP/1.1 socket open to the alternative server. That socket should not be
16559// used.
bncd16676a2016-07-20 16:23:0116560TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4616561 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4216562 HostPortPair alternative("alternative.example.org", 443);
16563 std::string origin_url = "https://origin.example.org:443";
16564 std::string alternative_url = "https://alternative.example.org:443";
16565
16566 // Negotiate HTTP/1.1 with alternative.example.org.
16567 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616568 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216569 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16570
16571 // HTTP/1.1 data for |request1| and |request2|.
16572 MockWrite http_writes[] = {
16573 MockWrite(
16574 "GET / HTTP/1.1\r\n"
16575 "Host: alternative.example.org\r\n"
16576 "Connection: keep-alive\r\n\r\n"),
16577 MockWrite(
16578 "GET / HTTP/1.1\r\n"
16579 "Host: alternative.example.org\r\n"
16580 "Connection: keep-alive\r\n\r\n"),
16581 };
16582
16583 MockRead http_reads[] = {
16584 MockRead(
16585 "HTTP/1.1 200 OK\r\n"
16586 "Content-Type: text/html; charset=iso-8859-1\r\n"
16587 "Content-Length: 40\r\n\r\n"
16588 "first HTTP/1.1 response from alternative"),
16589 MockRead(
16590 "HTTP/1.1 200 OK\r\n"
16591 "Content-Type: text/html; charset=iso-8859-1\r\n"
16592 "Content-Length: 41\r\n\r\n"
16593 "second HTTP/1.1 response from alternative"),
16594 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116595 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4216596 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16597
16598 // This test documents that an alternate Job should not pool to an already
16599 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4616600 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4216601 StaticSocketDataProvider data_refused;
16602 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16603 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16604
zhongyi3d4a55e72016-04-22 20:36:4616605 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916606 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016607 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216608 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116609 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216610 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116611 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716612 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216613
16614 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4216615 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4616616 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216617 request1.method = "GET";
16618 request1.url = GURL(alternative_url);
16619 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016620 request1.traffic_annotation =
16621 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216622 TestCompletionCallback callback1;
16623
tfarina42834112016-09-22 13:38:2016624 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116625 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616626 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216627 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5216628 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4216629 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216630 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216631 EXPECT_FALSE(response1->was_fetched_via_spdy);
16632 std::string response_data1;
bnc691fda62016-08-12 00:43:1616633 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4216634 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
16635
16636 // Request for origin.example.org, which has an alternative service. This
16637 // will start two Jobs: the alternative looks for connections to pool to,
16638 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4616639 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4216640 // this request fails.
bnc5452e2a2015-05-08 16:27:4216641 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4616642 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216643 request2.method = "GET";
16644 request2.url = GURL(origin_url);
16645 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016646 request2.traffic_annotation =
16647 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216648 TestCompletionCallback callback2;
16649
tfarina42834112016-09-22 13:38:2016650 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116651 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4216652
16653 // Another transaction to alternative. This is to test that the HTTP/1.1
16654 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4216655 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4616656 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216657 request3.method = "GET";
16658 request3.url = GURL(alternative_url);
16659 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016660 request3.traffic_annotation =
16661 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216662 TestCompletionCallback callback3;
16663
tfarina42834112016-09-22 13:38:2016664 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116665 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616666 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216667 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5216668 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4216669 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216670 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216671 EXPECT_FALSE(response3->was_fetched_via_spdy);
16672 std::string response_data3;
bnc691fda62016-08-12 00:43:1616673 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4216674 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
16675}
16676
bncd16676a2016-07-20 16:23:0116677TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2316678 const std::string https_url = "https://www.example.org:8080/";
16679 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416680
rdsmithebb50aa2015-11-12 03:44:3816681 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0116682 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3816683
[email protected]8450d722012-07-02 19:14:0416684 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2316685 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0416686 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
16687 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
16688 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1316689 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916690 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316691 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0216692 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3916693
16694 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1316695 spdy::SpdyHeaderBlock req2_block;
16696 req2_block[spdy::kHttp2MethodHeader] = "GET";
16697 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
16698 req2_block[spdy::kHttp2SchemeHeader] = "http";
16699 req2_block[spdy::kHttp2PathHeader] = "/";
16700 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1516701 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0416702
16703 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116704 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
16705 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0416706 };
16707
Ryan Hamilton0239aac2018-05-19 00:03:1316708 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1516709 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316710 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1516711 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316712 spdy::SpdySerializedFrame body1(
16713 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
16714 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3816715 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316716 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3816717 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3516718 spdy::SpdySerializedFrame resp2(
16719 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316720 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3316721 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116722 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3316723 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4116724 CreateMockRead(wrapped_resp1, 4),
16725 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3316726 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4116727 CreateMockRead(resp2, 8),
16728 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3316729 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
16730 };
[email protected]8450d722012-07-02 19:14:0416731
Ryan Sleevib8d7ea02018-05-07 20:01:0116732 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416733 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716734 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416735
Lily Houghton8c2f97d2018-01-22 05:06:5916736 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4916737 ProxyResolutionService::CreateFixedFromPacResult(
16738 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116739 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716740 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0416741 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616742 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316743 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0416744 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616745 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316746 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16747 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0416748
danakj1fd259a02016-04-16 03:17:0916749 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0416750
16751 // Start the first transaction to set up the SpdySession
16752 HttpRequestInfo request1;
16753 request1.method = "GET";
16754 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416755 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016756 request1.traffic_annotation =
16757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016758 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416759 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2016760 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416761
mmenke666a6fea2015-12-19 04:16:3316762 // This pause is a hack to avoid running into https://crbug.com/497228.
16763 data1.RunUntilPaused();
16764 base::RunLoop().RunUntilIdle();
16765 data1.Resume();
robpercival214763f2016-07-01 23:27:0116766 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0416767 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16768
[email protected]f6c63db52013-02-02 00:35:2216769 LoadTimingInfo load_timing_info1;
16770 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
16771 TestLoadTimingNotReusedWithPac(load_timing_info1,
16772 CONNECT_TIMING_HAS_SSL_TIMES);
16773
mmenke666a6fea2015-12-19 04:16:3316774 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0416775 HttpRequestInfo request2;
16776 request2.method = "GET";
16777 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416778 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016779 request2.traffic_annotation =
16780 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016781 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416782 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2016783 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416784
mmenke666a6fea2015-12-19 04:16:3316785 // This pause is a hack to avoid running into https://crbug.com/497228.
16786 data1.RunUntilPaused();
16787 base::RunLoop().RunUntilIdle();
16788 data1.Resume();
robpercival214763f2016-07-01 23:27:0116789 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3316790
[email protected]8450d722012-07-02 19:14:0416791 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2216792
16793 LoadTimingInfo load_timing_info2;
16794 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
16795 // The established SPDY sessions is considered reused by the HTTP request.
16796 TestLoadTimingReusedWithPac(load_timing_info2);
16797 // HTTP requests over a SPDY session should have a different connection
16798 // socket_log_id than requests over a tunnel.
16799 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0416800}
16801
[email protected]2d88e7d2012-07-19 17:55:1716802// Test that in the case where we have a SPDY session to a SPDY proxy
16803// that we do not pool other origins that resolve to the same IP when
16804// the certificate does not match the new origin.
16805// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0116806TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2316807 const std::string url1 = "http://www.example.org/";
16808 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1716809 const std::string ip_addr = "1.2.3.4";
16810
rdsmithebb50aa2015-11-12 03:44:3816811 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0116812 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3816813
[email protected]2d88e7d2012-07-19 17:55:1716814 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1316815 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2316816 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1316817 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1516818 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1716819
16820 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116821 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1716822 };
16823
Raul Tambre94493c652019-03-11 17:18:3516824 spdy::SpdySerializedFrame resp1(
16825 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316826 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1716827 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116828 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
16829 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1716830 };
16831
Ryan Sleevib8d7ea02018-05-07 20:01:0116832 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3216833 IPAddress ip;
martijn654c8c42016-02-10 22:10:5916834 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1716835 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16836 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3316837 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1716838
16839 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1316840 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916841 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1716842
16843 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116844 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1716845 };
16846
Ryan Hamilton0239aac2018-05-19 00:03:1316847 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3516848 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316849 spdy::SpdySerializedFrame body2(
16850 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116851 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3316852 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1716853
Ryan Sleevib8d7ea02018-05-07 20:01:0116854 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1716855 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3316856 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1716857
16858 // Set up a proxy config that sends HTTP requests to a proxy, and
16859 // all others direct.
16860 ProxyConfig proxy_config;
16861 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4916862 session_deps_.proxy_resolution_service =
16863 std::make_unique<ProxyResolutionService>(
16864 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
16865 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
16866 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1716867
bncce36dca22015-04-21 22:11:2316868 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616869 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1716870 // Load a valid cert. Note, that this does not need to
16871 // be valid for proxy because the MockSSLClientSocket does
16872 // not actually verify it. But SpdySession will use this
16873 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4916874 ssl1.ssl_info.cert =
16875 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
16876 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3316877 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16878 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1716879
16880 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616881 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316882 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16883 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1716884
Jeremy Roman0579ed62017-08-29 15:56:1916885 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2316886 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0716887 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1716888
danakj1fd259a02016-04-16 03:17:0916889 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1716890
16891 // Start the first transaction to set up the SpdySession
16892 HttpRequestInfo request1;
16893 request1.method = "GET";
16894 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1716895 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016896 request1.traffic_annotation =
16897 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016898 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716899 TestCompletionCallback callback1;
16900 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016901 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3316902 // This pause is a hack to avoid running into https://crbug.com/497228.
16903 data1.RunUntilPaused();
16904 base::RunLoop().RunUntilIdle();
16905 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1716906
robpercival214763f2016-07-01 23:27:0116907 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716908 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16909
16910 // Now, start the HTTP request
16911 HttpRequestInfo request2;
16912 request2.method = "GET";
16913 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1716914 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016915 request2.traffic_annotation =
16916 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016917 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716918 TestCompletionCallback callback2;
16919 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016920 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516921 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1716922
16923 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0116924 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716925 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16926}
16927
[email protected]85f97342013-04-17 06:12:2416928// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
16929// error) in SPDY session, removes the socket from pool and closes the SPDY
16930// session. Verify that new url's from the same HttpNetworkSession (and a new
16931// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0116932TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2316933 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2416934
16935 MockRead reads1[] = {
16936 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
16937 };
16938
Ryan Sleevib8d7ea02018-05-07 20:01:0116939 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2416940
Ryan Hamilton0239aac2018-05-19 00:03:1316941 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916942 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2416943 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116944 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2416945 };
16946
Raul Tambre94493c652019-03-11 17:18:3516947 spdy::SpdySerializedFrame resp2(
16948 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316949 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2416950 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4116951 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
16952 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2416953 };
16954
Ryan Sleevib8d7ea02018-05-07 20:01:0116955 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2416956
[email protected]85f97342013-04-17 06:12:2416957 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616958 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016959 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16960 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2416961
16962 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616963 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016964 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16965 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2416966
danakj1fd259a02016-04-16 03:17:0916967 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5016968 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2416969
16970 // Start the first transaction to set up the SpdySession and verify that
16971 // connection was closed.
16972 HttpRequestInfo request1;
16973 request1.method = "GET";
16974 request1.url = GURL(https_url);
16975 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016976 request1.traffic_annotation =
16977 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016978 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416979 TestCompletionCallback callback1;
16980 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016981 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0116982 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2416983
16984 // Now, start the second request and make sure it succeeds.
16985 HttpRequestInfo request2;
16986 request2.method = "GET";
16987 request2.url = GURL(https_url);
16988 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016989 request2.traffic_annotation =
16990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016991 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416992 TestCompletionCallback callback2;
16993 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016994 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2416995
robpercival214763f2016-07-01 23:27:0116996 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2416997 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16998}
16999
bncd16676a2016-07-20 16:23:0117000TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0317001 ClientSocketPoolManager::set_max_sockets_per_group(
17002 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17003 ClientSocketPoolManager::set_max_sockets_per_pool(
17004 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17005
17006 // Use two different hosts with different IPs so they don't get pooled.
17007 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
17008 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0917009 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0317010
17011 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617012 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317013 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617014 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0317015 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17016 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17017
Ryan Hamilton0239aac2018-05-19 00:03:1317018 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917019 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317020 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117021 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0317022 };
Ryan Hamilton0239aac2018-05-19 00:03:1317023 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517024 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317025 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117026 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317027 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117028 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917029 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317030 };
17031
rdsmithebb50aa2015-11-12 03:44:3817032 // Use a separate test instance for the separate SpdySession that will be
17033 // created.
bncd16676a2016-07-20 16:23:0117034 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0117035 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1217036 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0317037
Ryan Hamilton0239aac2018-05-19 00:03:1317038 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4917039 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317040 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117041 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0317042 };
Ryan Hamilton0239aac2018-05-19 00:03:1317043 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517044 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317045 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117046 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317047 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117048 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917049 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317050 };
17051
Ryan Sleevib8d7ea02018-05-07 20:01:0117052 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1217053 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0317054
17055 MockWrite http_write[] = {
17056 MockWrite("GET / HTTP/1.1\r\n"
17057 "Host: www.a.com\r\n"
17058 "Connection: keep-alive\r\n\r\n"),
17059 };
17060
17061 MockRead http_read[] = {
17062 MockRead("HTTP/1.1 200 OK\r\n"),
17063 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
17064 MockRead("Content-Length: 6\r\n\r\n"),
17065 MockRead("hello!"),
17066 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117067 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0317068 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17069
17070 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117071 SpdySessionKey spdy_session_key_a(
17072 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417073 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17074 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317075 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617076 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317077
17078 TestCompletionCallback callback;
17079 HttpRequestInfo request1;
17080 request1.method = "GET";
17081 request1.url = GURL("https://www.a.com/");
17082 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017083 request1.traffic_annotation =
17084 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817085 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917086 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317087
tfarina42834112016-09-22 13:38:2017088 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117089 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17090 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317091
17092 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217093 ASSERT_TRUE(response);
17094 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217095 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317096 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217097 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0317098
17099 std::string response_data;
robpercival214763f2016-07-01 23:27:0117100 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317101 EXPECT_EQ("hello!", response_data);
17102 trans.reset();
17103 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617104 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317105
17106 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117107 SpdySessionKey spdy_session_key_b(
17108 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417109 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17110 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317111 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617112 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317113 HttpRequestInfo request2;
17114 request2.method = "GET";
17115 request2.url = GURL("https://www.b.com/");
17116 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017117 request2.traffic_annotation =
17118 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817119 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917120 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317121
tfarina42834112016-09-22 13:38:2017122 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117123 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17124 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317125
17126 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217127 ASSERT_TRUE(response);
17128 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217129 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317130 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217131 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117132 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317133 EXPECT_EQ("hello!", response_data);
17134 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617135 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317136 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617137 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317138
17139 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1117140 SpdySessionKey spdy_session_key_a1(
17141 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3417142 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
17143 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0317144 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617145 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0317146 HttpRequestInfo request3;
17147 request3.method = "GET";
17148 request3.url = GURL("http://www.a.com/");
17149 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017150 request3.traffic_annotation =
17151 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817152 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917153 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317154
tfarina42834112016-09-22 13:38:2017155 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117156 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17157 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317158
17159 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217160 ASSERT_TRUE(response);
17161 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0317162 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17163 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217164 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117165 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317166 EXPECT_EQ("hello!", response_data);
17167 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617168 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317169 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617170 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317171}
17172
bncd16676a2016-07-20 16:23:0117173TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417174 HttpRequestInfo request;
17175 request.method = "GET";
bncce36dca22015-04-21 22:11:2317176 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017177 request.traffic_annotation =
17178 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417179
danakj1fd259a02016-04-16 03:17:0917180 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617181 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417182
ttuttled9dbc652015-09-29 20:00:5917183 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417184 StaticSocketDataProvider data;
17185 data.set_connect_data(mock_connect);
17186 session_deps_.socket_factory->AddSocketDataProvider(&data);
17187
17188 TestCompletionCallback callback;
17189
tfarina42834112016-09-22 13:38:2017190 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117191 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417192
17193 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117194 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417195
ttuttle1f2d7e92015-04-28 16:17:4717196 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617197 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717198 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117199 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917200
17201 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617202 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917203 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417204}
17205
bncd16676a2016-07-20 16:23:0117206TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417207 HttpRequestInfo request;
17208 request.method = "GET";
bncce36dca22015-04-21 22:11:2317209 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017210 request.traffic_annotation =
17211 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417212
danakj1fd259a02016-04-16 03:17:0917213 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617214 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417215
ttuttled9dbc652015-09-29 20:00:5917216 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417217 StaticSocketDataProvider data;
17218 data.set_connect_data(mock_connect);
17219 session_deps_.socket_factory->AddSocketDataProvider(&data);
17220
17221 TestCompletionCallback callback;
17222
tfarina42834112016-09-22 13:38:2017223 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117224 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417225
17226 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117227 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417228
ttuttle1f2d7e92015-04-28 16:17:4717229 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617230 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717231 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117232 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917233
17234 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617235 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917236 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417237}
17238
bncd16676a2016-07-20 16:23:0117239TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417240 HttpRequestInfo request;
17241 request.method = "GET";
bncce36dca22015-04-21 22:11:2317242 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017243 request.traffic_annotation =
17244 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417245
danakj1fd259a02016-04-16 03:17:0917246 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617247 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417248
17249 MockWrite data_writes[] = {
17250 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17251 };
17252 MockRead data_reads[] = {
17253 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17254 };
17255
Ryan Sleevib8d7ea02018-05-07 20:01:0117256 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417257 session_deps_.socket_factory->AddSocketDataProvider(&data);
17258
17259 TestCompletionCallback callback;
17260
tfarina42834112016-09-22 13:38:2017261 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117262 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417263
17264 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117265 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417266}
17267
bncd16676a2016-07-20 16:23:0117268TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417269 HttpRequestInfo request;
17270 request.method = "GET";
bncce36dca22015-04-21 22:11:2317271 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017272 request.traffic_annotation =
17273 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417274
danakj1fd259a02016-04-16 03:17:0917275 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617276 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417277
17278 MockWrite data_writes[] = {
17279 MockWrite(ASYNC, ERR_CONNECTION_RESET),
17280 };
17281 MockRead data_reads[] = {
17282 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17283 };
17284
Ryan Sleevib8d7ea02018-05-07 20:01:0117285 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417286 session_deps_.socket_factory->AddSocketDataProvider(&data);
17287
17288 TestCompletionCallback callback;
17289
tfarina42834112016-09-22 13:38:2017290 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117291 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417292
17293 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117294 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417295}
17296
bncd16676a2016-07-20 16:23:0117297TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417298 HttpRequestInfo request;
17299 request.method = "GET";
bncce36dca22015-04-21 22:11:2317300 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017301 request.traffic_annotation =
17302 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417303
danakj1fd259a02016-04-16 03:17:0917304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617305 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417306
17307 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317308 MockWrite(
17309 "GET / HTTP/1.1\r\n"
17310 "Host: www.example.org\r\n"
17311 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417312 };
17313 MockRead data_reads[] = {
17314 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
17315 };
17316
Ryan Sleevib8d7ea02018-05-07 20:01:0117317 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417318 session_deps_.socket_factory->AddSocketDataProvider(&data);
17319
17320 TestCompletionCallback callback;
17321
tfarina42834112016-09-22 13:38:2017322 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117323 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417324
17325 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117326 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417327}
17328
bncd16676a2016-07-20 16:23:0117329TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417330 HttpRequestInfo request;
17331 request.method = "GET";
bncce36dca22015-04-21 22:11:2317332 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017333 request.traffic_annotation =
17334 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417335
danakj1fd259a02016-04-16 03:17:0917336 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617337 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417338
17339 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317340 MockWrite(
17341 "GET / HTTP/1.1\r\n"
17342 "Host: www.example.org\r\n"
17343 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417344 };
17345 MockRead data_reads[] = {
17346 MockRead(ASYNC, ERR_CONNECTION_RESET),
17347 };
17348
Ryan Sleevib8d7ea02018-05-07 20:01:0117349 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417350 session_deps_.socket_factory->AddSocketDataProvider(&data);
17351
17352 TestCompletionCallback callback;
17353
tfarina42834112016-09-22 13:38:2017354 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117355 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417356
17357 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117358 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417359}
17360
[email protected]043b68c82013-08-22 23:41:5217361// Tests that when a used socket is returned to the SSL socket pool, it's closed
17362// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117363TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5217364 ClientSocketPoolManager::set_max_sockets_per_group(
17365 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17366 ClientSocketPoolManager::set_max_sockets_per_pool(
17367 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17368
17369 // Set up SSL request.
17370
17371 HttpRequestInfo ssl_request;
17372 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2317373 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017374 ssl_request.traffic_annotation =
17375 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217376
17377 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2317378 MockWrite(
17379 "GET / HTTP/1.1\r\n"
17380 "Host: www.example.org\r\n"
17381 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217382 };
17383 MockRead ssl_reads[] = {
17384 MockRead("HTTP/1.1 200 OK\r\n"),
17385 MockRead("Content-Length: 11\r\n\r\n"),
17386 MockRead("hello world"),
17387 MockRead(SYNCHRONOUS, OK),
17388 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117389 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5217390 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17391
17392 SSLSocketDataProvider ssl(ASYNC, OK);
17393 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17394
17395 // Set up HTTP request.
17396
17397 HttpRequestInfo http_request;
17398 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317399 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017400 http_request.traffic_annotation =
17401 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217402
17403 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317404 MockWrite(
17405 "GET / HTTP/1.1\r\n"
17406 "Host: www.example.org\r\n"
17407 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217408 };
17409 MockRead http_reads[] = {
17410 MockRead("HTTP/1.1 200 OK\r\n"),
17411 MockRead("Content-Length: 7\r\n\r\n"),
17412 MockRead("falafel"),
17413 MockRead(SYNCHRONOUS, OK),
17414 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117415 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217416 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17417
danakj1fd259a02016-04-16 03:17:0917418 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217419
17420 // Start the SSL request.
17421 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1617422 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017423 ASSERT_EQ(ERR_IO_PENDING,
17424 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
17425 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5217426
17427 // Start the HTTP request. Pool should stall.
17428 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617429 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017430 ASSERT_EQ(ERR_IO_PENDING,
17431 http_trans.Start(&http_request, http_callback.callback(),
17432 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117433 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217434
17435 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0117436 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217437 std::string response_data;
bnc691fda62016-08-12 00:43:1617438 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217439 EXPECT_EQ("hello world", response_data);
17440
17441 // The SSL socket should automatically be closed, so the HTTP request can
17442 // start.
Matt Menke9d5e2c92019-02-05 01:42:2317443 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4117444 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217445
17446 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0117447 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1617448 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217449 EXPECT_EQ("falafel", response_data);
17450
dcheng48459ac22014-08-26 00:46:4117451 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217452}
17453
17454// Tests that when a SSL connection is established but there's no corresponding
17455// request that needs it, the new socket is closed if the transport socket pool
17456// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117457TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5217458 ClientSocketPoolManager::set_max_sockets_per_group(
17459 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17460 ClientSocketPoolManager::set_max_sockets_per_pool(
17461 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17462
17463 // Set up an ssl request.
17464
17465 HttpRequestInfo ssl_request;
17466 ssl_request.method = "GET";
17467 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1017468 ssl_request.traffic_annotation =
17469 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217470
17471 // No data will be sent on the SSL socket.
17472 StaticSocketDataProvider ssl_data;
17473 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17474
17475 SSLSocketDataProvider ssl(ASYNC, OK);
17476 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17477
17478 // Set up HTTP request.
17479
17480 HttpRequestInfo http_request;
17481 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317482 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017483 http_request.traffic_annotation =
17484 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217485
17486 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317487 MockWrite(
17488 "GET / HTTP/1.1\r\n"
17489 "Host: www.example.org\r\n"
17490 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217491 };
17492 MockRead http_reads[] = {
17493 MockRead("HTTP/1.1 200 OK\r\n"),
17494 MockRead("Content-Length: 7\r\n\r\n"),
17495 MockRead("falafel"),
17496 MockRead(SYNCHRONOUS, OK),
17497 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117498 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217499 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17500
danakj1fd259a02016-04-16 03:17:0917501 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217502
17503 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
17504 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2917505 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5917506 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2317507 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217508
17509 // Start the HTTP request. Pool should stall.
17510 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617511 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017512 ASSERT_EQ(ERR_IO_PENDING,
17513 http_trans.Start(&http_request, http_callback.callback(),
17514 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117515 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217516
17517 // The SSL connection will automatically be closed once the connection is
17518 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0117519 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217520 std::string response_data;
bnc691fda62016-08-12 00:43:1617521 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217522 EXPECT_EQ("falafel", response_data);
17523
dcheng48459ac22014-08-26 00:46:4117524 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217525}
17526
bncd16676a2016-07-20 16:23:0117527TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917528 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217529 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917530 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217531 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417532
17533 HttpRequestInfo request;
17534 request.method = "POST";
17535 request.url = GURL("http://www.foo.com/");
17536 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017537 request.traffic_annotation =
17538 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417539
danakj1fd259a02016-04-16 03:17:0917540 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617541 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417542 // Send headers successfully, but get an error while sending the body.
17543 MockWrite data_writes[] = {
17544 MockWrite("POST / HTTP/1.1\r\n"
17545 "Host: www.foo.com\r\n"
17546 "Connection: keep-alive\r\n"
17547 "Content-Length: 3\r\n\r\n"),
17548 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17549 };
17550
17551 MockRead data_reads[] = {
17552 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17553 MockRead("hello world"),
17554 MockRead(SYNCHRONOUS, OK),
17555 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117556 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417557 session_deps_.socket_factory->AddSocketDataProvider(&data);
17558
17559 TestCompletionCallback callback;
17560
tfarina42834112016-09-22 13:38:2017561 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117562 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417563
17564 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117565 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417566
bnc691fda62016-08-12 00:43:1617567 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217568 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417569
wezca1070932016-05-26 20:30:5217570 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417571 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17572
17573 std::string response_data;
bnc691fda62016-08-12 00:43:1617574 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117575 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417576 EXPECT_EQ("hello world", response_data);
17577}
17578
17579// This test makes sure the retry logic doesn't trigger when reading an error
17580// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0117581TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417582 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0917583 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5417584 MockWrite data_writes[] = {
17585 MockWrite("GET / HTTP/1.1\r\n"
17586 "Host: www.foo.com\r\n"
17587 "Connection: keep-alive\r\n\r\n"),
17588 MockWrite("POST / HTTP/1.1\r\n"
17589 "Host: www.foo.com\r\n"
17590 "Connection: keep-alive\r\n"
17591 "Content-Length: 3\r\n\r\n"),
17592 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17593 };
17594
17595 MockRead data_reads[] = {
17596 MockRead("HTTP/1.1 200 Peachy\r\n"
17597 "Content-Length: 14\r\n\r\n"),
17598 MockRead("first response"),
17599 MockRead("HTTP/1.1 400 Not OK\r\n"
17600 "Content-Length: 15\r\n\r\n"),
17601 MockRead("second response"),
17602 MockRead(SYNCHRONOUS, OK),
17603 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117604 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417605 session_deps_.socket_factory->AddSocketDataProvider(&data);
17606
17607 TestCompletionCallback callback;
17608 HttpRequestInfo request1;
17609 request1.method = "GET";
17610 request1.url = GURL("http://www.foo.com/");
17611 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017612 request1.traffic_annotation =
17613 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417614
bnc87dcefc2017-05-25 12:47:5817615 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1917616 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017617 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117618 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417619
17620 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117621 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417622
17623 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5217624 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5417625
wezca1070932016-05-26 20:30:5217626 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5417627 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
17628
17629 std::string response_data1;
17630 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0117631 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417632 EXPECT_EQ("first response", response_data1);
17633 // Delete the transaction to release the socket back into the socket pool.
17634 trans1.reset();
17635
danakj1fd259a02016-04-16 03:17:0917636 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217637 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917638 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217639 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417640
17641 HttpRequestInfo request2;
17642 request2.method = "POST";
17643 request2.url = GURL("http://www.foo.com/");
17644 request2.upload_data_stream = &upload_data_stream;
17645 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017646 request2.traffic_annotation =
17647 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417648
bnc691fda62016-08-12 00:43:1617649 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017650 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117651 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417652
17653 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117654 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417655
bnc691fda62016-08-12 00:43:1617656 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217657 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5417658
wezca1070932016-05-26 20:30:5217659 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5417660 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
17661
17662 std::string response_data2;
bnc691fda62016-08-12 00:43:1617663 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0117664 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417665 EXPECT_EQ("second response", response_data2);
17666}
17667
bncd16676a2016-07-20 16:23:0117668TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417669 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0917670 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217671 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917672 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217673 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417674
17675 HttpRequestInfo request;
17676 request.method = "POST";
17677 request.url = GURL("http://www.foo.com/");
17678 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017679 request.traffic_annotation =
17680 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417681
danakj1fd259a02016-04-16 03:17:0917682 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617683 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417684 // Send headers successfully, but get an error while sending the body.
17685 MockWrite data_writes[] = {
17686 MockWrite("POST / HTTP/1.1\r\n"
17687 "Host: www.foo.com\r\n"
17688 "Connection: keep-alive\r\n"
17689 "Content-Length: 3\r\n\r\n"
17690 "fo"),
17691 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17692 };
17693
17694 MockRead data_reads[] = {
17695 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17696 MockRead("hello world"),
17697 MockRead(SYNCHRONOUS, OK),
17698 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117699 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417700 session_deps_.socket_factory->AddSocketDataProvider(&data);
17701
17702 TestCompletionCallback callback;
17703
tfarina42834112016-09-22 13:38:2017704 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117705 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417706
17707 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117708 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417709
bnc691fda62016-08-12 00:43:1617710 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217711 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417712
wezca1070932016-05-26 20:30:5217713 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417714 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17715
17716 std::string response_data;
bnc691fda62016-08-12 00:43:1617717 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117718 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417719 EXPECT_EQ("hello world", response_data);
17720}
17721
17722// This tests the more common case than the previous test, where headers and
17723// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0117724TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0717725 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5417726
17727 HttpRequestInfo request;
17728 request.method = "POST";
17729 request.url = GURL("http://www.foo.com/");
17730 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017731 request.traffic_annotation =
17732 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417733
danakj1fd259a02016-04-16 03:17:0917734 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617735 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417736 // Send headers successfully, but get an error while sending the body.
17737 MockWrite data_writes[] = {
17738 MockWrite("POST / HTTP/1.1\r\n"
17739 "Host: www.foo.com\r\n"
17740 "Connection: keep-alive\r\n"
17741 "Transfer-Encoding: chunked\r\n\r\n"),
17742 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17743 };
17744
17745 MockRead data_reads[] = {
17746 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17747 MockRead("hello world"),
17748 MockRead(SYNCHRONOUS, OK),
17749 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117750 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417751 session_deps_.socket_factory->AddSocketDataProvider(&data);
17752
17753 TestCompletionCallback callback;
17754
tfarina42834112016-09-22 13:38:2017755 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117756 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417757 // Make sure the headers are sent before adding a chunk. This ensures that
17758 // they can't be merged with the body in a single send. Not currently
17759 // necessary since a chunked body is never merged with headers, but this makes
17760 // the test more future proof.
17761 base::RunLoop().RunUntilIdle();
17762
mmenkecbc2b712014-10-09 20:29:0717763 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5417764
17765 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117766 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417767
bnc691fda62016-08-12 00:43:1617768 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217769 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417770
wezca1070932016-05-26 20:30:5217771 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417772 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17773
17774 std::string response_data;
bnc691fda62016-08-12 00:43:1617775 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117776 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417777 EXPECT_EQ("hello world", response_data);
17778}
17779
bncd16676a2016-07-20 16:23:0117780TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917781 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217782 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917783 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217784 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417785
17786 HttpRequestInfo request;
17787 request.method = "POST";
17788 request.url = GURL("http://www.foo.com/");
17789 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017790 request.traffic_annotation =
17791 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417792
danakj1fd259a02016-04-16 03:17:0917793 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617794 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417795
17796 MockWrite data_writes[] = {
17797 MockWrite("POST / HTTP/1.1\r\n"
17798 "Host: www.foo.com\r\n"
17799 "Connection: keep-alive\r\n"
17800 "Content-Length: 3\r\n\r\n"),
17801 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17802 };
17803
17804 MockRead data_reads[] = {
17805 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17806 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17807 MockRead("hello world"),
17808 MockRead(SYNCHRONOUS, OK),
17809 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117810 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417811 session_deps_.socket_factory->AddSocketDataProvider(&data);
17812
17813 TestCompletionCallback callback;
17814
tfarina42834112016-09-22 13:38:2017815 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117816 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417817
17818 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117819 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417820
bnc691fda62016-08-12 00:43:1617821 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217822 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417823
wezca1070932016-05-26 20:30:5217824 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417825 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17826
17827 std::string response_data;
bnc691fda62016-08-12 00:43:1617828 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117829 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417830 EXPECT_EQ("hello world", response_data);
17831}
17832
bncd16676a2016-07-20 16:23:0117833TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917834 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217835 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917836 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217837 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417838
17839 HttpRequestInfo request;
17840 request.method = "POST";
17841 request.url = GURL("http://www.foo.com/");
17842 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017843 request.traffic_annotation =
17844 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417845
danakj1fd259a02016-04-16 03:17:0917846 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617847 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417848 // Send headers successfully, but get an error while sending the body.
17849 MockWrite data_writes[] = {
17850 MockWrite("POST / HTTP/1.1\r\n"
17851 "Host: www.foo.com\r\n"
17852 "Connection: keep-alive\r\n"
17853 "Content-Length: 3\r\n\r\n"),
17854 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17855 };
17856
17857 MockRead data_reads[] = {
17858 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
17859 MockRead("hello world"),
17860 MockRead(SYNCHRONOUS, OK),
17861 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117862 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417863 session_deps_.socket_factory->AddSocketDataProvider(&data);
17864
17865 TestCompletionCallback callback;
17866
tfarina42834112016-09-22 13:38:2017867 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117868 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417869
17870 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117871 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417872}
17873
bncd16676a2016-07-20 16:23:0117874TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417875 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917876 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217877 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917878 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217879 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417880
17881 HttpRequestInfo request;
17882 request.method = "POST";
17883 request.url = GURL("http://www.foo.com/");
17884 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017885 request.traffic_annotation =
17886 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417887
danakj1fd259a02016-04-16 03:17:0917888 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617889 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417890 // Send headers successfully, but get an error while sending the body.
17891 MockWrite data_writes[] = {
17892 MockWrite("POST / HTTP/1.1\r\n"
17893 "Host: www.foo.com\r\n"
17894 "Connection: keep-alive\r\n"
17895 "Content-Length: 3\r\n\r\n"),
17896 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17897 };
17898
17899 MockRead data_reads[] = {
17900 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17901 MockRead("HTTP/1.0 302 Redirect\r\n"),
17902 MockRead("Location: http://somewhere-else.com/\r\n"),
17903 MockRead("Content-Length: 0\r\n\r\n"),
17904 MockRead(SYNCHRONOUS, OK),
17905 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117906 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417907 session_deps_.socket_factory->AddSocketDataProvider(&data);
17908
17909 TestCompletionCallback callback;
17910
tfarina42834112016-09-22 13:38:2017911 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117912 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417913
17914 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117915 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417916}
17917
bncd16676a2016-07-20 16:23:0117918TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917919 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217920 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917921 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217922 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417923
17924 HttpRequestInfo request;
17925 request.method = "POST";
17926 request.url = GURL("http://www.foo.com/");
17927 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017928 request.traffic_annotation =
17929 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417930
danakj1fd259a02016-04-16 03:17:0917931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617932 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417933 // Send headers successfully, but get an error while sending the body.
17934 MockWrite data_writes[] = {
17935 MockWrite("POST / HTTP/1.1\r\n"
17936 "Host: www.foo.com\r\n"
17937 "Connection: keep-alive\r\n"
17938 "Content-Length: 3\r\n\r\n"),
17939 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17940 };
17941
17942 MockRead data_reads[] = {
17943 MockRead("HTTP 0.9 rocks!"),
17944 MockRead(SYNCHRONOUS, OK),
17945 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117946 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417947 session_deps_.socket_factory->AddSocketDataProvider(&data);
17948
17949 TestCompletionCallback callback;
17950
tfarina42834112016-09-22 13:38:2017951 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117952 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417953
17954 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117955 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417956}
17957
bncd16676a2016-07-20 16:23:0117958TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0917959 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217960 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917961 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217962 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417963
17964 HttpRequestInfo request;
17965 request.method = "POST";
17966 request.url = GURL("http://www.foo.com/");
17967 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017968 request.traffic_annotation =
17969 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417970
danakj1fd259a02016-04-16 03:17:0917971 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617972 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417973 // Send headers successfully, but get an error while sending the body.
17974 MockWrite data_writes[] = {
17975 MockWrite("POST / HTTP/1.1\r\n"
17976 "Host: www.foo.com\r\n"
17977 "Connection: keep-alive\r\n"
17978 "Content-Length: 3\r\n\r\n"),
17979 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17980 };
17981
17982 MockRead data_reads[] = {
17983 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
17984 MockRead(SYNCHRONOUS, OK),
17985 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117986 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417987 session_deps_.socket_factory->AddSocketDataProvider(&data);
17988
17989 TestCompletionCallback callback;
17990
tfarina42834112016-09-22 13:38:2017991 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117992 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417993
17994 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117995 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417996}
17997
Bence Békydca6bd92018-01-30 13:43:0617998#if BUILDFLAG(ENABLE_WEBSOCKETS)
17999
18000namespace {
18001
18002void AddWebSocketHeaders(HttpRequestHeaders* headers) {
18003 headers->SetHeader("Connection", "Upgrade");
18004 headers->SetHeader("Upgrade", "websocket");
18005 headers->SetHeader("Origin", "http://www.example.org");
18006 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0618007}
18008
18009} // namespace
18010
18011TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0118012 for (bool secure : {true, false}) {
18013 MockWrite data_writes[] = {
18014 MockWrite("GET / HTTP/1.1\r\n"
18015 "Host: www.example.org\r\n"
18016 "Connection: Upgrade\r\n"
18017 "Upgrade: websocket\r\n"
18018 "Origin: http://www.example.org\r\n"
18019 "Sec-WebSocket-Version: 13\r\n"
18020 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18021 "Sec-WebSocket-Extensions: permessage-deflate; "
18022 "client_max_window_bits\r\n\r\n")};
18023
18024 MockRead data_reads[] = {
18025 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18026 "Upgrade: websocket\r\n"
18027 "Connection: Upgrade\r\n"
18028 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
18029
Ryan Sleevib8d7ea02018-05-07 20:01:0118030 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0118031 session_deps_.socket_factory->AddSocketDataProvider(&data);
18032 SSLSocketDataProvider ssl(ASYNC, OK);
18033 if (secure)
18034 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0618035
18036 HttpRequestInfo request;
18037 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0118038 request.url =
18039 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18040 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e2018-02-07 07:41:1018041 request.traffic_annotation =
18042 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0618043
Bence Béky2fcf4fa2018-04-06 20:06:0118044 TestWebSocketHandshakeStreamCreateHelper
18045 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1518046
Bence Béky2fcf4fa2018-04-06 20:06:0118047 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0618048 HttpNetworkTransaction trans(LOW, session.get());
18049 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0118050 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0618051
18052 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0118053 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0618055
Bence Béky2fcf4fa2018-04-06 20:06:0118056 const HttpStreamRequest* stream_request = trans.stream_request_.get();
18057 ASSERT_TRUE(stream_request);
18058 EXPECT_EQ(&websocket_handshake_stream_create_helper,
18059 stream_request->websocket_handshake_stream_create_helper());
18060
18061 rv = callback.WaitForResult();
18062 EXPECT_THAT(rv, IsOk());
18063
18064 EXPECT_TRUE(data.AllReadDataConsumed());
18065 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0618066 }
18067}
18068
Adam Rice425cf122015-01-19 06:18:2418069// Verify that proxy headers are not sent to the destination server when
18070// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0118071TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2418072 HttpRequestInfo request;
18073 request.method = "GET";
bncce36dca22015-04-21 22:11:2318074 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018075 request.traffic_annotation =
18076 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418077 AddWebSocketHeaders(&request.extra_headers);
18078
18079 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918080 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918081 ProxyResolutionService::CreateFixedFromPacResult(
18082 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418083
danakj1fd259a02016-04-16 03:17:0918084 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418085
18086 // Since a proxy is configured, try to establish a tunnel.
18087 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1718088 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18089 "Host: www.example.org:443\r\n"
18090 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418091
18092 // After calling trans->RestartWithAuth(), this is the request we should
18093 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1718094 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18095 "Host: www.example.org:443\r\n"
18096 "Proxy-Connection: keep-alive\r\n"
18097 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418098
rsleevidb16bb02015-11-12 23:47:1718099 MockWrite("GET / HTTP/1.1\r\n"
18100 "Host: www.example.org\r\n"
18101 "Connection: Upgrade\r\n"
18102 "Upgrade: websocket\r\n"
18103 "Origin: http://www.example.org\r\n"
18104 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1518105 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18106 "Sec-WebSocket-Extensions: permessage-deflate; "
18107 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418108
18109 // The proxy responds to the connect with a 407, using a persistent
18110 // connection.
18111 MockRead data_reads[] = {
18112 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1518113 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
18114 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
18115 "Content-Length: 0\r\n"
18116 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418117
18118 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18119
Bence Béky8d1c6052018-02-07 12:48:1518120 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18121 "Upgrade: websocket\r\n"
18122 "Connection: Upgrade\r\n"
18123 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418124
Ryan Sleevib8d7ea02018-05-07 20:01:0118125 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418126 session_deps_.socket_factory->AddSocketDataProvider(&data);
18127 SSLSocketDataProvider ssl(ASYNC, OK);
18128 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18129
Bence Béky8d1c6052018-02-07 12:48:1518130 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18131
bnc87dcefc2017-05-25 12:47:5818132 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918133 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418134 trans->SetWebSocketHandshakeStreamCreateHelper(
18135 &websocket_stream_create_helper);
18136
18137 {
18138 TestCompletionCallback callback;
18139
tfarina42834112016-09-22 13:38:2018140 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118141 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418142
18143 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118144 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418145 }
18146
18147 const HttpResponseInfo* response = trans->GetResponseInfo();
18148 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218149 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418150 EXPECT_EQ(407, response->headers->response_code());
18151
18152 {
18153 TestCompletionCallback callback;
18154
18155 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
18156 callback.callback());
robpercival214763f2016-07-01 23:27:0118157 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418158
18159 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118160 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418161 }
18162
18163 response = trans->GetResponseInfo();
18164 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218165 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418166
18167 EXPECT_EQ(101, response->headers->response_code());
18168
18169 trans.reset();
18170 session->CloseAllConnections();
18171}
18172
18173// Verify that proxy headers are not sent to the destination server when
18174// establishing a tunnel for an insecure WebSocket connection.
18175// This requires the authentication info to be injected into the auth cache
18176// due to crbug.com/395064
18177// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0118178TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2418179 HttpRequestInfo request;
18180 request.method = "GET";
bncce36dca22015-04-21 22:11:2318181 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018182 request.traffic_annotation =
18183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418184 AddWebSocketHeaders(&request.extra_headers);
18185
18186 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918187 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918188 ProxyResolutionService::CreateFixedFromPacResult(
18189 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418190
danakj1fd259a02016-04-16 03:17:0918191 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418192
18193 MockWrite data_writes[] = {
18194 // Try to establish a tunnel for the WebSocket connection, with
18195 // credentials. Because WebSockets have a separate set of socket pools,
18196 // they cannot and will not use the same TCP/IP connection as the
18197 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1518198 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
18199 "Host: www.example.org:80\r\n"
18200 "Proxy-Connection: keep-alive\r\n"
18201 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418202
Bence Béky8d1c6052018-02-07 12:48:1518203 MockWrite("GET / HTTP/1.1\r\n"
18204 "Host: www.example.org\r\n"
18205 "Connection: Upgrade\r\n"
18206 "Upgrade: websocket\r\n"
18207 "Origin: http://www.example.org\r\n"
18208 "Sec-WebSocket-Version: 13\r\n"
18209 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18210 "Sec-WebSocket-Extensions: permessage-deflate; "
18211 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418212
18213 MockRead data_reads[] = {
18214 // HTTP CONNECT with credentials.
18215 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18216
18217 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1518218 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18219 "Upgrade: websocket\r\n"
18220 "Connection: Upgrade\r\n"
18221 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418222
Ryan Sleevib8d7ea02018-05-07 20:01:0118223 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418224 session_deps_.socket_factory->AddSocketDataProvider(&data);
18225
18226 session->http_auth_cache()->Add(
18227 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
18228 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
18229
Bence Béky8d1c6052018-02-07 12:48:1518230 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18231
bnc87dcefc2017-05-25 12:47:5818232 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918233 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418234 trans->SetWebSocketHandshakeStreamCreateHelper(
18235 &websocket_stream_create_helper);
18236
18237 TestCompletionCallback callback;
18238
tfarina42834112016-09-22 13:38:2018239 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118240 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418241
18242 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118243 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418244
18245 const HttpResponseInfo* response = trans->GetResponseInfo();
18246 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218247 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418248
18249 EXPECT_EQ(101, response->headers->response_code());
18250
18251 trans.reset();
18252 session->CloseAllConnections();
18253}
18254
Matt Menke1d6093e32019-03-22 17:33:4318255// WebSockets over QUIC is not supported, including over QUIC proxies.
18256TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
18257 for (bool secure : {true, false}) {
18258 SCOPED_TRACE(secure);
18259 session_deps_.proxy_resolution_service =
18260 ProxyResolutionService::CreateFixedFromPacResult(
18261 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
18262 session_deps_.enable_quic = true;
18263
18264 HttpRequestInfo request;
18265 request.url =
18266 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18267 AddWebSocketHeaders(&request.extra_headers);
18268 request.traffic_annotation =
18269 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18270
18271 TestWebSocketHandshakeStreamCreateHelper
18272 websocket_handshake_stream_create_helper;
18273
18274 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18275 HttpNetworkTransaction trans(LOW, session.get());
18276 trans.SetWebSocketHandshakeStreamCreateHelper(
18277 &websocket_handshake_stream_create_helper);
18278
18279 TestCompletionCallback callback;
18280 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18281 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18282
18283 rv = callback.WaitForResult();
18284 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
18285 }
18286}
18287
Bence Békydca6bd92018-01-30 13:43:0618288#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
18289
bncd16676a2016-07-20 16:23:0118290TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0918291 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218292 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918293 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218294 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218295
18296 HttpRequestInfo request;
18297 request.method = "POST";
18298 request.url = GURL("http://www.foo.com/");
18299 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018300 request.traffic_annotation =
18301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218302
danakj1fd259a02016-04-16 03:17:0918303 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618304 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218305 MockWrite data_writes[] = {
18306 MockWrite("POST / HTTP/1.1\r\n"
18307 "Host: www.foo.com\r\n"
18308 "Connection: keep-alive\r\n"
18309 "Content-Length: 3\r\n\r\n"),
18310 MockWrite("foo"),
18311 };
18312
18313 MockRead data_reads[] = {
18314 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18315 MockRead(SYNCHRONOUS, OK),
18316 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118317 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218318 session_deps_.socket_factory->AddSocketDataProvider(&data);
18319
18320 TestCompletionCallback callback;
18321
18322 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018323 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118324 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218325
18326 std::string response_data;
bnc691fda62016-08-12 00:43:1618327 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218328
Ryan Sleevib8d7ea02018-05-07 20:01:0118329 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18330 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218331}
18332
bncd16676a2016-07-20 16:23:0118333TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0918334 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218335 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918336 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218337 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218338
18339 HttpRequestInfo request;
18340 request.method = "POST";
18341 request.url = GURL("http://www.foo.com/");
18342 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018343 request.traffic_annotation =
18344 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218345
danakj1fd259a02016-04-16 03:17:0918346 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618347 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218348 MockWrite data_writes[] = {
18349 MockWrite("POST / HTTP/1.1\r\n"
18350 "Host: www.foo.com\r\n"
18351 "Connection: keep-alive\r\n"
18352 "Content-Length: 3\r\n\r\n"),
18353 MockWrite("foo"),
18354 };
18355
18356 MockRead data_reads[] = {
18357 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
18358 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18359 MockRead(SYNCHRONOUS, OK),
18360 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118361 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218362 session_deps_.socket_factory->AddSocketDataProvider(&data);
18363
18364 TestCompletionCallback callback;
18365
18366 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018367 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118368 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218369
18370 std::string response_data;
bnc691fda62016-08-12 00:43:1618371 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218372
Ryan Sleevib8d7ea02018-05-07 20:01:0118373 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18374 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218375}
18376
bncd16676a2016-07-20 16:23:0118377TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2218378 ChunkedUploadDataStream upload_data_stream(0);
18379
18380 HttpRequestInfo request;
18381 request.method = "POST";
18382 request.url = GURL("http://www.foo.com/");
18383 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018384 request.traffic_annotation =
18385 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218386
danakj1fd259a02016-04-16 03:17:0918387 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618388 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218389 // Send headers successfully, but get an error while sending the body.
18390 MockWrite data_writes[] = {
18391 MockWrite("POST / HTTP/1.1\r\n"
18392 "Host: www.foo.com\r\n"
18393 "Connection: keep-alive\r\n"
18394 "Transfer-Encoding: chunked\r\n\r\n"),
18395 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
18396 };
18397
18398 MockRead data_reads[] = {
18399 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18400 MockRead(SYNCHRONOUS, OK),
18401 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118402 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218403 session_deps_.socket_factory->AddSocketDataProvider(&data);
18404
18405 TestCompletionCallback callback;
18406
18407 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018408 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2218409
18410 base::RunLoop().RunUntilIdle();
18411 upload_data_stream.AppendData("f", 1, false);
18412
18413 base::RunLoop().RunUntilIdle();
18414 upload_data_stream.AppendData("oo", 2, true);
18415
robpercival214763f2016-07-01 23:27:0118416 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218417
18418 std::string response_data;
bnc691fda62016-08-12 00:43:1618419 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218420
Ryan Sleevib8d7ea02018-05-07 20:01:0118421 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18422 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218423}
18424
eustasc7d27da2017-04-06 10:33:2018425void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
18426 const std::string& accept_encoding,
18427 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0318428 const std::string& location,
eustasc7d27da2017-04-06 10:33:2018429 bool should_match) {
18430 HttpRequestInfo request;
18431 request.method = "GET";
18432 request.url = GURL("http://www.foo.com/");
18433 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
18434 accept_encoding);
Ramin Halavatib5e433e2018-02-07 07:41:1018435 request.traffic_annotation =
18436 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2018437
18438 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
18439 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18440 // Send headers successfully, but get an error while sending the body.
18441 MockWrite data_writes[] = {
18442 MockWrite("GET / HTTP/1.1\r\n"
18443 "Host: www.foo.com\r\n"
18444 "Connection: keep-alive\r\n"
18445 "Accept-Encoding: "),
18446 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
18447 };
18448
sky50576f32017-05-01 19:28:0318449 std::string response_code = "200 OK";
18450 std::string extra;
18451 if (!location.empty()) {
18452 response_code = "301 Redirect\r\nLocation: ";
18453 response_code.append(location);
18454 }
18455
eustasc7d27da2017-04-06 10:33:2018456 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0318457 MockRead("HTTP/1.0 "),
18458 MockRead(response_code.data()),
18459 MockRead("\r\nContent-Encoding: "),
18460 MockRead(content_encoding.data()),
18461 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2018462 MockRead(SYNCHRONOUS, OK),
18463 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118464 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2018465 session_deps->socket_factory->AddSocketDataProvider(&data);
18466
18467 TestCompletionCallback callback;
18468
18469 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18470 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18471
18472 rv = callback.WaitForResult();
18473 if (should_match) {
18474 EXPECT_THAT(rv, IsOk());
18475 } else {
18476 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
18477 }
18478}
18479
18480TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0318481 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2018482}
18483
18484TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0318485 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
18486 true);
eustasc7d27da2017-04-06 10:33:2018487}
18488
18489TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
18490 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0318491 "", false);
18492}
18493
18494TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
18495 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
18496 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2018497}
18498
xunjieli96f2a402017-06-05 17:24:2718499TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
18500 ProxyConfig proxy_config;
18501 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18502 proxy_config.set_pac_mandatory(true);
18503 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918504 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918505 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18506 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0418507 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2718508
18509 HttpRequestInfo request;
18510 request.method = "GET";
18511 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018512 request.traffic_annotation =
18513 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718514
18515 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18516 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18517
18518 TestCompletionCallback callback;
18519
18520 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18521 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18522 EXPECT_THAT(callback.WaitForResult(),
18523 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18524}
18525
18526TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
18527 ProxyConfig proxy_config;
18528 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18529 proxy_config.set_pac_mandatory(true);
18530 MockAsyncProxyResolverFactory* proxy_resolver_factory =
18531 new MockAsyncProxyResolverFactory(false);
18532 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918533 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918534 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18535 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5918536 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2718537 HttpRequestInfo request;
18538 request.method = "GET";
18539 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018540 request.traffic_annotation =
18541 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718542
18543 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18544 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18545
18546 TestCompletionCallback callback;
18547 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18548 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18549
18550 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
18551 ERR_FAILED, &resolver);
18552 EXPECT_THAT(callback.WaitForResult(),
18553 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18554}
18555
18556TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5918557 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918558 ProxyResolutionService::CreateFixedFromPacResult(
18559 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718560 session_deps_.enable_quic = false;
18561 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18562
18563 HttpRequestInfo request;
18564 request.method = "GET";
18565 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018566 request.traffic_annotation =
18567 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718568
18569 TestCompletionCallback callback;
18570 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18571 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18572 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18573
18574 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
18575}
18576
Douglas Creager3cb042052018-11-06 23:08:5218577//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1418578// Reporting tests
18579
18580#if BUILDFLAG(ENABLE_REPORTING)
18581class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
18582 protected:
18583 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618584 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1418585 auto test_reporting_context = std::make_unique<TestReportingContext>(
18586 &clock_, &tick_clock_, ReportingPolicy());
18587 test_reporting_context_ = test_reporting_context.get();
18588 session_deps_.reporting_service =
18589 ReportingService::CreateForTesting(std::move(test_reporting_context));
18590 }
18591
18592 TestReportingContext* reporting_context() const {
18593 return test_reporting_context_;
18594 }
18595
18596 void clear_reporting_service() {
18597 session_deps_.reporting_service.reset();
18598 test_reporting_context_ = nullptr;
18599 }
18600
18601 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4218602 void RequestPolicy(CertStatus cert_status = 0) {
18603 HttpRequestInfo request;
18604 request.method = "GET";
18605 request.url = GURL(url_);
18606 request.traffic_annotation =
18607 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18608
Lily Chend3930e72019-03-01 19:31:1118609 MockWrite data_writes[] = {
18610 MockWrite("GET / HTTP/1.1\r\n"
18611 "Host: www.example.org\r\n"
18612 "Connection: keep-alive\r\n\r\n"),
18613 };
Douglas Creager134b52e2018-11-09 18:00:1418614 MockRead data_reads[] = {
18615 MockRead("HTTP/1.0 200 OK\r\n"),
18616 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
18617 "\"endpoints\": [{\"url\": "
18618 "\"https://www.example.org/upload/\"}]}\r\n"),
18619 MockRead("\r\n"),
18620 MockRead("hello world"),
18621 MockRead(SYNCHRONOUS, OK),
18622 };
Douglas Creager134b52e2018-11-09 18:00:1418623
Lily Chenfec60d92019-01-24 01:16:4218624 StaticSocketDataProvider reads(data_reads, data_writes);
18625 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1418626
18627 SSLSocketDataProvider ssl(ASYNC, OK);
18628 if (request.url.SchemeIsCryptographic()) {
18629 ssl.ssl_info.cert =
18630 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18631 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218632 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1418633 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18634 }
18635
Douglas Creager134b52e2018-11-09 18:00:1418636 TestCompletionCallback callback;
18637 auto session = CreateSession(&session_deps_);
18638 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18639 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4218640 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1418641 }
18642
18643 protected:
18644 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1418645
18646 private:
18647 TestReportingContext* test_reporting_context_;
18648};
18649
18650TEST_F(HttpNetworkTransactionReportingTest,
18651 DontProcessReportToHeaderNoService) {
18652 base::HistogramTester histograms;
18653 clear_reporting_service();
18654 RequestPolicy();
18655 histograms.ExpectBucketCount(
18656 ReportingHeaderParser::kHeaderOutcomeHistogram,
18657 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
18658}
18659
18660TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
18661 base::HistogramTester histograms;
18662 url_ = "http://www.example.org/";
18663 RequestPolicy();
18664 histograms.ExpectBucketCount(
18665 ReportingHeaderParser::kHeaderOutcomeHistogram,
18666 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18667}
18668
18669TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
18670 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5418671 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1018672 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5418673 reporting_context()->cache()->GetEndpointForTesting(
18674 url::Origin::Create(GURL("https://www.example.org/")), "nel",
18675 GURL("https://www.example.org/upload/"));
18676 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1418677}
18678
18679TEST_F(HttpNetworkTransactionReportingTest,
18680 DontProcessReportToHeaderInvalidHttps) {
18681 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218682 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18683 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1418684 histograms.ExpectBucketCount(
18685 ReportingHeaderParser::kHeaderOutcomeHistogram,
18686 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
18687}
18688#endif // BUILDFLAG(ENABLE_REPORTING)
18689
18690//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5218691// Network Error Logging tests
18692
18693#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4218694namespace {
18695
18696const char kUserAgent[] = "Mozilla/1.0";
18697const char kReferrer[] = "https://www.referrer.org/";
18698
18699} // namespace
18700
Douglas Creager3cb042052018-11-06 23:08:5218701class HttpNetworkTransactionNetworkErrorLoggingTest
18702 : public HttpNetworkTransactionTest {
18703 protected:
18704 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618705 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5218706 auto network_error_logging_service =
18707 std::make_unique<TestNetworkErrorLoggingService>();
18708 test_network_error_logging_service_ = network_error_logging_service.get();
18709 session_deps_.network_error_logging_service =
18710 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4218711
18712 extra_headers_.SetHeader("User-Agent", kUserAgent);
18713 extra_headers_.SetHeader("Referer", kReferrer);
18714
18715 request_.method = "GET";
18716 request_.url = GURL(url_);
18717 request_.extra_headers = extra_headers_;
18718 request_.reporting_upload_depth = reporting_upload_depth_;
18719 request_.traffic_annotation =
18720 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5218721 }
18722
18723 TestNetworkErrorLoggingService* network_error_logging_service() const {
18724 return test_network_error_logging_service_;
18725 }
18726
18727 void clear_network_error_logging_service() {
18728 session_deps_.network_error_logging_service.reset();
18729 test_network_error_logging_service_ = nullptr;
18730 }
18731
18732 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4218733 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3618734 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318735 MockWrite data_writes[] = {
18736 MockWrite("GET / HTTP/1.1\r\n"
18737 "Host: www.example.org\r\n"
18738 "Connection: keep-alive\r\n"),
18739 MockWrite(ASYNC, extra_header_string.data(),
18740 extra_header_string.size()),
18741 };
Lily Chend3930e72019-03-01 19:31:1118742 MockRead data_reads[] = {
18743 MockRead("HTTP/1.0 200 OK\r\n"),
18744 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18745 MockRead("\r\n"),
18746 MockRead("hello world"),
18747 MockRead(SYNCHRONOUS, OK),
18748 };
Douglas Creager3cb042052018-11-06 23:08:5218749
Lily Chenfec60d92019-01-24 01:16:4218750 StaticSocketDataProvider reads(data_reads, data_writes);
18751 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5218752
18753 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4218754 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5218755 ssl.ssl_info.cert =
18756 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18757 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218758 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5218759 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18760 }
18761
Douglas Creager3cb042052018-11-06 23:08:5218762 TestCompletionCallback callback;
18763 auto session = CreateSession(&session_deps_);
18764 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4218765 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
18766 EXPECT_THAT(callback.GetResult(rv), IsOk());
18767
18768 std::string response_data;
18769 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
18770 EXPECT_EQ("hello world", response_data);
18771 }
18772
18773 void CheckReport(size_t index,
18774 int status_code,
18775 int error_type,
18776 IPAddress server_ip = IPAddress::IPv4Localhost()) {
18777 ASSERT_LT(index, network_error_logging_service()->errors().size());
18778
18779 const NetworkErrorLoggingService::RequestDetails& error =
18780 network_error_logging_service()->errors()[index];
18781 EXPECT_EQ(url_, error.uri);
18782 EXPECT_EQ(kReferrer, error.referrer);
18783 EXPECT_EQ(kUserAgent, error.user_agent);
18784 EXPECT_EQ(server_ip, error.server_ip);
18785 EXPECT_EQ("http/1.1", error.protocol);
18786 EXPECT_EQ("GET", error.method);
18787 EXPECT_EQ(status_code, error.status_code);
18788 EXPECT_EQ(error_type, error.type);
18789 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5218790 }
18791
18792 protected:
18793 std::string url_ = "https://www.example.org/";
18794 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4218795 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3618796 HttpRequestHeaders extra_headers_;
18797 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5218798
18799 private:
18800 TestNetworkErrorLoggingService* test_network_error_logging_service_;
18801};
18802
18803TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18804 DontProcessNelHeaderNoService) {
18805 base::HistogramTester histograms;
18806 clear_network_error_logging_service();
18807 RequestPolicy();
18808 histograms.ExpectBucketCount(
18809 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18810 NetworkErrorLoggingService::HeaderOutcome::
18811 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
18812 1);
18813}
18814
18815TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18816 DontProcessNelHeaderHttp) {
18817 base::HistogramTester histograms;
18818 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4218819 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5218820 RequestPolicy();
18821 histograms.ExpectBucketCount(
18822 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18823 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18824}
18825
Lily Chen90ae93cc2019-02-14 01:15:3918826// Don't set NEL policies received on a proxied connection.
18827TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18828 DontProcessNelHeaderProxy) {
18829 session_deps_.proxy_resolution_service =
18830 ProxyResolutionService::CreateFixedFromPacResult(
18831 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
18832 BoundTestNetLog log;
18833 session_deps_.net_log = log.bound().net_log();
18834 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18835
18836 HttpRequestInfo request;
18837 request.method = "GET";
18838 request.url = GURL("https://www.example.org/");
18839 request.traffic_annotation =
18840 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18841
18842 // Since we have proxy, should try to establish tunnel.
18843 MockWrite data_writes1[] = {
18844 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18845 "Host: www.example.org:443\r\n"
18846 "Proxy-Connection: keep-alive\r\n\r\n"),
18847
18848 MockWrite("GET / HTTP/1.1\r\n"
18849 "Host: www.example.org\r\n"
18850 "Connection: keep-alive\r\n\r\n"),
18851 };
18852
18853 MockRead data_reads1[] = {
18854 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18855
18856 MockRead("HTTP/1.1 200 OK\r\n"),
18857 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18858 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18859 MockRead("Content-Length: 100\r\n\r\n"),
18860 MockRead(SYNCHRONOUS, OK),
18861 };
18862
18863 StaticSocketDataProvider data1(data_reads1, data_writes1);
18864 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18865 SSLSocketDataProvider ssl(ASYNC, OK);
18866 ssl.ssl_info.cert =
18867 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18868 ASSERT_TRUE(ssl.ssl_info.cert);
18869 ssl.ssl_info.cert_status = 0;
18870 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18871
18872 TestCompletionCallback callback1;
18873 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18874
18875 int rv = trans.Start(&request, callback1.callback(), log.bound());
18876 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18877
18878 rv = callback1.WaitForResult();
18879 EXPECT_THAT(rv, IsOk());
18880
18881 const HttpResponseInfo* response = trans.GetResponseInfo();
18882 ASSERT_TRUE(response);
18883 EXPECT_EQ(200, response->headers->response_code());
18884 EXPECT_TRUE(response->was_fetched_via_proxy);
18885
18886 // No NEL header was set.
18887 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
18888}
18889
Douglas Creager3cb042052018-11-06 23:08:5218890TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
18891 RequestPolicy();
18892 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
18893 const auto& header = network_error_logging_service()->headers()[0];
18894 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
18895 header.origin);
18896 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
18897 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
18898}
18899
18900TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18901 DontProcessNelHeaderInvalidHttps) {
18902 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218903 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18904 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5218905 histograms.ExpectBucketCount(
18906 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18907 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
18908 1);
18909}
Douglas Creageref5eecdc2018-11-09 20:50:3618910
Lily Chenfec60d92019-01-24 01:16:4218911TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3618912 RequestPolicy();
18913 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4218914 CheckReport(0 /* index */, 200 /* status_code */, OK);
18915}
18916
18917TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18918 CreateReportErrorAfterStart) {
18919 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18920 auto trans =
18921 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18922
18923 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
18924 StaticSocketDataProvider data;
18925 data.set_connect_data(mock_connect);
18926 session_deps_.socket_factory->AddSocketDataProvider(&data);
18927
18928 TestCompletionCallback callback;
18929
18930 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18931 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18932
18933 trans.reset();
18934
18935 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18936 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18937 IPAddress() /* server_ip */);
18938}
18939
18940// Same as above except the error is ASYNC
18941TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18942 CreateReportErrorAfterStartAsync) {
18943 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18944 auto trans =
18945 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18946
18947 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
18948 StaticSocketDataProvider data;
18949 data.set_connect_data(mock_connect);
18950 session_deps_.socket_factory->AddSocketDataProvider(&data);
18951
18952 TestCompletionCallback callback;
18953
18954 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18955 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18956
18957 trans.reset();
18958
18959 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18960 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18961 IPAddress() /* server_ip */);
18962}
18963
18964TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18965 CreateReportReadBodyError) {
18966 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318967 MockWrite data_writes[] = {
18968 MockWrite("GET / HTTP/1.1\r\n"
18969 "Host: www.example.org\r\n"
18970 "Connection: keep-alive\r\n"),
18971 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18972 };
Lily Chend3930e72019-03-01 19:31:1118973 MockRead data_reads[] = {
18974 MockRead("HTTP/1.0 200 OK\r\n"),
18975 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18976 MockRead("hello world"),
18977 MockRead(SYNCHRONOUS, OK),
18978 };
Lily Chenfec60d92019-01-24 01:16:4218979
18980 StaticSocketDataProvider reads(data_reads, data_writes);
18981 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18982
18983 SSLSocketDataProvider ssl(ASYNC, OK);
18984 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18985
18986 // Log start time
18987 base::TimeTicks start_time = base::TimeTicks::Now();
18988
18989 TestCompletionCallback callback;
18990 auto session = CreateSession(&session_deps_);
18991 auto trans =
18992 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18993 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18994 EXPECT_THAT(callback.GetResult(rv), IsOk());
18995
18996 const HttpResponseInfo* response = trans->GetResponseInfo();
18997 ASSERT_TRUE(response);
18998
18999 EXPECT_TRUE(response->headers);
19000 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19001
19002 std::string response_data;
19003 rv = ReadTransaction(trans.get(), &response_data);
19004 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19005
19006 trans.reset();
19007
19008 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19009
19010 CheckReport(0 /* index */, 200 /* status_code */,
19011 ERR_CONTENT_LENGTH_MISMATCH);
19012 const NetworkErrorLoggingService::RequestDetails& error =
19013 network_error_logging_service()->errors()[0];
19014 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19015}
19016
19017// Same as above except the final read is ASYNC.
19018TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19019 CreateReportReadBodyErrorAsync) {
19020 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319021 MockWrite data_writes[] = {
19022 MockWrite("GET / HTTP/1.1\r\n"
19023 "Host: www.example.org\r\n"
19024 "Connection: keep-alive\r\n"),
19025 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19026 };
Lily Chend3930e72019-03-01 19:31:1119027 MockRead data_reads[] = {
19028 MockRead("HTTP/1.0 200 OK\r\n"),
19029 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
19030 MockRead("hello world"),
19031 MockRead(ASYNC, OK),
19032 };
Lily Chenfec60d92019-01-24 01:16:4219033
19034 StaticSocketDataProvider reads(data_reads, data_writes);
19035 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19036
19037 SSLSocketDataProvider ssl(ASYNC, OK);
19038 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19039
19040 // Log start time
19041 base::TimeTicks start_time = base::TimeTicks::Now();
19042
19043 TestCompletionCallback callback;
19044 auto session = CreateSession(&session_deps_);
19045 auto trans =
19046 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19047 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19048 EXPECT_THAT(callback.GetResult(rv), IsOk());
19049
19050 const HttpResponseInfo* response = trans->GetResponseInfo();
19051 ASSERT_TRUE(response);
19052
19053 EXPECT_TRUE(response->headers);
19054 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19055
19056 std::string response_data;
19057 rv = ReadTransaction(trans.get(), &response_data);
19058 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19059
19060 trans.reset();
19061
19062 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19063
19064 CheckReport(0 /* index */, 200 /* status_code */,
19065 ERR_CONTENT_LENGTH_MISMATCH);
19066 const NetworkErrorLoggingService::RequestDetails& error =
19067 network_error_logging_service()->errors()[0];
19068 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19069}
19070
19071TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19072 CreateReportRestartWithAuth) {
19073 std::string extra_header_string = extra_headers_.ToString();
19074 static const base::TimeDelta kSleepDuration =
19075 base::TimeDelta::FromMilliseconds(10);
19076
19077 MockWrite data_writes1[] = {
19078 MockWrite("GET / HTTP/1.1\r\n"
19079 "Host: www.example.org\r\n"
19080 "Connection: keep-alive\r\n"),
19081 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19082 };
19083
19084 MockRead data_reads1[] = {
19085 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19086 // Give a couple authenticate options (only the middle one is actually
19087 // supported).
19088 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19089 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19090 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19092 // Large content-length -- won't matter, as connection will be reset.
19093 MockRead("Content-Length: 10000\r\n\r\n"),
19094 MockRead(SYNCHRONOUS, ERR_FAILED),
19095 };
19096
19097 // After calling trans->RestartWithAuth(), this is the request we should
19098 // be issuing -- the final header line contains the credentials.
19099 MockWrite data_writes2[] = {
19100 MockWrite("GET / HTTP/1.1\r\n"
19101 "Host: www.example.org\r\n"
19102 "Connection: keep-alive\r\n"
19103 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19104 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19105 };
19106
19107 // Lastly, the server responds with the actual content.
19108 MockRead data_reads2[] = {
19109 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19110 MockRead("hello world"),
19111 MockRead(SYNCHRONOUS, OK),
19112 };
19113
19114 StaticSocketDataProvider data1(data_reads1, data_writes1);
19115 StaticSocketDataProvider data2(data_reads2, data_writes2);
19116 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19117 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19118
19119 SSLSocketDataProvider ssl1(ASYNC, OK);
19120 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19121 SSLSocketDataProvider ssl2(ASYNC, OK);
19122 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19123
19124 base::TimeTicks start_time = base::TimeTicks::Now();
19125 base::TimeTicks restart_time;
19126
19127 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19128 auto trans =
19129 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19130
19131 TestCompletionCallback callback1;
19132
19133 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19134 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19135
19136 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19137
19138 TestCompletionCallback callback2;
19139
19140 // Wait 10 ms then restart with auth
19141 FastForwardBy(kSleepDuration);
19142 restart_time = base::TimeTicks::Now();
19143 rv =
19144 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19145 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19146
19147 std::string response_data;
19148 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19149 EXPECT_EQ("hello world", response_data);
19150
19151 trans.reset();
19152
19153 // One 401 report for the auth challenge, then a 200 report for the successful
19154 // retry. Note that we don't report the error draining the body, as the first
19155 // request already generated a report for the auth challenge.
19156 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19157
19158 // Check error report contents
19159 CheckReport(0 /* index */, 401 /* status_code */, OK);
19160 CheckReport(1 /* index */, 200 /* status_code */, OK);
19161
19162 const NetworkErrorLoggingService::RequestDetails& error1 =
19163 network_error_logging_service()->errors()[0];
19164 const NetworkErrorLoggingService::RequestDetails& error2 =
19165 network_error_logging_service()->errors()[1];
19166
19167 // Sanity-check elapsed time values
19168 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19169 // Check that the start time is refreshed when restarting with auth.
19170 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19171}
19172
19173// Same as above, except draining the body before restarting fails
19174// asynchronously.
19175TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19176 CreateReportRestartWithAuthAsync) {
19177 std::string extra_header_string = extra_headers_.ToString();
19178 static const base::TimeDelta kSleepDuration =
19179 base::TimeDelta::FromMilliseconds(10);
19180
19181 MockWrite data_writes1[] = {
19182 MockWrite("GET / HTTP/1.1\r\n"
19183 "Host: www.example.org\r\n"
19184 "Connection: keep-alive\r\n"),
19185 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19186 };
19187
19188 MockRead data_reads1[] = {
19189 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19190 // Give a couple authenticate options (only the middle one is actually
19191 // supported).
19192 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19193 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19194 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19195 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19196 // Large content-length -- won't matter, as connection will be reset.
19197 MockRead("Content-Length: 10000\r\n\r\n"),
19198 MockRead(ASYNC, ERR_FAILED),
19199 };
19200
19201 // After calling trans->RestartWithAuth(), this is the request we should
19202 // be issuing -- the final header line contains the credentials.
19203 MockWrite data_writes2[] = {
19204 MockWrite("GET / HTTP/1.1\r\n"
19205 "Host: www.example.org\r\n"
19206 "Connection: keep-alive\r\n"
19207 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19208 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19209 };
19210
19211 // Lastly, the server responds with the actual content.
19212 MockRead data_reads2[] = {
19213 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19214 MockRead("hello world"),
19215 MockRead(SYNCHRONOUS, OK),
19216 };
19217
19218 StaticSocketDataProvider data1(data_reads1, data_writes1);
19219 StaticSocketDataProvider data2(data_reads2, data_writes2);
19220 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19221 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19222
19223 SSLSocketDataProvider ssl1(ASYNC, OK);
19224 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19225 SSLSocketDataProvider ssl2(ASYNC, OK);
19226 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19227
19228 base::TimeTicks start_time = base::TimeTicks::Now();
19229 base::TimeTicks restart_time;
19230
19231 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19232 auto trans =
19233 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19234
19235 TestCompletionCallback callback1;
19236
19237 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19238 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19239
19240 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19241
19242 TestCompletionCallback callback2;
19243
19244 // Wait 10 ms then restart with auth
19245 FastForwardBy(kSleepDuration);
19246 restart_time = base::TimeTicks::Now();
19247 rv =
19248 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19249 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19250
19251 std::string response_data;
19252 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19253 EXPECT_EQ("hello world", response_data);
19254
19255 trans.reset();
19256
19257 // One 401 report for the auth challenge, then a 200 report for the successful
19258 // retry. Note that we don't report the error draining the body, as the first
19259 // request already generated a report for the auth challenge.
19260 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19261
19262 // Check error report contents
19263 CheckReport(0 /* index */, 401 /* status_code */, OK);
19264 CheckReport(1 /* index */, 200 /* status_code */, OK);
19265
19266 const NetworkErrorLoggingService::RequestDetails& error1 =
19267 network_error_logging_service()->errors()[0];
19268 const NetworkErrorLoggingService::RequestDetails& error2 =
19269 network_error_logging_service()->errors()[1];
19270
19271 // Sanity-check elapsed time values
19272 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19273 // Check that the start time is refreshed when restarting with auth.
19274 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19275}
19276
19277TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19278 CreateReportRetryKeepAliveConnectionReset) {
19279 std::string extra_header_string = extra_headers_.ToString();
19280 MockWrite data_writes1[] = {
19281 MockWrite("GET / HTTP/1.1\r\n"
19282 "Host: www.example.org\r\n"
19283 "Connection: keep-alive\r\n"),
19284 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19285 MockWrite("GET / HTTP/1.1\r\n"
19286 "Host: www.example.org\r\n"
19287 "Connection: keep-alive\r\n"),
19288 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19289 };
19290
19291 MockRead data_reads1[] = {
19292 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19293 MockRead("hello"),
19294 // Connection is reset
19295 MockRead(ASYNC, ERR_CONNECTION_RESET),
19296 };
19297
19298 // Successful retry
19299 MockRead data_reads2[] = {
19300 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19301 MockRead("world"),
19302 MockRead(ASYNC, OK),
19303 };
19304
19305 StaticSocketDataProvider data1(data_reads1, data_writes1);
19306 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19307 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19308 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19309
19310 SSLSocketDataProvider ssl1(ASYNC, OK);
19311 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19312 SSLSocketDataProvider ssl2(ASYNC, OK);
19313 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19314
19315 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19316 auto trans1 =
19317 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19318
19319 TestCompletionCallback callback1;
19320
19321 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19322 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19323
19324 std::string response_data;
19325 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19326 EXPECT_EQ("hello", response_data);
19327
19328 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19329
19330 auto trans2 =
19331 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19332
19333 TestCompletionCallback callback2;
19334
19335 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19336 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19337
19338 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19339 EXPECT_EQ("world", response_data);
19340
19341 trans1.reset();
19342 trans2.reset();
19343
19344 // One OK report from first request, then a ERR_CONNECTION_RESET report from
19345 // the second request, then an OK report from the successful retry.
19346 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19347
19348 // Check error report contents
19349 CheckReport(0 /* index */, 200 /* status_code */, OK);
19350 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
19351 CheckReport(2 /* index */, 200 /* status_code */, OK);
19352}
19353
19354TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19355 CreateReportRetryKeepAlive408) {
19356 std::string extra_header_string = extra_headers_.ToString();
19357 MockWrite data_writes1[] = {
19358 MockWrite("GET / HTTP/1.1\r\n"
19359 "Host: www.example.org\r\n"
19360 "Connection: keep-alive\r\n"),
19361 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19362 MockWrite("GET / HTTP/1.1\r\n"
19363 "Host: www.example.org\r\n"
19364 "Connection: keep-alive\r\n"),
19365 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19366 };
19367
19368 MockRead data_reads1[] = {
19369 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19370 MockRead("hello"),
19371 // 408 Request Timeout
19372 MockRead(SYNCHRONOUS,
19373 "HTTP/1.1 408 Request Timeout\r\n"
19374 "Connection: Keep-Alive\r\n"
19375 "Content-Length: 6\r\n\r\n"
19376 "Pickle"),
19377 };
19378
19379 // Successful retry
19380 MockRead data_reads2[] = {
19381 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19382 MockRead("world"),
19383 MockRead(ASYNC, OK),
19384 };
19385
19386 StaticSocketDataProvider data1(data_reads1, data_writes1);
19387 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19388 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19389 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19390
19391 SSLSocketDataProvider ssl1(ASYNC, OK);
19392 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19393 SSLSocketDataProvider ssl2(ASYNC, OK);
19394 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19395
19396 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19397 auto trans1 =
19398 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19399
19400 TestCompletionCallback callback1;
19401
19402 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19403 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19404
19405 std::string response_data;
19406 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19407 EXPECT_EQ("hello", response_data);
19408
19409 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19410
19411 auto trans2 =
19412 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19413
19414 TestCompletionCallback callback2;
19415
19416 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19417 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19418
19419 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19420 EXPECT_EQ("world", response_data);
19421
19422 trans1.reset();
19423 trans2.reset();
19424
19425 // One 200 report from first request, then a 408 report from
19426 // the second request, then a 200 report from the successful retry.
19427 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19428
19429 // Check error report contents
19430 CheckReport(0 /* index */, 200 /* status_code */, OK);
19431 CheckReport(1 /* index */, 408 /* status_code */, OK);
19432 CheckReport(2 /* index */, 200 /* status_code */, OK);
19433}
19434
19435TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19436 CreateReportRetry421WithoutConnectionPooling) {
19437 // Two hosts resolve to the same IP address.
19438 const std::string ip_addr = "1.2.3.4";
19439 IPAddress ip;
19440 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
19441 IPEndPoint peer_addr = IPEndPoint(ip, 443);
19442
19443 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19444 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
19445 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
19446
19447 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19448
19449 // Two requests on the first connection.
19450 spdy::SpdySerializedFrame req1(
19451 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19452 spdy_util_.UpdateWithStreamDestruction(1);
19453 spdy::SpdySerializedFrame req2(
19454 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
19455 spdy::SpdySerializedFrame rst(
19456 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
19457 MockWrite writes1[] = {
19458 CreateMockWrite(req1, 0),
19459 CreateMockWrite(req2, 3),
19460 CreateMockWrite(rst, 6),
19461 };
19462
19463 // The first one succeeds, the second gets error 421 Misdirected Request.
19464 spdy::SpdySerializedFrame resp1(
19465 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19466 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
19467 spdy::SpdyHeaderBlock response_headers;
19468 response_headers[spdy::kHttp2StatusHeader] = "421";
19469 spdy::SpdySerializedFrame resp2(
19470 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
19471 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
19472 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
19473
19474 MockConnect connect1(ASYNC, OK, peer_addr);
19475 SequencedSocketData data1(connect1, reads1, writes1);
19476 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19477
19478 AddSSLSocketData();
19479
19480 // Retry the second request on a second connection.
19481 SpdyTestUtil spdy_util2;
19482 spdy::SpdySerializedFrame req3(
19483 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
19484 MockWrite writes2[] = {
19485 CreateMockWrite(req3, 0),
19486 };
19487
19488 spdy::SpdySerializedFrame resp3(
19489 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
19490 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
19491 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
19492 MockRead(ASYNC, 0, 3)};
19493
19494 MockConnect connect2(ASYNC, OK, peer_addr);
19495 SequencedSocketData data2(connect2, reads2, writes2);
19496 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19497
19498 AddSSLSocketData();
19499
19500 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3319501 int rv = session_deps_.host_resolver->LoadIntoCache(
19502 HostPortPair("mail.example.com", 443), base::nullopt);
19503 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4219504
19505 HttpRequestInfo request1;
19506 request1.method = "GET";
19507 request1.url = GURL("https://www.example.org/");
19508 request1.load_flags = 0;
19509 request1.traffic_annotation =
19510 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19511 auto trans1 =
19512 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19513
Eric Orthf4db66a2019-02-19 21:35:3319514 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219515 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
19516 EXPECT_THAT(callback.GetResult(rv), IsOk());
19517
19518 const HttpResponseInfo* response = trans1->GetResponseInfo();
19519 ASSERT_TRUE(response);
19520 ASSERT_TRUE(response->headers);
19521 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19522 EXPECT_TRUE(response->was_fetched_via_spdy);
19523 EXPECT_TRUE(response->was_alpn_negotiated);
19524 std::string response_data;
19525 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19526 EXPECT_EQ("hello!", response_data);
19527
19528 trans1.reset();
19529
19530 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19531
19532 HttpRequestInfo request2;
19533 request2.method = "GET";
19534 request2.url = GURL("https://mail.example.org/");
19535 request2.load_flags = 0;
19536 request2.traffic_annotation =
19537 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19538 auto trans2 =
19539 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19540
19541 BoundTestNetLog log;
19542 rv = trans2->Start(&request2, callback.callback(), log.bound());
19543 EXPECT_THAT(callback.GetResult(rv), IsOk());
19544
19545 response = trans2->GetResponseInfo();
19546 ASSERT_TRUE(response);
19547 ASSERT_TRUE(response->headers);
19548 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19549 EXPECT_TRUE(response->was_fetched_via_spdy);
19550 EXPECT_TRUE(response->was_alpn_negotiated);
19551 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19552 EXPECT_EQ("hello!", response_data);
19553
19554 trans2.reset();
19555
19556 // One 200 report from the first request, then a 421 report from the
19557 // second request, then a 200 report from the successful retry.
19558 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19559
19560 // Check error report contents
19561 const NetworkErrorLoggingService::RequestDetails& error1 =
19562 network_error_logging_service()->errors()[0];
19563 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
19564 EXPECT_TRUE(error1.referrer.is_empty());
19565 EXPECT_EQ("", error1.user_agent);
19566 EXPECT_EQ(ip, error1.server_ip);
19567 EXPECT_EQ("h2", error1.protocol);
19568 EXPECT_EQ("GET", error1.method);
19569 EXPECT_EQ(200, error1.status_code);
19570 EXPECT_EQ(OK, error1.type);
19571 EXPECT_EQ(0, error1.reporting_upload_depth);
19572
19573 const NetworkErrorLoggingService::RequestDetails& error2 =
19574 network_error_logging_service()->errors()[1];
19575 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
19576 EXPECT_TRUE(error2.referrer.is_empty());
19577 EXPECT_EQ("", error2.user_agent);
19578 EXPECT_EQ(ip, error2.server_ip);
19579 EXPECT_EQ("h2", error2.protocol);
19580 EXPECT_EQ("GET", error2.method);
19581 EXPECT_EQ(421, error2.status_code);
19582 EXPECT_EQ(OK, error2.type);
19583 EXPECT_EQ(0, error2.reporting_upload_depth);
19584
19585 const NetworkErrorLoggingService::RequestDetails& error3 =
19586 network_error_logging_service()->errors()[2];
19587 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
19588 EXPECT_TRUE(error3.referrer.is_empty());
19589 EXPECT_EQ("", error3.user_agent);
19590 EXPECT_EQ(ip, error3.server_ip);
19591 EXPECT_EQ("h2", error3.protocol);
19592 EXPECT_EQ("GET", error3.method);
19593 EXPECT_EQ(200, error3.status_code);
19594 EXPECT_EQ(OK, error3.type);
19595 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3619596}
19597
Lily Chend3930e72019-03-01 19:31:1119598TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19599 CreateReportCancelAfterStart) {
19600 StaticSocketDataProvider data;
19601 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
19602 session_deps_.socket_factory->AddSocketDataProvider(&data);
19603
19604 TestCompletionCallback callback;
19605 auto session = CreateSession(&session_deps_);
19606 auto trans =
19607 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19608 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19609 EXPECT_EQ(rv, ERR_IO_PENDING);
19610
19611 // Cancel after start.
19612 trans.reset();
19613
19614 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19615 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
19616 IPAddress() /* server_ip */);
19617}
19618
19619TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19620 CreateReportCancelBeforeReadingBody) {
19621 std::string extra_header_string = extra_headers_.ToString();
19622 MockWrite data_writes[] = {
19623 MockWrite("GET / HTTP/1.1\r\n"
19624 "Host: www.example.org\r\n"
19625 "Connection: keep-alive\r\n"),
19626 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19627 };
19628 MockRead data_reads[] = {
19629 MockRead("HTTP/1.0 200 OK\r\n"),
19630 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
19631 };
19632
19633 StaticSocketDataProvider data(data_reads, data_writes);
19634 session_deps_.socket_factory->AddSocketDataProvider(&data);
19635
19636 SSLSocketDataProvider ssl(ASYNC, OK);
19637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19638
19639 TestCompletionCallback callback;
19640 auto session = CreateSession(&session_deps_);
19641 auto trans =
19642 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19643 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19644 EXPECT_THAT(callback.GetResult(rv), IsOk());
19645
19646 const HttpResponseInfo* response = trans->GetResponseInfo();
19647 ASSERT_TRUE(response);
19648
19649 EXPECT_TRUE(response->headers);
19650 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19651
19652 // Cancel before reading the body.
19653 trans.reset();
19654
19655 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19656 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
19657}
19658
Lily Chen00196ab62018-12-04 19:52:2919659TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
19660 base::HistogramTester histograms;
19661 RequestPolicy();
19662 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19663 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19664
19665 // Make HTTP request
19666 std::string extra_header_string = extra_headers_.ToString();
19667 MockRead data_reads[] = {
19668 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19669 MockRead("hello world"),
19670 MockRead(SYNCHRONOUS, OK),
19671 };
19672 MockWrite data_writes[] = {
19673 MockWrite("GET / HTTP/1.1\r\n"
19674 "Host: www.example.org\r\n"
19675 "Connection: keep-alive\r\n"),
19676 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19677 };
19678
Lily Chend3930e72019-03-01 19:31:1119679 StaticSocketDataProvider data(data_reads, data_writes);
19680 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2919681
Lily Chenfec60d92019-01-24 01:16:4219682 // Insecure url
19683 url_ = "http://www.example.org/";
19684 request_.url = GURL(url_);
19685
Lily Chen00196ab62018-12-04 19:52:2919686 TestCompletionCallback callback;
19687 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4219688 auto trans =
19689 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19690 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19691 EXPECT_THAT(callback.GetResult(rv), IsOk());
19692
19693 std::string response_data;
19694 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19695 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2919696
19697 // Insecure request does not generate a report
19698 histograms.ExpectBucketCount(
19699 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519700 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919701
19702 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19703}
19704
19705TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19706 DontCreateReportHttpError) {
19707 base::HistogramTester histograms;
19708 RequestPolicy();
19709 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19710 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19711
19712 // Make HTTP request that fails
19713 MockRead data_reads[] = {
19714 MockRead("hello world"),
19715 MockRead(SYNCHRONOUS, OK),
19716 };
19717
19718 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19719 session_deps_.socket_factory->AddSocketDataProvider(&data);
19720
Lily Chenfec60d92019-01-24 01:16:4219721 url_ = "http://www.originwithoutpolicy.com:2000/";
19722 request_.url = GURL(url_);
19723
Lily Chen00196ab62018-12-04 19:52:2919724 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19725
Lily Chen00196ab62018-12-04 19:52:2919726 auto trans =
19727 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2919728 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219729 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2919730 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
19731
19732 // Insecure request does not generate a report, regardless of existence of a
19733 // policy for the origin.
19734 histograms.ExpectBucketCount(
19735 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519736 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919737
19738 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19739}
19740
Lily Chen90ae93cc2019-02-14 01:15:3919741// Don't report on proxy auth challenges, don't report if connecting through a
19742// proxy.
19743TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
19744 HttpRequestInfo request;
19745 request.method = "GET";
19746 request.url = GURL("https://www.example.org/");
19747 request.traffic_annotation =
19748 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19749
19750 // Configure against proxy server "myproxy:70".
19751 session_deps_.proxy_resolution_service =
19752 ProxyResolutionService::CreateFixedFromPacResult(
19753 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19754 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19755
19756 // Since we have proxy, should try to establish tunnel.
19757 MockWrite data_writes1[] = {
19758 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19759 "Host: www.example.org:443\r\n"
19760 "Proxy-Connection: keep-alive\r\n\r\n"),
19761 };
19762
19763 // The proxy responds to the connect with a 407, using a non-persistent
19764 // connection.
19765 MockRead data_reads1[] = {
19766 // No credentials.
19767 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
19768 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19769 MockRead("Proxy-Connection: close\r\n\r\n"),
19770 };
19771
19772 MockWrite data_writes2[] = {
19773 // After calling trans->RestartWithAuth(), this is the request we should
19774 // be issuing -- the final header line contains the credentials.
19775 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19776 "Host: www.example.org:443\r\n"
19777 "Proxy-Connection: keep-alive\r\n"
19778 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
19779
19780 MockWrite("GET / HTTP/1.1\r\n"
19781 "Host: www.example.org\r\n"
19782 "Connection: keep-alive\r\n\r\n"),
19783 };
19784
19785 MockRead data_reads2[] = {
19786 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19787
19788 MockRead("HTTP/1.1 200 OK\r\n"),
19789 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19790 MockRead("Content-Length: 5\r\n\r\n"),
19791 MockRead(SYNCHRONOUS, "hello"),
19792 };
19793
19794 StaticSocketDataProvider data1(data_reads1, data_writes1);
19795 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19796 StaticSocketDataProvider data2(data_reads2, data_writes2);
19797 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19798 SSLSocketDataProvider ssl(ASYNC, OK);
19799 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19800
19801 TestCompletionCallback callback1;
19802
19803 auto trans =
19804 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19805
19806 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
19807 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19808
19809 const HttpResponseInfo* response = trans->GetResponseInfo();
19810 EXPECT_EQ(407, response->headers->response_code());
19811
19812 std::string response_data;
19813 rv = ReadTransaction(trans.get(), &response_data);
19814 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
19815
19816 // No NEL report is generated for the 407.
19817 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19818
19819 TestCompletionCallback callback2;
19820
19821 rv =
19822 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19823 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19824
19825 response = trans->GetResponseInfo();
19826 EXPECT_EQ(200, response->headers->response_code());
19827
19828 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19829 EXPECT_EQ("hello", response_data);
19830
19831 trans.reset();
19832
19833 // No NEL report is generated because we are behind a proxy.
19834 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19835}
19836
Douglas Creageref5eecdc2018-11-09 20:50:3619837TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19838 ReportContainsUploadDepth) {
19839 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4219840 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3619841 RequestPolicy();
19842 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219843 const NetworkErrorLoggingService::RequestDetails& error =
19844 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3619845 EXPECT_EQ(7, error.reporting_upload_depth);
19846}
19847
Lily Chenfec60d92019-01-24 01:16:4219848TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
19849 std::string extra_header_string = extra_headers_.ToString();
19850 static const base::TimeDelta kSleepDuration =
19851 base::TimeDelta::FromMilliseconds(10);
19852
19853 std::vector<MockWrite> data_writes = {
19854 MockWrite(ASYNC, 0,
19855 "GET / HTTP/1.1\r\n"
19856 "Host: www.example.org\r\n"
19857 "Connection: keep-alive\r\n"),
19858 MockWrite(ASYNC, 1, extra_header_string.data()),
19859 };
19860
19861 std::vector<MockRead> data_reads = {
19862 // Write one byte of the status line, followed by a pause.
19863 MockRead(ASYNC, 2, "H"),
19864 MockRead(ASYNC, ERR_IO_PENDING, 3),
19865 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
19866 MockRead(ASYNC, 5, "hello world"),
19867 MockRead(SYNCHRONOUS, OK, 6),
19868 };
19869
19870 SequencedSocketData data(data_reads, data_writes);
19871 session_deps_.socket_factory->AddSocketDataProvider(&data);
19872
19873 SSLSocketDataProvider ssl(ASYNC, OK);
19874 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19875
19876 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19877
19878 auto trans =
19879 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19880
19881 TestCompletionCallback callback;
19882
19883 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19884 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19885
19886 data.RunUntilPaused();
19887 ASSERT_TRUE(data.IsPaused());
19888 FastForwardBy(kSleepDuration);
19889 data.Resume();
19890
19891 EXPECT_THAT(callback.GetResult(rv), IsOk());
19892
19893 std::string response_data;
19894 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19895 EXPECT_EQ("hello world", response_data);
19896
19897 trans.reset();
19898
Douglas Creageref5eecdc2018-11-09 20:50:3619899 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219900
19901 CheckReport(0 /* index */, 200 /* status_code */, OK);
19902
19903 const NetworkErrorLoggingService::RequestDetails& error =
19904 network_error_logging_service()->errors()[0];
19905
19906 // Sanity-check elapsed time in error report
19907 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3619908}
Lily Chenfec60d92019-01-24 01:16:4219909
Douglas Creager3cb042052018-11-06 23:08:5219910#endif // BUILDFLAG(ENABLE_REPORTING)
19911
Batalov Vladislava4e97a502019-04-11 15:35:2319912TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
19913 HttpRequestInfo request;
19914 request.method = "GET";
19915 request.url = GURL("http://example.org/");
19916
19917 request.load_flags = LOAD_ONLY_FROM_CACHE;
19918
19919 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19920 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19921 TestCompletionCallback callback1;
19922 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
19923
19924 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
19925}
19926
Steven Valdez1c1859172019-04-10 15:33:2819927TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
19928 HttpRequestInfo request;
19929 request.method = "GET";
19930 request.url = GURL("https://www.example.org/");
19931 request.traffic_annotation =
19932 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19933
19934 MockWrite data_writes[] = {
19935 MockWrite("GET / HTTP/1.1\r\n"
19936 "Host: www.example.org\r\n"
19937 "Connection: keep-alive\r\n\r\n"),
19938 };
19939
Steven Valdez1c1859172019-04-10 15:33:2819940 MockRead data_reads[] = {
19941 MockRead("HTTP/1.1 200 OK\r\n"),
19942 MockRead("Content-Length: 1\r\n\r\n"),
19943 MockRead(SYNCHRONOUS, "1"),
19944 };
19945
19946 StaticSocketDataProvider data(data_reads, data_writes);
19947 session_deps_.socket_factory->AddSocketDataProvider(&data);
19948 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19949 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19950 session_deps_.enable_early_data = true;
19951 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19952
19953 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19954
19955 TestCompletionCallback callback;
19956 auto trans =
19957 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19958
19959 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19960 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19961
19962 rv = callback.WaitForResult();
19963 EXPECT_THAT(rv, IsOk());
19964
19965 const HttpResponseInfo* response = trans->GetResponseInfo();
19966 ASSERT_TRUE(response);
19967 ASSERT_TRUE(response->headers);
19968 EXPECT_EQ(200, response->headers->response_code());
19969 EXPECT_EQ(1, response->headers->GetContentLength());
19970
19971 // Check that ConfirmHandshake wasn't called.
19972 ASSERT_FALSE(ssl.ConfirmDataConsumed());
19973 ASSERT_TRUE(ssl.WriteBeforeConfirm());
19974
19975 trans.reset();
19976
19977 session->CloseAllConnections();
19978}
19979
19980TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
19981 HttpRequestInfo request;
19982 request.method = "POST";
19983 request.url = GURL("https://www.example.org/");
19984 request.traffic_annotation =
19985 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19986
19987 MockWrite data_writes[] = {
19988 MockWrite(SYNCHRONOUS,
19989 "POST / HTTP/1.1\r\n"
19990 "Host: www.example.org\r\n"
19991 "Connection: keep-alive\r\n"
19992 "Content-Length: 0\r\n\r\n"),
19993 };
19994
Steven Valdez1c1859172019-04-10 15:33:2819995 MockRead data_reads[] = {
19996 MockRead("HTTP/1.1 200 OK\r\n"),
19997 MockRead("Content-Length: 1\r\n\r\n"),
19998 MockRead(SYNCHRONOUS, "1"),
19999 };
20000
20001 StaticSocketDataProvider data(data_reads, data_writes);
20002 session_deps_.socket_factory->AddSocketDataProvider(&data);
20003 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20004 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20005 session_deps_.enable_early_data = true;
20006 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20007
20008 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20009
20010 TestCompletionCallback callback;
20011 auto trans =
20012 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20013
20014 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20015 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20016
20017 rv = callback.WaitForResult();
20018 EXPECT_THAT(rv, IsOk());
20019
20020 const HttpResponseInfo* response = trans->GetResponseInfo();
20021 ASSERT_TRUE(response);
20022 ASSERT_TRUE(response->headers);
20023 EXPECT_EQ(200, response->headers->response_code());
20024 EXPECT_EQ(1, response->headers->GetContentLength());
20025
20026 // Check that the Write didn't get called before ConfirmHandshake completed.
20027 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20028
20029 trans.reset();
20030
20031 session->CloseAllConnections();
20032}
20033
20034TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
20035 HttpRequestInfo request;
20036 request.method = "POST";
20037 request.url = GURL("https://www.example.org/");
20038 request.traffic_annotation =
20039 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20040
20041 MockWrite data_writes[] = {
20042 MockWrite(ASYNC,
20043 "POST / HTTP/1.1\r\n"
20044 "Host: www.example.org\r\n"
20045 "Connection: keep-alive\r\n"
20046 "Content-Length: 0\r\n\r\n"),
20047 };
20048
Steven Valdez1c1859172019-04-10 15:33:2820049 MockRead data_reads[] = {
20050 MockRead("HTTP/1.1 200 OK\r\n"),
20051 MockRead("Content-Length: 1\r\n\r\n"),
20052 MockRead(SYNCHRONOUS, "1"),
20053 };
20054
20055 StaticSocketDataProvider data(data_reads, data_writes);
20056 session_deps_.socket_factory->AddSocketDataProvider(&data);
20057 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20058 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
20059 session_deps_.enable_early_data = true;
20060 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20061
20062 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20063
20064 TestCompletionCallback callback;
20065 auto trans =
20066 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20067
20068 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20069 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20070
20071 rv = callback.WaitForResult();
20072 EXPECT_THAT(rv, IsOk());
20073
20074 const HttpResponseInfo* response = trans->GetResponseInfo();
20075 ASSERT_TRUE(response);
20076 ASSERT_TRUE(response->headers);
20077 EXPECT_EQ(200, response->headers->response_code());
20078 EXPECT_EQ(1, response->headers->GetContentLength());
20079
20080 // Check that the Write didn't get called before ConfirmHandshake completed.
20081 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20082
20083 trans.reset();
20084
20085 session->CloseAllConnections();
20086}
20087
20088TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
20089 HttpRequestInfo request;
20090 request.method = "POST";
20091 request.url = GURL("https://www.example.org/");
20092 request.traffic_annotation =
20093 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20094
20095 MockWrite data_writes[] = {
20096 MockWrite(SYNCHRONOUS,
20097 "POST / HTTP/1.1\r\n"
20098 "Host: www.example.org\r\n"
20099 "Connection: keep-alive\r\n"
20100 "Content-Length: 0\r\n\r\n"),
20101 };
20102
Steven Valdez1c1859172019-04-10 15:33:2820103 MockRead data_reads[] = {
20104 MockRead("HTTP/1.1 200 OK\r\n"),
20105 MockRead("Content-Length: 1\r\n\r\n"),
20106 MockRead(SYNCHRONOUS, "1"),
20107 };
20108
20109 StaticSocketDataProvider data(data_reads, data_writes);
20110 session_deps_.socket_factory->AddSocketDataProvider(&data);
20111 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20112 ssl.confirm = MockConfirm(ASYNC, OK);
20113 session_deps_.enable_early_data = true;
20114 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20115
20116 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20117
20118 TestCompletionCallback callback;
20119 auto trans =
20120 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20121
20122 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20123 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20124
20125 rv = callback.WaitForResult();
20126 EXPECT_THAT(rv, IsOk());
20127
20128 const HttpResponseInfo* response = trans->GetResponseInfo();
20129 ASSERT_TRUE(response);
20130 ASSERT_TRUE(response->headers);
20131 EXPECT_EQ(200, response->headers->response_code());
20132 EXPECT_EQ(1, response->headers->GetContentLength());
20133
20134 // Check that the Write didn't get called before ConfirmHandshake completed.
20135 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20136
20137 trans.reset();
20138
20139 session->CloseAllConnections();
20140}
20141
20142TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
20143 HttpRequestInfo request;
20144 request.method = "POST";
20145 request.url = GURL("https://www.example.org/");
20146 request.traffic_annotation =
20147 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20148
20149 MockWrite data_writes[] = {
20150 MockWrite(ASYNC,
20151 "POST / HTTP/1.1\r\n"
20152 "Host: www.example.org\r\n"
20153 "Connection: keep-alive\r\n"
20154 "Content-Length: 0\r\n\r\n"),
20155 };
20156
Steven Valdez1c1859172019-04-10 15:33:2820157 MockRead data_reads[] = {
20158 MockRead("HTTP/1.1 200 OK\r\n"),
20159 MockRead("Content-Length: 1\r\n\r\n"),
20160 MockRead(SYNCHRONOUS, "1"),
20161 };
20162
20163 StaticSocketDataProvider data(data_reads, data_writes);
20164 session_deps_.socket_factory->AddSocketDataProvider(&data);
20165 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20166 ssl.confirm = MockConfirm(ASYNC, OK);
20167 session_deps_.enable_early_data = true;
20168 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20169
20170 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20171
20172 TestCompletionCallback callback;
20173 auto trans =
20174 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20175
20176 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20177 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20178
20179 rv = callback.WaitForResult();
20180 EXPECT_THAT(rv, IsOk());
20181
20182 const HttpResponseInfo* response = trans->GetResponseInfo();
20183 ASSERT_TRUE(response);
20184 ASSERT_TRUE(response->headers);
20185 EXPECT_EQ(200, response->headers->response_code());
20186 EXPECT_EQ(1, response->headers->GetContentLength());
20187
20188 // Check that the Write didn't get called before ConfirmHandshake completed.
20189 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20190
20191 trans.reset();
20192
20193 session->CloseAllConnections();
20194}
20195
David Benjaminfb976932019-05-15 13:39:1520196// 0-RTT rejects are handled at HttpNetworkTransaction.
20197TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
20198 enum class RejectType {
20199 kRead,
20200 kWrite,
20201 kConfirm,
20202 };
20203
20204 for (RejectType type :
20205 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
20206 SCOPED_TRACE(static_cast<int>(type));
20207 for (Error reject_error :
20208 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
20209 SCOPED_TRACE(reject_error);
20210 session_deps_.socket_factory =
20211 std::make_unique<MockClientSocketFactory>();
20212
20213 HttpRequestInfo request;
20214 request.method = type == RejectType::kConfirm ? "POST" : "GET";
20215 request.url = GURL("https://www.example.org/");
20216 request.traffic_annotation =
20217 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20218
20219 // The first request fails.
20220 std::vector<MockWrite> data1_writes;
20221 std::vector<MockRead> data1_reads;
20222 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
20223 switch (type) {
20224 case RejectType::kRead:
20225 data1_writes.emplace_back(
20226 "GET / HTTP/1.1\r\n"
20227 "Host: www.example.org\r\n"
20228 "Connection: keep-alive\r\n\r\n");
20229 data1_reads.emplace_back(ASYNC, reject_error);
20230 // Cause ConfirmHandshake to hang (it should not be called).
20231 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20232 break;
20233 case RejectType::kWrite:
20234 data1_writes.emplace_back(ASYNC, reject_error);
20235 // Cause ConfirmHandshake to hang (it should not be called).
20236 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20237 break;
20238 case RejectType::kConfirm:
20239 // The request never gets far enough to read or write.
20240 ssl1.confirm = MockConfirm(ASYNC, reject_error);
20241 break;
20242 }
20243
20244 StaticSocketDataProvider data1(data1_reads, data1_writes);
20245 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20246 session_deps_.enable_early_data = true;
20247 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20248
20249 // The retry succeeds.
20250 //
20251 // TODO(https://crbug.com/950705): If |reject_error| is
20252 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
20253 MockWrite data2_writes[] = {
20254 request.method == "POST"
20255 ? MockWrite("POST / HTTP/1.1\r\n"
20256 "Host: www.example.org\r\n"
20257 "Connection: keep-alive\r\n"
20258 "Content-Length: 0\r\n\r\n")
20259 : MockWrite("GET / HTTP/1.1\r\n"
20260 "Host: www.example.org\r\n"
20261 "Connection: keep-alive\r\n\r\n"),
20262 };
20263
20264 MockRead data2_reads[] = {
20265 MockRead("HTTP/1.1 200 OK\r\n"),
20266 MockRead("Content-Length: 1\r\n\r\n"),
20267 MockRead(SYNCHRONOUS, "1"),
20268 };
20269
20270 StaticSocketDataProvider data2(data2_reads, data2_writes);
20271 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20272 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
20273 ssl2.confirm = MockConfirm(ASYNC, OK);
20274 session_deps_.enable_early_data = true;
20275 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20276
20277 std::unique_ptr<HttpNetworkSession> session(
20278 CreateSession(&session_deps_));
20279
20280 TestCompletionCallback callback;
20281 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20282 session.get());
20283
20284 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20285 NetLogWithSource())),
20286 IsOk());
20287
20288 const HttpResponseInfo* response = trans->GetResponseInfo();
20289 ASSERT_TRUE(response);
20290 ASSERT_TRUE(response->headers);
20291 EXPECT_EQ(200, response->headers->response_code());
20292 EXPECT_EQ(1, response->headers->GetContentLength());
20293 }
20294 }
20295}
20296
Steven Valdez1c1859172019-04-10 15:33:2820297TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
20298 HttpRequestInfo request;
20299 request.method = "POST";
20300 request.url = GURL("https://www.example.org/");
20301 request.traffic_annotation =
20302 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20303
20304 MockWrite data_writes[] = {
20305 MockWrite("POST / HTTP/1.1\r\n"
20306 "Host: www.example.org\r\n"
20307 "Connection: keep-alive\r\n"
20308 "Content-Length: 0\r\n\r\n"),
20309 };
20310
Steven Valdez1c1859172019-04-10 15:33:2820311 MockRead data_reads[] = {
20312 MockRead("HTTP/1.1 200 OK\r\n"),
20313 MockRead("Content-Length: 1\r\n\r\n"),
20314 MockRead(SYNCHRONOUS, "1"),
20315 };
20316
20317 StaticSocketDataProvider data(data_reads, data_writes);
20318 session_deps_.socket_factory->AddSocketDataProvider(&data);
20319 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20320 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
20321 session_deps_.enable_early_data = true;
20322 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20323
20324 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20325
20326 TestCompletionCallback callback;
20327 auto trans =
20328 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20329
20330 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20331 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20332
20333 rv = callback.WaitForResult();
20334 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20335
20336 // Check that the Write didn't get called before ConfirmHandshake completed.
20337 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20338
20339 trans.reset();
20340
20341 session->CloseAllConnections();
20342}
20343
20344TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
20345 HttpRequestInfo request;
20346 request.method = "POST";
20347 request.url = GURL("https://www.example.org/");
20348 request.traffic_annotation =
20349 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20350
20351 MockWrite data_writes[] = {
20352 MockWrite("POST / HTTP/1.1\r\n"
20353 "Host: www.example.org\r\n"
20354 "Connection: keep-alive\r\n"
20355 "Content-Length: 0\r\n\r\n"),
20356 };
20357
Steven Valdez1c1859172019-04-10 15:33:2820358 MockRead data_reads[] = {
20359 MockRead("HTTP/1.1 200 OK\r\n"),
20360 MockRead("Content-Length: 1\r\n\r\n"),
20361 MockRead(SYNCHRONOUS, "1"),
20362 };
20363
20364 StaticSocketDataProvider data(data_reads, data_writes);
20365 session_deps_.socket_factory->AddSocketDataProvider(&data);
20366 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20367 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
20368 session_deps_.enable_early_data = true;
20369 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20370
20371 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20372
20373 TestCompletionCallback callback;
20374 auto trans =
20375 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20376
20377 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20378 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20379
20380 rv = callback.WaitForResult();
20381 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20382
20383 // Check that the Write didn't get called before ConfirmHandshake completed.
20384 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20385
20386 trans.reset();
20387
20388 session->CloseAllConnections();
20389}
20390
David Benjamin2eb827f2019-04-29 18:31:0420391// Test the proxy and origin server each requesting both TLS client certificates
20392// and HTTP auth. This is a regression test for https://crbug.com/946406.
20393TEST_F(HttpNetworkTransactionTest, AuthEverything) {
20394 // Note these hosts must match the CheckBasic*Auth() functions.
20395 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20396 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20397
20398 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20399 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20400
20401 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20402 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20403 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20404 ASSERT_TRUE(identity_proxy);
20405
20406 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20407 cert_request_info_origin->host_and_port =
20408 HostPortPair("www.example.org", 443);
20409
20410 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20411 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20412 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20413 ASSERT_TRUE(identity_origin);
20414
20415 HttpRequestInfo request;
20416 request.method = "GET";
20417 request.url = GURL("https://www.example.org/");
20418 request.traffic_annotation =
20419 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20420
David Benjamin7ebab032019-04-30 21:51:3020421 // First, the client connects to the proxy, which requests a client
20422 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420423 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20424 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20425 ssl_proxy1.expected_send_client_cert = false;
David Benjamin2eb827f2019-04-29 18:31:0420426 StaticSocketDataProvider data1;
20427 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020428 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420429
David Benjamin7ebab032019-04-30 21:51:3020430 // The client responds with a certificate on a new connection. The handshake
20431 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420432 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20433 ssl_proxy2.expected_send_client_cert = true;
20434 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020435 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420436 std::vector<MockWrite> mock_writes2;
20437 std::vector<MockRead> mock_reads2;
20438 mock_writes2.emplace_back(
20439 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20440 "Host: www.example.org:443\r\n"
20441 "Proxy-Connection: keep-alive\r\n\r\n");
20442 mock_reads2.emplace_back(
20443 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20444 "Content-Length: 0\r\n"
20445 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020446 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0420447 mock_writes2.emplace_back(
20448 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20449 "Host: www.example.org:443\r\n"
20450 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020451 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420452 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20453 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20454 // The origin requests client certificates.
20455 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20456 ssl_origin2.cert_request_info = cert_request_info_origin.get();
David Benjamin2eb827f2019-04-29 18:31:0420457 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20458 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020459 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20460 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0420461
David Benjamin7ebab032019-04-30 21:51:3020462 // The client responds to the origin client certificate request on a new
20463 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420464 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20465 ssl_proxy3.expected_send_client_cert = true;
20466 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
David Benjamin2eb827f2019-04-29 18:31:0420467 std::vector<MockWrite> mock_writes3;
20468 std::vector<MockRead> mock_reads3;
20469 mock_writes3.emplace_back(
20470 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20471 "Host: www.example.org:443\r\n"
20472 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020473 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420474 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20475 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20476 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
20477 ssl_origin3.expected_send_client_cert = true;
20478 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020479 // The client sends the origin HTTP request, which results in another HTTP
20480 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0420481 mock_writes3.emplace_back(
20482 "GET / HTTP/1.1\r\n"
20483 "Host: www.example.org\r\n"
20484 "Connection: keep-alive\r\n\r\n");
20485 mock_reads3.emplace_back(
20486 "HTTP/1.1 401 Unauthorized\r\n"
20487 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20488 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020489 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420490 mock_writes3.emplace_back(
20491 "GET / HTTP/1.1\r\n"
20492 "Host: www.example.org\r\n"
20493 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020494 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420495 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20496 mock_reads3.emplace_back(
20497 "HTTP/1.1 200 OK\r\n"
20498 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4120499 // The client makes another request. This should reuse the socket with all
20500 // credentials cached.
20501 mock_writes3.emplace_back(
20502 "GET / HTTP/1.1\r\n"
20503 "Host: www.example.org\r\n"
20504 "Connection: keep-alive\r\n"
20505 // Authenticate as user:pass.
20506 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20507 mock_reads3.emplace_back(
20508 "HTTP/1.1 200 OK\r\n"
20509 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0420510 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20511 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020512 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20513 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420514
20515 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20516
20517 // Start the request.
20518 TestCompletionCallback callback;
20519 auto trans =
20520 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20521 int rv = callback.GetResult(
20522 trans->Start(&request, callback.callback(), NetLogWithSource()));
20523
20524 // Handle the proxy client certificate challenge.
20525 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20526 SSLCertRequestInfo* cert_request_info =
20527 trans->GetResponseInfo()->cert_request_info.get();
20528 ASSERT_TRUE(cert_request_info);
20529 EXPECT_TRUE(cert_request_info->is_proxy);
20530 EXPECT_EQ(cert_request_info->host_and_port,
20531 cert_request_info_proxy->host_and_port);
20532 rv = callback.GetResult(trans->RestartWithCertificate(
20533 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20534 callback.callback()));
20535
20536 // Handle the proxy HTTP auth challenge.
20537 ASSERT_THAT(rv, IsOk());
20538 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20539 EXPECT_TRUE(
20540 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20541 rv = callback.GetResult(trans->RestartWithAuth(
20542 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20543 callback.callback()));
20544
20545 // Handle the origin client certificate challenge.
20546 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20547 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20548 ASSERT_TRUE(cert_request_info);
20549 EXPECT_FALSE(cert_request_info->is_proxy);
20550 EXPECT_EQ(cert_request_info->host_and_port,
20551 cert_request_info_origin->host_and_port);
20552 rv = callback.GetResult(trans->RestartWithCertificate(
20553 identity_origin->certificate(), identity_origin->ssl_private_key(),
20554 callback.callback()));
20555
20556 // Handle the origin HTTP auth challenge.
20557 ASSERT_THAT(rv, IsOk());
20558 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20559 EXPECT_TRUE(
20560 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20561 rv = callback.GetResult(trans->RestartWithAuth(
20562 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20563 callback.callback()));
20564
20565 // The request completes.
20566 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020567 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4120568
20569 // Make a second request. This time all credentials are cached.
20570 trans =
20571 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20572 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20573 NetLogWithSource())),
20574 IsOk());
20575 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420576}
20577
20578// Test the proxy and origin server each requesting both TLS client certificates
20579// and HTTP auth and each HTTP auth closing the connection. This is a regression
20580// test for https://crbug.com/946406.
20581TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
20582 // Note these hosts must match the CheckBasic*Auth() functions.
20583 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20584 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20585
20586 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20587 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20588
20589 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20590 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20591 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20592 ASSERT_TRUE(identity_proxy);
20593
20594 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20595 cert_request_info_origin->host_and_port =
20596 HostPortPair("www.example.org", 443);
20597
20598 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20599 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20600 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20601 ASSERT_TRUE(identity_origin);
20602
20603 HttpRequestInfo request;
20604 request.method = "GET";
20605 request.url = GURL("https://www.example.org/");
20606 request.traffic_annotation =
20607 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20608
David Benjamin7ebab032019-04-30 21:51:3020609 // First, the client connects to the proxy, which requests a client
20610 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420611 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20612 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20613 ssl_proxy1.expected_send_client_cert = false;
20614 StaticSocketDataProvider data1;
20615 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020616 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420617
David Benjamin7ebab032019-04-30 21:51:3020618 // The client responds with a certificate on a new connection. The handshake
20619 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420620 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20621 ssl_proxy2.expected_send_client_cert = true;
20622 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020623 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420624 std::vector<MockWrite> mock_writes2;
20625 std::vector<MockRead> mock_reads2;
20626 mock_writes2.emplace_back(
20627 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20628 "Host: www.example.org:443\r\n"
20629 "Proxy-Connection: keep-alive\r\n\r\n");
20630 mock_reads2.emplace_back(
20631 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20632 "Content-Length: 0\r\n"
20633 "Proxy-Connection: close\r\n"
20634 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20635 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20636 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0420638
David Benjamin7ebab032019-04-30 21:51:3020639 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0420640 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20641 ssl_proxy3.expected_send_client_cert = true;
20642 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
20643 std::vector<MockWrite> mock_writes3;
20644 std::vector<MockRead> mock_reads3;
20645 mock_writes3.emplace_back(
20646 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20647 "Host: www.example.org:443\r\n"
20648 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020649 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420650 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20651 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20652 // The origin requests client certificates.
20653 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20654 ssl_origin3.cert_request_info = cert_request_info_origin.get();
20655 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20656 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020657 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20658 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420659
David Benjamin7ebab032019-04-30 21:51:3020660 // The client responds to the origin client certificate request on a new
20661 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420662 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
20663 ssl_proxy4.expected_send_client_cert = true;
20664 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
20665 std::vector<MockWrite> mock_writes4;
20666 std::vector<MockRead> mock_reads4;
20667 mock_writes4.emplace_back(
20668 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20669 "Host: www.example.org:443\r\n"
20670 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020671 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420672 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20673 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20674 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
20675 ssl_origin4.expected_send_client_cert = true;
20676 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020677 // The client sends the origin HTTP request, which results in another HTTP
20678 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0420679 mock_writes4.emplace_back(
20680 "GET / HTTP/1.1\r\n"
20681 "Host: www.example.org\r\n"
20682 "Connection: keep-alive\r\n\r\n");
20683 mock_reads4.emplace_back(
20684 "HTTP/1.1 401 Unauthorized\r\n"
20685 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20686 "Connection: close\r\n"
20687 "Content-Length: 0\r\n\r\n");
20688 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
20689 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3020690 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
20691 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0420692
David Benjamin7ebab032019-04-30 21:51:3020693 // The client retries with credentials on a new connection, and the request
20694 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420695 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
20696 ssl_proxy5.expected_send_client_cert = true;
20697 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
20698 std::vector<MockWrite> mock_writes5;
20699 std::vector<MockRead> mock_reads5;
20700 mock_writes5.emplace_back(
20701 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20702 "Host: www.example.org:443\r\n"
20703 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020704 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420705 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20706 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20707 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
20708 ssl_origin5.expected_send_client_cert = true;
20709 ssl_origin5.expected_client_cert = identity_origin->certificate();
20710 mock_writes5.emplace_back(
20711 "GET / HTTP/1.1\r\n"
20712 "Host: www.example.org\r\n"
20713 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020714 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420715 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20716 mock_reads5.emplace_back(
20717 "HTTP/1.1 200 OK\r\n"
20718 "Connection: close\r\n"
20719 "Content-Length: 0\r\n\r\n");
20720 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
20721 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3020722 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
20723 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0420724
David Benjaminbac8dff2019-08-07 01:30:4120725 // The client makes a second request. This needs yet another connection, but
20726 // all credentials are cached.
20727 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
20728 ssl_proxy6.expected_send_client_cert = true;
20729 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
20730 std::vector<MockWrite> mock_writes6;
20731 std::vector<MockRead> mock_reads6;
20732 mock_writes6.emplace_back(
20733 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20734 "Host: www.example.org:443\r\n"
20735 "Proxy-Connection: keep-alive\r\n"
20736 // Authenticate as proxyuser:proxypass.
20737 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20738 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20739 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
20740 ssl_origin6.expected_send_client_cert = true;
20741 ssl_origin6.expected_client_cert = identity_origin->certificate();
20742 mock_writes6.emplace_back(
20743 "GET / HTTP/1.1\r\n"
20744 "Host: www.example.org\r\n"
20745 "Connection: keep-alive\r\n"
20746 // Authenticate as user:pass.
20747 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20748 mock_reads6.emplace_back(
20749 "HTTP/1.1 200 OK\r\n"
20750 "Connection: close\r\n"
20751 "Content-Length: 0\r\n\r\n");
20752 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
20753 session_deps_.socket_factory->AddSocketDataProvider(&data6);
20754 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
20755 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
20756
David Benjamin2eb827f2019-04-29 18:31:0420757 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20758
20759 // Start the request.
20760 TestCompletionCallback callback;
20761 auto trans =
20762 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20763 int rv = callback.GetResult(
20764 trans->Start(&request, callback.callback(), NetLogWithSource()));
20765
20766 // Handle the proxy client certificate challenge.
20767 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20768 SSLCertRequestInfo* cert_request_info =
20769 trans->GetResponseInfo()->cert_request_info.get();
20770 ASSERT_TRUE(cert_request_info);
20771 EXPECT_TRUE(cert_request_info->is_proxy);
20772 EXPECT_EQ(cert_request_info->host_and_port,
20773 cert_request_info_proxy->host_and_port);
20774 rv = callback.GetResult(trans->RestartWithCertificate(
20775 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20776 callback.callback()));
20777
20778 // Handle the proxy HTTP auth challenge.
20779 ASSERT_THAT(rv, IsOk());
20780 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20781 EXPECT_TRUE(
20782 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20783 rv = callback.GetResult(trans->RestartWithAuth(
20784 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20785 callback.callback()));
20786
20787 // Handle the origin client certificate challenge.
20788 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20789 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20790 ASSERT_TRUE(cert_request_info);
20791 EXPECT_FALSE(cert_request_info->is_proxy);
20792 EXPECT_EQ(cert_request_info->host_and_port,
20793 cert_request_info_origin->host_and_port);
20794 rv = callback.GetResult(trans->RestartWithCertificate(
20795 identity_origin->certificate(), identity_origin->ssl_private_key(),
20796 callback.callback()));
20797
20798 // Handle the origin HTTP auth challenge.
20799 ASSERT_THAT(rv, IsOk());
20800 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20801 EXPECT_TRUE(
20802 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20803 rv = callback.GetResult(trans->RestartWithAuth(
20804 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20805 callback.callback()));
20806
20807 // The request completes.
20808 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020809 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4120810
20811 // Make a second request. This time all credentials are cached.
20812 trans =
20813 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20814 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20815 NetLogWithSource())),
20816 IsOk());
20817 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3020818}
20819
20820// Test the proxy requesting HTTP auth and the server requesting TLS client
20821// certificates. This is a regression test for https://crbug.com/946406.
20822TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
20823 // Note these hosts must match the CheckBasic*Auth() functions.
20824 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20825 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20826
20827 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20828 cert_request_info_origin->host_and_port =
20829 HostPortPair("www.example.org", 443);
20830
20831 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20832 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20833 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20834 ASSERT_TRUE(identity_origin);
20835
20836 HttpRequestInfo request;
20837 request.method = "GET";
20838 request.url = GURL("https://www.example.org/");
20839 request.traffic_annotation =
20840 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20841
20842 // The client connects to the proxy. The handshake succeeds.
20843 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
20844 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20845 std::vector<MockWrite> mock_writes1;
20846 std::vector<MockRead> mock_reads1;
20847 mock_writes1.emplace_back(
20848 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20849 "Host: www.example.org:443\r\n"
20850 "Proxy-Connection: keep-alive\r\n\r\n");
20851 mock_reads1.emplace_back(
20852 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20853 "Content-Length: 0\r\n"
20854 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20855 // The client retries with credentials, and the request finally succeeds.
20856 mock_writes1.emplace_back(
20857 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20858 "Host: www.example.org:443\r\n"
20859 "Proxy-Connection: keep-alive\r\n"
20860 // Authenticate as proxyuser:proxypass.
20861 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20862 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20863 // The origin requests client certificates.
20864 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20865 ssl_origin1.cert_request_info = cert_request_info_origin.get();
20866 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
20867 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20868 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
20869 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
20870
20871 // The client responds to the origin client certificate request on a new
20872 // connection.
20873 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20874 std::vector<MockWrite> mock_writes2;
20875 std::vector<MockRead> mock_reads2;
20876 mock_writes2.emplace_back(
20877 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20878 "Host: www.example.org:443\r\n"
20879 "Proxy-Connection: keep-alive\r\n"
20880 // Authenticate as proxyuser:proxypass.
20881 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20882 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20883 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
20884 ssl_origin2.expected_send_client_cert = true;
20885 ssl_origin2.expected_client_cert = identity_origin->certificate();
20886 // The client sends the origin HTTP request, which succeeds.
20887 mock_writes2.emplace_back(
20888 "GET / HTTP/1.1\r\n"
20889 "Host: www.example.org\r\n"
20890 "Connection: keep-alive\r\n\r\n");
20891 mock_reads2.emplace_back(
20892 "HTTP/1.1 200 OK\r\n"
20893 "Content-Length: 0\r\n\r\n");
20894 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20895 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20896 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20897 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
20898
20899 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20900
20901 // Start the request.
20902 TestCompletionCallback callback;
20903 auto trans =
20904 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20905 int rv = callback.GetResult(
20906 trans->Start(&request, callback.callback(), NetLogWithSource()));
20907
20908 // Handle the proxy HTTP auth challenge.
20909 ASSERT_THAT(rv, IsOk());
20910 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20911 EXPECT_TRUE(
20912 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20913 rv = callback.GetResult(trans->RestartWithAuth(
20914 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20915 callback.callback()));
20916
20917 // Handle the origin client certificate challenge.
20918 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20919 SSLCertRequestInfo* cert_request_info =
20920 trans->GetResponseInfo()->cert_request_info.get();
20921 ASSERT_TRUE(cert_request_info);
20922 EXPECT_FALSE(cert_request_info->is_proxy);
20923 EXPECT_EQ(cert_request_info->host_and_port,
20924 cert_request_info_origin->host_and_port);
20925 rv = callback.GetResult(trans->RestartWithCertificate(
20926 identity_origin->certificate(), identity_origin->ssl_private_key(),
20927 callback.callback()));
20928
20929 // The request completes.
20930 ASSERT_THAT(rv, IsOk());
20931 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420932}
20933
David Benjamin6e673a82019-04-30 22:52:5820934// Test that socket reuse works with client certificates.
20935TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
20936 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
20937 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
20938
20939 std::unique_ptr<FakeClientCertIdentity> identity =
20940 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20941 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20942 ASSERT_TRUE(identity);
20943
20944 HttpRequestInfo request1;
20945 request1.method = "GET";
20946 request1.url = GURL("https://www.example.org/a");
20947 request1.traffic_annotation =
20948 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20949
20950 HttpRequestInfo request2;
20951 request2.method = "GET";
20952 request2.url = GURL("https://www.example.org/b");
20953 request2.traffic_annotation =
20954 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20955
20956 // The first connection results in a client certificate request.
20957 StaticSocketDataProvider data1;
20958 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20959 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20960 ssl1.cert_request_info = cert_request_info.get();
20961 ssl1.expected_send_client_cert = false;
20962 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20963
20964 // The second connection succeeds and is usable for both requests.
20965 MockWrite mock_writes[] = {
20966 MockWrite("GET /a HTTP/1.1\r\n"
20967 "Host: www.example.org\r\n"
20968 "Connection: keep-alive\r\n\r\n"),
20969 MockWrite("GET /b HTTP/1.1\r\n"
20970 "Host: www.example.org\r\n"
20971 "Connection: keep-alive\r\n\r\n"),
20972 };
20973 MockRead mock_reads[] = {
20974 MockRead("HTTP/1.1 200 OK\r\n"
20975 "Content-Length: 0\r\n\r\n"),
20976 MockRead("HTTP/1.1 200 OK\r\n"
20977 "Content-Length: 0\r\n\r\n"),
20978 };
20979 StaticSocketDataProvider data2(mock_reads, mock_writes);
20980 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20981 SSLSocketDataProvider ssl2(ASYNC, OK);
20982 ssl2.expected_send_client_cert = true;
20983 ssl2.expected_client_cert = identity->certificate();
20984 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20985
20986 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20987
20988 // Start the first request. It succeeds after providing client certificates.
20989 TestCompletionCallback callback;
20990 auto trans =
20991 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20992 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
20993 NetLogWithSource())),
20994 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20995
20996 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
20997 ASSERT_TRUE(info);
20998 EXPECT_FALSE(info->is_proxy);
20999 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
21000
21001 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
21002 identity->certificate(), identity->ssl_private_key(),
21003 callback.callback())),
21004 IsOk());
21005 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21006
21007 // Make the second request. It completes without requesting client
21008 // certificates.
21009 trans =
21010 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21011 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
21012 NetLogWithSource())),
21013 IsOk());
21014 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
21015}
21016
Matt Menke166443c2019-05-24 18:45:5921017// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
21018// sequence with two different NetworkIsolationKeys, the first and last have the
21019// same key, the second a different one. Checks that the requests are
21020// partitioned across sockets as expected.
21021TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2721022 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21023 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21024 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21025 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5921026
21027 for (bool partition_connections : {false, true}) {
21028 SCOPED_TRACE(partition_connections);
21029
21030 base::test::ScopedFeatureList feature_list;
21031 if (partition_connections) {
21032 feature_list.InitAndEnableFeature(
21033 features::kPartitionConnectionsByNetworkIsolationKey);
21034 } else {
21035 feature_list.InitAndDisableFeature(
21036 features::kPartitionConnectionsByNetworkIsolationKey);
21037 }
21038
21039 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21040
21041 // Reads and writes for the unpartitioned case, where only one socket is
21042 // used.
21043
21044 const MockWrite kUnpartitionedWrites[] = {
21045 MockWrite("GET /1 HTTP/1.1\r\n"
21046 "Host: foo.test\r\n"
21047 "Connection: keep-alive\r\n\r\n"),
21048 MockWrite("GET /2 HTTP/1.1\r\n"
21049 "Host: foo.test\r\n"
21050 "Connection: keep-alive\r\n\r\n"),
21051 MockWrite("GET /3 HTTP/1.1\r\n"
21052 "Host: foo.test\r\n"
21053 "Connection: keep-alive\r\n\r\n"),
21054 };
21055
21056 const MockRead kUnpartitionedReads[] = {
21057 MockRead("HTTP/1.1 200 OK\r\n"
21058 "Connection: keep-alive\r\n"
21059 "Content-Length: 1\r\n\r\n"
21060 "1"),
21061 MockRead("HTTP/1.1 200 OK\r\n"
21062 "Connection: keep-alive\r\n"
21063 "Content-Length: 1\r\n\r\n"
21064 "2"),
21065 MockRead("HTTP/1.1 200 OK\r\n"
21066 "Connection: keep-alive\r\n"
21067 "Content-Length: 1\r\n\r\n"
21068 "3"),
21069 };
21070
21071 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
21072 kUnpartitionedWrites);
21073
21074 // Reads and writes for the partitioned case, where two sockets are used.
21075
21076 const MockWrite kPartitionedWrites1[] = {
21077 MockWrite("GET /1 HTTP/1.1\r\n"
21078 "Host: foo.test\r\n"
21079 "Connection: keep-alive\r\n\r\n"),
21080 MockWrite("GET /3 HTTP/1.1\r\n"
21081 "Host: foo.test\r\n"
21082 "Connection: keep-alive\r\n\r\n"),
21083 };
21084
21085 const MockRead kPartitionedReads1[] = {
21086 MockRead("HTTP/1.1 200 OK\r\n"
21087 "Connection: keep-alive\r\n"
21088 "Content-Length: 1\r\n\r\n"
21089 "1"),
21090 MockRead("HTTP/1.1 200 OK\r\n"
21091 "Connection: keep-alive\r\n"
21092 "Content-Length: 1\r\n\r\n"
21093 "3"),
21094 };
21095
21096 const MockWrite kPartitionedWrites2[] = {
21097 MockWrite("GET /2 HTTP/1.1\r\n"
21098 "Host: foo.test\r\n"
21099 "Connection: keep-alive\r\n\r\n"),
21100 };
21101
21102 const MockRead kPartitionedReads2[] = {
21103 MockRead("HTTP/1.1 200 OK\r\n"
21104 "Connection: keep-alive\r\n"
21105 "Content-Length: 1\r\n\r\n"
21106 "2"),
21107 };
21108
21109 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
21110 kPartitionedWrites1);
21111 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
21112 kPartitionedWrites2);
21113
21114 if (partition_connections) {
21115 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21116 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21117 } else {
21118 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
21119 }
21120
21121 TestCompletionCallback callback;
21122 HttpRequestInfo request1;
21123 request1.method = "GET";
21124 request1.url = GURL("http://foo.test/1");
21125 request1.traffic_annotation =
21126 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21127 request1.network_isolation_key = network_isolation_key1;
21128 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21129 session.get());
21130 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21131 EXPECT_THAT(callback.GetResult(rv), IsOk());
21132 std::string response_data1;
21133 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21134 EXPECT_EQ("1", response_data1);
21135 trans1.reset();
21136
21137 HttpRequestInfo request2;
21138 request2.method = "GET";
21139 request2.url = GURL("http://foo.test/2");
21140 request2.traffic_annotation =
21141 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21142 request2.network_isolation_key = network_isolation_key2;
21143 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21144 session.get());
21145 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21146 EXPECT_THAT(callback.GetResult(rv), IsOk());
21147 std::string response_data2;
21148 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21149 EXPECT_EQ("2", response_data2);
21150 trans2.reset();
21151
21152 HttpRequestInfo request3;
21153 request3.method = "GET";
21154 request3.url = GURL("http://foo.test/3");
21155 request3.traffic_annotation =
21156 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21157 request3.network_isolation_key = network_isolation_key1;
21158 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21159 session.get());
21160 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21161 EXPECT_THAT(callback.GetResult(rv), IsOk());
21162 std::string response_data3;
21163 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21164 EXPECT_EQ("3", response_data3);
21165 trans3.reset();
21166 }
21167}
21168
Matt Menkeae58eeb2019-05-24 21:09:5021169TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2721170 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21171 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21172 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21173 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5021174
21175 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
21176 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
21177 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
21178 // the same way as the HTTP over H2 proxy case.
21179 for (bool use_proxy : {false, true}) {
21180 SCOPED_TRACE(use_proxy);
21181 if (use_proxy) {
21182 session_deps_.proxy_resolution_service =
21183 ProxyResolutionService::CreateFixedFromPacResult(
21184 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
21185 } else {
21186 session_deps_.proxy_resolution_service =
21187 ProxyResolutionService::CreateDirect();
21188 }
21189 const char* url1 = nullptr;
21190 const char* url2 = nullptr;
21191 const char* url3 = nullptr;
21192 if (use_proxy) {
21193 url1 = "http://foo.test/1";
21194 url2 = "http://foo.test/2";
21195 url3 = "http://foo.test/3";
21196 } else {
21197 url1 = "https://foo.test/1";
21198 url2 = "https://foo.test/2";
21199 url3 = "https://foo.test/3";
21200 }
21201
21202 for (bool partition_connections : {false, true}) {
21203 SCOPED_TRACE(partition_connections);
21204
21205 base::test::ScopedFeatureList feature_list;
21206 if (partition_connections) {
21207 feature_list.InitAndEnableFeature(
21208 features::kPartitionConnectionsByNetworkIsolationKey);
21209 } else {
21210 feature_list.InitAndDisableFeature(
21211 features::kPartitionConnectionsByNetworkIsolationKey);
21212 }
21213
21214 std::unique_ptr<HttpNetworkSession> session(
21215 CreateSession(&session_deps_));
21216
21217 // Reads and writes for the unpartitioned case, where only one socket is
21218 // used.
21219
21220 SpdyTestUtil spdy_util;
21221 spdy::SpdySerializedFrame unpartitioned_req1(
21222 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
21223 spdy::SpdySerializedFrame unpartitioned_response1(
21224 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
21225 spdy::SpdySerializedFrame unpartitioned_body1(
21226 spdy_util.ConstructSpdyDataFrame(1, "1", true));
21227 spdy_util.UpdateWithStreamDestruction(1);
21228
21229 spdy::SpdySerializedFrame unpartitioned_req2(
21230 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
21231 spdy::SpdySerializedFrame unpartitioned_response2(
21232 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
21233 spdy::SpdySerializedFrame unpartitioned_body2(
21234 spdy_util.ConstructSpdyDataFrame(3, "2", true));
21235 spdy_util.UpdateWithStreamDestruction(3);
21236
21237 spdy::SpdySerializedFrame unpartitioned_req3(
21238 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
21239 spdy::SpdySerializedFrame unpartitioned_response3(
21240 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
21241 spdy::SpdySerializedFrame unpartitioned_body3(
21242 spdy_util.ConstructSpdyDataFrame(5, "3", true));
21243
21244 const MockWrite kUnpartitionedWrites[] = {
21245 CreateMockWrite(unpartitioned_req1, 0),
21246 CreateMockWrite(unpartitioned_req2, 3),
21247 CreateMockWrite(unpartitioned_req3, 6),
21248 };
21249
21250 const MockRead kUnpartitionedReads[] = {
21251 CreateMockRead(unpartitioned_response1, 1),
21252 CreateMockRead(unpartitioned_body1, 2),
21253 CreateMockRead(unpartitioned_response2, 4),
21254 CreateMockRead(unpartitioned_body2, 5),
21255 CreateMockRead(unpartitioned_response3, 7),
21256 CreateMockRead(unpartitioned_body3, 8),
21257 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
21258 };
21259
21260 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
21261 kUnpartitionedWrites);
21262
21263 // Reads and writes for the partitioned case, where two sockets are used.
21264
21265 SpdyTestUtil spdy_util2;
21266 spdy::SpdySerializedFrame partitioned_req1(
21267 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
21268 spdy::SpdySerializedFrame partitioned_response1(
21269 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
21270 spdy::SpdySerializedFrame partitioned_body1(
21271 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
21272 spdy_util2.UpdateWithStreamDestruction(1);
21273
21274 spdy::SpdySerializedFrame partitioned_req3(
21275 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
21276 spdy::SpdySerializedFrame partitioned_response3(
21277 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
21278 spdy::SpdySerializedFrame partitioned_body3(
21279 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
21280
21281 const MockWrite kPartitionedWrites1[] = {
21282 CreateMockWrite(partitioned_req1, 0),
21283 CreateMockWrite(partitioned_req3, 3),
21284 };
21285
21286 const MockRead kPartitionedReads1[] = {
21287 CreateMockRead(partitioned_response1, 1),
21288 CreateMockRead(partitioned_body1, 2),
21289 CreateMockRead(partitioned_response3, 4),
21290 CreateMockRead(partitioned_body3, 5),
21291 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
21292 };
21293
21294 SpdyTestUtil spdy_util3;
21295 spdy::SpdySerializedFrame partitioned_req2(
21296 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
21297 spdy::SpdySerializedFrame partitioned_response2(
21298 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
21299 spdy::SpdySerializedFrame partitioned_body2(
21300 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
21301
21302 const MockWrite kPartitionedWrites2[] = {
21303 CreateMockWrite(partitioned_req2, 0),
21304 };
21305
21306 const MockRead kPartitionedReads2[] = {
21307 CreateMockRead(partitioned_response2, 1),
21308 CreateMockRead(partitioned_body2, 2),
21309 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
21310 };
21311
21312 SequencedSocketData partitioned_data1(kPartitionedReads1,
21313 kPartitionedWrites1);
21314 SequencedSocketData partitioned_data2(kPartitionedReads2,
21315 kPartitionedWrites2);
21316
21317 // No need to segment SSLDataProviders by whether or not partitioning is
21318 // enabled.
21319 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21320 ssl_data1.next_proto = kProtoHTTP2;
21321 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21322 ssl_data2.next_proto = kProtoHTTP2;
21323
21324 if (partition_connections) {
21325 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21326 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21327 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21328 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21329 } else {
21330 session_deps_.socket_factory->AddSocketDataProvider(
21331 &unpartitioned_data);
21332 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21333 }
21334
21335 TestCompletionCallback callback;
21336 HttpRequestInfo request1;
21337 request1.method = "GET";
21338 request1.url = GURL(url1);
21339 request1.traffic_annotation =
21340 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21341 request1.network_isolation_key = network_isolation_key1;
21342 auto trans1 =
21343 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21344 int rv =
21345 trans1->Start(&request1, callback.callback(), NetLogWithSource());
21346 EXPECT_THAT(callback.GetResult(rv), IsOk());
21347 std::string response_data1;
21348 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21349 EXPECT_EQ("1", response_data1);
21350 trans1.reset();
21351
21352 HttpRequestInfo request2;
21353 request2.method = "GET";
21354 request2.url = GURL(url2);
21355 request2.traffic_annotation =
21356 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21357 request2.network_isolation_key = network_isolation_key2;
21358 auto trans2 =
21359 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21360 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21361 EXPECT_THAT(callback.GetResult(rv), IsOk());
21362 std::string response_data2;
21363 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21364 EXPECT_EQ("2", response_data2);
21365 trans2.reset();
21366
21367 HttpRequestInfo request3;
21368 request3.method = "GET";
21369 request3.url = GURL(url3);
21370 request3.traffic_annotation =
21371 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21372 request3.network_isolation_key = network_isolation_key1;
21373 auto trans3 =
21374 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21375 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21376 EXPECT_THAT(callback.GetResult(rv), IsOk());
21377 std::string response_data3;
21378 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21379 EXPECT_EQ("3", response_data3);
21380 trans3.reset();
21381 }
21382 }
21383}
21384
Matt Menke7281f872019-06-25 19:29:2521385// Preconnect two sockets with different NetworkIsolationKeys when
21386// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
21387// request and make sure the correct socket is used. Loops three times,
21388// expecting to use the first preconnect, second preconnect, and neither.
21389TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
21390 base::test::ScopedFeatureList feature_list;
21391 feature_list.InitAndEnableFeature(
21392 features::kPartitionConnectionsByNetworkIsolationKey);
21393
21394 enum class TestCase {
21395 kUseFirstPreconnect,
21396 kUseSecondPreconnect,
21397 kDontUsePreconnect,
21398 };
21399
Shivani Sharma8ae506c2019-07-21 21:08:2721400 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21401 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21402 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
21403 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
21404 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
21405 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2521406
21407 // Test that only preconnects with
21408 for (TestCase test_case :
21409 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
21410 TestCase::kDontUsePreconnect}) {
21411 SpdySessionDependencies session_deps;
21412 // Make DNS lookups completely synchronously, so preconnects complete
21413 // immediately.
21414 session_deps.host_resolver->set_synchronous_mode(true);
21415
21416 const MockWrite kMockWrites[] = {
21417 MockWrite(ASYNC, 0,
21418 "GET / HTTP/1.1\r\n"
21419 "Host: www.foo.com\r\n"
21420 "Connection: keep-alive\r\n\r\n"),
21421 };
21422
21423 const MockRead kMockReads[] = {
21424 MockRead(ASYNC, 1,
21425 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
21426 "hello"),
21427 };
21428
21429 // Used for the socket that will actually be used, which may or may not be
21430 // one of the preconnects
21431 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
21432 kMockReads, kMockWrites);
21433
21434 // Used for the preconnects that won't actually be used.
21435 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
21436 base::span<const MockRead>(),
21437 base::span<const MockWrite>());
21438 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
21439 base::span<const MockRead>(),
21440 base::span<const MockWrite>());
21441
21442 NetworkIsolationKey network_isolation_key_for_request;
21443
21444 switch (test_case) {
21445 case TestCase::kUseFirstPreconnect:
21446 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21447 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21448 network_isolation_key_for_request = preconnect1_isolation_key;
21449 break;
21450 case TestCase::kUseSecondPreconnect:
21451 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21452 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21453 network_isolation_key_for_request = preconnect2_isolation_key;
21454 break;
21455 case TestCase::kDontUsePreconnect:
21456 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21457 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21458 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21459 network_isolation_key_for_request = not_preconnected_isolation_key;
21460 break;
21461 }
21462
21463 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
21464
21465 // Preconnect sockets.
21466 HttpRequestInfo request;
21467 request.method = "GET";
21468 request.url = GURL("http://www.foo.com/");
21469 request.traffic_annotation =
21470 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21471
21472 request.network_isolation_key = preconnect1_isolation_key;
21473 session->http_stream_factory()->PreconnectStreams(1, request);
21474
21475 request.network_isolation_key = preconnect2_isolation_key;
21476 session->http_stream_factory()->PreconnectStreams(1, request);
21477
21478 request.network_isolation_key = network_isolation_key_for_request;
21479
21480 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21481
21482 // Make the request.
21483 TestCompletionCallback callback;
21484
21485 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21486
21487 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
21488 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21489
21490 rv = callback.WaitForResult();
21491 EXPECT_THAT(rv, IsOk());
21492
21493 const HttpResponseInfo* response = trans.GetResponseInfo();
21494 ASSERT_TRUE(response);
21495 ASSERT_TRUE(response->headers);
21496 EXPECT_EQ(200, response->headers->response_code());
21497
21498 std::string response_data;
21499 rv = ReadTransaction(&trans, &response_data);
21500 EXPECT_THAT(rv, IsOk());
21501 EXPECT_EQ("hello", response_data);
21502
21503 if (test_case != TestCase::kDontUsePreconnect) {
21504 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21505 } else {
21506 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
21507 }
21508 }
21509}
21510
David Benjamin6f2da652019-06-26 23:36:3521511// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21512// cache is isolated.
21513TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
21514 base::test::ScopedFeatureList feature_list;
21515 feature_list.InitWithFeatures(
21516 {features::kPartitionConnectionsByNetworkIsolationKey,
21517 features::kPartitionSSLSessionsByNetworkIsolationKey},
21518 {});
21519
Shivani Sharma8ae506c2019-07-21 21:08:2721520 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21521 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21522 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
21523 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3521524 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21525
21526 // The server always sends Connection: close, so each request goes over a
21527 // distinct socket.
21528
21529 const MockWrite kWrites1[] = {
21530 MockWrite("GET /1 HTTP/1.1\r\n"
21531 "Host: foo.test\r\n"
21532 "Connection: keep-alive\r\n\r\n")};
21533
21534 const MockRead kReads1[] = {
21535 MockRead("HTTP/1.1 200 OK\r\n"
21536 "Connection: close\r\n"
21537 "Content-Length: 1\r\n\r\n"
21538 "1")};
21539
21540 const MockWrite kWrites2[] = {
21541 MockWrite("GET /2 HTTP/1.1\r\n"
21542 "Host: foo.test\r\n"
21543 "Connection: keep-alive\r\n\r\n")};
21544
21545 const MockRead kReads2[] = {
21546 MockRead("HTTP/1.1 200 OK\r\n"
21547 "Connection: close\r\n"
21548 "Content-Length: 1\r\n\r\n"
21549 "2")};
21550
21551 const MockWrite kWrites3[] = {
21552 MockWrite("GET /3 HTTP/1.1\r\n"
21553 "Host: foo.test\r\n"
21554 "Connection: keep-alive\r\n\r\n")};
21555
21556 const MockRead kReads3[] = {
21557 MockRead("HTTP/1.1 200 OK\r\n"
21558 "Connection: close\r\n"
21559 "Content-Length: 1\r\n\r\n"
21560 "3")};
21561
21562 StaticSocketDataProvider data1(kReads1, kWrites1);
21563 StaticSocketDataProvider data2(kReads2, kWrites2);
21564 StaticSocketDataProvider data3(kReads3, kWrites3);
21565 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21566 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21567 session_deps_.socket_factory->AddSocketDataProvider(&data3);
21568
21569 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21570 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
21571 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
21572 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21573 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
21574 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
21575 SSLSocketDataProvider ssl_data3(ASYNC, OK);
21576 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
21577 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
21578 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21579 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21580 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
21581
21582 TestCompletionCallback callback;
21583 HttpRequestInfo request1;
21584 request1.method = "GET";
21585 request1.url = GURL("https://foo.test/1");
21586 request1.traffic_annotation =
21587 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21588 request1.network_isolation_key = kNetworkIsolationKey1;
21589 auto trans1 =
21590 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21591 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21592 EXPECT_THAT(callback.GetResult(rv), IsOk());
21593 std::string response_data1;
21594 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21595 EXPECT_EQ("1", response_data1);
21596 trans1.reset();
21597
21598 HttpRequestInfo request2;
21599 request2.method = "GET";
21600 request2.url = GURL("https://foo.test/2");
21601 request2.traffic_annotation =
21602 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21603 request2.network_isolation_key = kNetworkIsolationKey2;
21604 auto trans2 =
21605 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21606 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21607 EXPECT_THAT(callback.GetResult(rv), IsOk());
21608 std::string response_data2;
21609 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21610 EXPECT_EQ("2", response_data2);
21611 trans2.reset();
21612
21613 HttpRequestInfo request3;
21614 request3.method = "GET";
21615 request3.url = GURL("https://foo.test/3");
21616 request3.traffic_annotation =
21617 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21618 request3.network_isolation_key = kNetworkIsolationKey1;
21619 auto trans3 =
21620 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21621 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21622 EXPECT_THAT(callback.GetResult(rv), IsOk());
21623 std::string response_data3;
21624 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21625 EXPECT_EQ("3", response_data3);
21626 trans3.reset();
21627}
21628
21629// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21630// cache is isolated, for both origins and proxies.
21631TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
21632 base::test::ScopedFeatureList feature_list;
21633 feature_list.InitWithFeatures(
21634 {features::kPartitionConnectionsByNetworkIsolationKey,
21635 features::kPartitionSSLSessionsByNetworkIsolationKey},
21636 {});
21637
21638 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21639 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21640
Shivani Sharma8ae506c2019-07-21 21:08:2721641 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21642 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21643 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
21644 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3521645 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21646
21647 // Make both a tunneled and non-tunneled request.
21648 HttpRequestInfo request1;
21649 request1.method = "GET";
21650 request1.url = GURL("https://foo.test/1");
21651 request1.traffic_annotation =
21652 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21653 request1.network_isolation_key = kNetworkIsolationKey1;
21654
21655 HttpRequestInfo request2;
21656 request2.method = "GET";
21657 request2.url = GURL("http://foo.test/2");
21658 request2.traffic_annotation =
21659 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21660 request2.network_isolation_key = kNetworkIsolationKey2;
21661
21662 const MockWrite kWrites1[] = {
21663 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
21664 "Host: foo.test:443\r\n"
21665 "Proxy-Connection: keep-alive\r\n\r\n"),
21666 MockWrite("GET /1 HTTP/1.1\r\n"
21667 "Host: foo.test\r\n"
21668 "Connection: keep-alive\r\n\r\n")};
21669
21670 const MockRead kReads1[] = {
21671 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
21672 MockRead("HTTP/1.1 200 OK\r\n"
21673 "Connection: close\r\n"
21674 "Content-Length: 1\r\n\r\n"
21675 "1")};
21676
21677 const MockWrite kWrites2[] = {
21678 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
21679 "Host: foo.test\r\n"
21680 "Proxy-Connection: keep-alive\r\n\r\n")};
21681
21682 const MockRead kReads2[] = {
21683 MockRead("HTTP/1.1 200 OK\r\n"
21684 "Connection: close\r\n"
21685 "Content-Length: 1\r\n\r\n"
21686 "2")};
21687
21688 StaticSocketDataProvider data1(kReads1, kWrites1);
21689 StaticSocketDataProvider data2(kReads2, kWrites2);
21690 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21691 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21692 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21693
21694 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21695 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
21696 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
21697 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
21698 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
21699 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
21700 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21701 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
21702 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
21703 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21704 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21705 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21706
21707 TestCompletionCallback callback;
21708 auto trans1 =
21709 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21710 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21711 EXPECT_THAT(callback.GetResult(rv), IsOk());
21712 std::string response_data1;
21713 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21714 EXPECT_EQ("1", response_data1);
21715 trans1.reset();
21716
21717 auto trans2 =
21718 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21719 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21720 EXPECT_THAT(callback.GetResult(rv), IsOk());
21721 std::string response_data2;
21722 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21723 EXPECT_EQ("2", response_data2);
21724 trans2.reset();
21725}
21726
David Benjaminef2f2a5a2019-07-16 19:21:3121727// Test that SSLConfig changes from SSLConfigService are picked up even when
21728// there are live sockets.
21729TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5221730 SSLContextConfig ssl_context_config;
21731 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21732 auto ssl_config_service =
21733 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121734 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21735
21736 session_deps_.ssl_config_service = std::move(ssl_config_service);
21737
21738 // Make three requests. Between the second and third, the SSL config will
21739 // change.
21740 HttpRequestInfo request1;
21741 request1.method = "GET";
21742 request1.url = GURL("https://foo.test/1");
21743 request1.traffic_annotation =
21744 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21745
21746 HttpRequestInfo request2;
21747 request2.method = "GET";
21748 request2.url = GURL("https://foo.test/2");
21749 request2.traffic_annotation =
21750 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21751
21752 HttpRequestInfo request3;
21753 request3.method = "GET";
21754 request3.url = GURL("https://foo.test/3");
21755 request3.traffic_annotation =
21756 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21757
21758 const MockWrite kWrites1[] = {
21759 MockWrite("GET /1 HTTP/1.1\r\n"
21760 "Host: foo.test\r\n"
21761 "Connection: keep-alive\r\n\r\n"),
21762 MockWrite("GET /2 HTTP/1.1\r\n"
21763 "Host: foo.test\r\n"
21764 "Connection: keep-alive\r\n\r\n"),
21765 };
21766
21767 const MockRead kReads1[] = {
21768 MockRead("HTTP/1.1 200 OK\r\n"
21769 "Connection: keep-alive\r\n"
21770 "Content-Length: 1\r\n\r\n"
21771 "1"),
21772 MockRead("HTTP/1.1 200 OK\r\n"
21773 "Connection: keep-alive\r\n"
21774 "Content-Length: 1\r\n\r\n"
21775 "2"),
21776 };
21777
21778 // The third request goes on a different socket because the SSL config has
21779 // changed.
21780 const MockWrite kWrites2[] = {
21781 MockWrite("GET /3 HTTP/1.1\r\n"
21782 "Host: foo.test\r\n"
21783 "Connection: keep-alive\r\n\r\n")};
21784
21785 const MockRead kReads2[] = {
21786 MockRead("HTTP/1.1 200 OK\r\n"
21787 "Connection: keep-alive\r\n"
21788 "Content-Length: 1\r\n\r\n"
21789 "3")};
21790
21791 StaticSocketDataProvider data1(kReads1, kWrites1);
21792 StaticSocketDataProvider data2(kReads2, kWrites2);
21793 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21794 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21795
21796 SSLSocketDataProvider ssl1(ASYNC, OK);
21797 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21798 SSLSocketDataProvider ssl2(ASYNC, OK);
21799 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21801 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21802
21803 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21804
21805 TestCompletionCallback callback;
21806 auto trans1 =
21807 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21808 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21809 EXPECT_THAT(callback.GetResult(rv), IsOk());
21810 std::string response_data1;
21811 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21812 EXPECT_EQ("1", response_data1);
21813 trans1.reset();
21814
21815 auto trans2 =
21816 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21817 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21818 EXPECT_THAT(callback.GetResult(rv), IsOk());
21819 std::string response_data2;
21820 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21821 EXPECT_EQ("2", response_data2);
21822 trans2.reset();
21823
David Benjamin151ec6b2019-08-02 19:38:5221824 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21825 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121826
21827 auto trans3 =
21828 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21829 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21830 EXPECT_THAT(callback.GetResult(rv), IsOk());
21831 std::string response_data3;
21832 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21833 EXPECT_EQ("3", response_data3);
21834 trans3.reset();
21835}
21836
21837TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5221838 SSLContextConfig ssl_context_config;
21839 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21840 auto ssl_config_service =
21841 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121842 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21843
21844 session_deps_.ssl_config_service = std::move(ssl_config_service);
21845
21846 HttpRequestInfo request;
21847 request.method = "GET";
21848 request.url = GURL("https://foo.test/1");
21849 request.traffic_annotation =
21850 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21851
21852 // Make a socket which never connects.
21853 StaticSocketDataProvider data({}, {});
21854 session_deps_.socket_factory->AddSocketDataProvider(&data);
21855 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
21856 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21857 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
21858
21859 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21860
21861 TestCompletionCallback callback;
21862 auto trans =
21863 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21864 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21865 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21866
David Benjamin151ec6b2019-08-02 19:38:5221867 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21868 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121869
21870 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
21871}
21872
David Benjaminbac8dff2019-08-07 01:30:4121873// Test that HttpNetworkTransaction correctly handles existing sockets when the
21874// server requests a client certificate post-handshake (via a TLS
21875// renegotiation). This is a regression test for https://crbug.com/829184.
21876TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
21877 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
21878 TRAFFIC_ANNOTATION_FOR_TESTS);
21879
21880 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
21881 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
21882
21883 std::unique_ptr<FakeClientCertIdentity> identity =
21884 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21885 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21886 ASSERT_TRUE(identity);
21887
21888 // This test will make several requests so that, when the client certificate
21889 // request comes in, we have a socket in use, an idle socket, and a socket for
21890 // an unrelated host.
21891 //
21892 // First, two long-lived requests which do not complete until after the client
21893 // certificate request. This arranges for sockets to be in use during the
21894 // request. They should not be interrupted.
21895 HttpRequestInfo request_long_lived;
21896 request_long_lived.method = "GET";
21897 request_long_lived.url = GURL("https://foo.test/long-lived");
21898 request_long_lived.traffic_annotation = kTrafficAnnotation;
21899
21900 HttpRequestInfo request_long_lived_bar;
21901 request_long_lived_bar.method = "GET";
21902 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
21903 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
21904
21905 // Next, make a request that needs client certificates.
21906 HttpRequestInfo request_auth;
21907 request_auth.method = "GET";
21908 request_auth.url = GURL("https://foo.test/auth");
21909 request_auth.traffic_annotation = kTrafficAnnotation;
21910
21911 // Before responding to the challenge, make a request to an unauthenticated
21912 // endpoint. This will result in an idle socket when the client certificate
21913 // challenge is resolved.
21914 HttpRequestInfo request_unauth;
21915 request_unauth.method = "GET";
21916 request_unauth.url = GURL("https://foo.test/unauth");
21917 request_unauth.traffic_annotation = kTrafficAnnotation;
21918
21919 // After all the preceding requests complete, end with two additional requests
21920 // to ensure pre-authentication foo.test sockets are not used and bar.test
21921 // sockets are unaffected.
21922 HttpRequestInfo request_post_auth;
21923 request_post_auth.method = "GET";
21924 request_post_auth.url = GURL("https://foo.test/post-auth");
21925 request_post_auth.traffic_annotation = kTrafficAnnotation;
21926
21927 HttpRequestInfo request_post_auth_bar;
21928 request_post_auth_bar.method = "GET";
21929 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
21930 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
21931
21932 // The sockets for /long-lived and /unauth complete their request but are
21933 // not allocated for /post-auth or /retry because SSL state has since changed.
21934 const MockWrite kLongLivedWrites[] = {
21935 MockWrite(ASYNC, 0,
21936 "GET /long-lived HTTP/1.1\r\n"
21937 "Host: foo.test\r\n"
21938 "Connection: keep-alive\r\n\r\n"),
21939 };
21940 const MockRead kLongLivedReads[] = {
21941 // Pause so /long-lived completes after the client presents client
21942 // certificates.
21943 MockRead(ASYNC, ERR_IO_PENDING, 1),
21944 MockRead(ASYNC, 2,
21945 "HTTP/1.1 200 OK\r\n"
21946 "Connection: keep-alive\r\n"
21947 "Content-Length: 10\r\n\r\n"
21948 "long-lived"),
21949 };
21950 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
21951 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
21952 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
21953 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
21954
21955 // Requests for bar.test should be unaffected by foo.test and get allocated
21956 // a single socket.
21957 const MockWrite kBarWrites[] = {
21958 MockWrite(ASYNC, 0,
21959 "GET /long-lived HTTP/1.1\r\n"
21960 "Host: bar.test\r\n"
21961 "Connection: keep-alive\r\n\r\n"),
21962 MockWrite(ASYNC, 3,
21963 "GET /post-auth HTTP/1.1\r\n"
21964 "Host: bar.test\r\n"
21965 "Connection: keep-alive\r\n\r\n"),
21966 };
21967 const MockRead kBarReads[] = {
21968 // Pause on /long-lived so it completes after foo.test's authentication.
21969 MockRead(ASYNC, ERR_IO_PENDING, 1),
21970 MockRead(ASYNC, 2,
21971 "HTTP/1.1 200 OK\r\n"
21972 "Connection: keep-alive\r\n"
21973 "Content-Length: 10\r\n\r\n"
21974 "long-lived"),
21975 MockRead(ASYNC, 4,
21976 "HTTP/1.1 200 OK\r\n"
21977 "Connection: keep-alive\r\n"
21978 "Content-Length: 9\r\n\r\n"
21979 "post-auth"),
21980 };
21981 SequencedSocketData data_bar(kBarReads, kBarWrites);
21982 SSLSocketDataProvider ssl_bar(ASYNC, OK);
21983 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
21984 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
21985
21986 // Requesting /auth results in a post-handshake client certificate challenge.
21987 const MockWrite kAuthWrites[] = {
21988 MockWrite(ASYNC, 0,
21989 "GET /auth HTTP/1.1\r\n"
21990 "Host: foo.test\r\n"
21991 "Connection: keep-alive\r\n\r\n"),
21992 };
21993 const MockRead kAuthReads[] = {
21994 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
21995 };
21996 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
21997 SSLSocketDataProvider ssl_auth(ASYNC, OK);
21998 ssl_auth.cert_request_info = cert_request_info.get();
21999 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
22000 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
22001
22002 // Requesting /unauth completes.
22003 const MockWrite kUnauthWrites[] = {
22004 MockWrite(ASYNC, 0,
22005 "GET /unauth HTTP/1.1\r\n"
22006 "Host: foo.test\r\n"
22007 "Connection: keep-alive\r\n\r\n"),
22008 };
22009 const MockRead kUnauthReads[] = {
22010 MockRead(ASYNC, 1,
22011 "HTTP/1.1 200 OK\r\n"
22012 "Connection: keep-alive\r\n"
22013 "Content-Length: 6\r\n\r\n"
22014 "unauth"),
22015 };
22016 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
22017 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
22018 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
22019 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
22020
22021 // When the client certificate is selected, /auth is retried on a new
22022 // connection. In particular, it should not be retried on |data_unauth|,
22023 // which would not honor the new client certificate configuration.
22024 const MockWrite kRetryWrites[] = {
22025 MockWrite(ASYNC, 0,
22026 "GET /auth HTTP/1.1\r\n"
22027 "Host: foo.test\r\n"
22028 "Connection: keep-alive\r\n\r\n"),
22029 };
22030 const MockRead kRetryReads[] = {
22031 MockRead(ASYNC, 1,
22032 "HTTP/1.1 200 OK\r\n"
22033 // Close the connection so we test that /post-auth is not
22034 // allocated to |data_unauth| or |data_long_lived|.
22035 "Connection: close\r\n"
22036 "Content-Length: 4\r\n\r\n"
22037 "auth"),
22038 };
22039 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
22040 SSLSocketDataProvider ssl_retry(ASYNC, OK);
22041 ssl_retry.expected_send_client_cert = true;
22042 ssl_retry.expected_client_cert = identity->certificate();
22043 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
22044 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
22045
22046 // /post-auth gets its own socket.
22047 const MockWrite kPostAuthWrites[] = {
22048 MockWrite(ASYNC, 0,
22049 "GET /post-auth HTTP/1.1\r\n"
22050 "Host: foo.test\r\n"
22051 "Connection: keep-alive\r\n\r\n"),
22052 };
22053 const MockRead kPostAuthReads[] = {
22054 MockRead(ASYNC, 1,
22055 "HTTP/1.1 200 OK\r\n"
22056 "Connection: keep-alive\r\n"
22057 "Content-Length: 9\r\n\r\n"
22058 "post-auth"),
22059 };
22060 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
22061 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
22062 ssl_post_auth.expected_send_client_cert = true;
22063 ssl_post_auth.expected_client_cert = identity->certificate();
22064 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
22065 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
22066
22067 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22068
22069 // Start the two long-lived requests.
22070 TestCompletionCallback callback_long_lived;
22071 auto trans_long_lived =
22072 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22073 int rv = trans_long_lived->Start(
22074 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
22075 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22076 data_long_lived.RunUntilPaused();
22077
22078 TestCompletionCallback callback_long_lived_bar;
22079 auto trans_long_lived_bar =
22080 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22081 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
22082 callback_long_lived_bar.callback(),
22083 NetLogWithSource());
22084 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22085 data_bar.RunUntilPaused();
22086
22087 // Request /auth. This gives a client certificate challenge.
22088 TestCompletionCallback callback_auth;
22089 auto trans_auth =
22090 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22091 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
22092 NetLogWithSource());
22093 EXPECT_THAT(callback_auth.GetResult(rv),
22094 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22095
22096 // Make an unauthenticated request. This completes.
22097 TestCompletionCallback callback_unauth;
22098 auto trans_unauth =
22099 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22100 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
22101 NetLogWithSource());
22102 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
22103 std::string response_unauth;
22104 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
22105 EXPECT_EQ("unauth", response_unauth);
22106 trans_unauth.reset();
22107
22108 // Complete the authenticated request.
22109 rv = trans_auth->RestartWithCertificate(identity->certificate(),
22110 identity->ssl_private_key(),
22111 callback_auth.callback());
22112 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
22113 std::string response_auth;
22114 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
22115 EXPECT_EQ("auth", response_auth);
22116 trans_auth.reset();
22117
22118 // Complete the long-lived requests.
22119 data_long_lived.Resume();
22120 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
22121 std::string response_long_lived;
22122 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
22123 IsOk());
22124 EXPECT_EQ("long-lived", response_long_lived);
22125 trans_long_lived.reset();
22126
22127 data_bar.Resume();
22128 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
22129 std::string response_long_lived_bar;
22130 EXPECT_THAT(
22131 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
22132 IsOk());
22133 EXPECT_EQ("long-lived", response_long_lived_bar);
22134 trans_long_lived_bar.reset();
22135
22136 // Run the post-authentication requests.
22137 TestCompletionCallback callback_post_auth;
22138 auto trans_post_auth =
22139 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22140 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
22141 NetLogWithSource());
22142 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
22143 std::string response_post_auth;
22144 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
22145 IsOk());
22146 EXPECT_EQ("post-auth", response_post_auth);
22147 trans_post_auth.reset();
22148
22149 TestCompletionCallback callback_post_auth_bar;
22150 auto trans_post_auth_bar =
22151 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22152 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
22153 callback_post_auth_bar.callback(),
22154 NetLogWithSource());
22155 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
22156 std::string response_post_auth_bar;
22157 EXPECT_THAT(
22158 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
22159 IsOk());
22160 EXPECT_EQ("post-auth", response_post_auth_bar);
22161 trans_post_auth_bar.reset();
22162}
22163
[email protected]89ceba9a2009-03-21 03:46:0622164} // namespace net