blob: f8fcca106f792174b2f78154b70b17b8a38066b2 [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"
Titouan Rigoudyba507a882020-07-31 12:15:1546#include "net/base/ip_address.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3747#include "net/base/ip_endpoint.h"
[email protected]58e32bb2013-01-21 18:23:2548#include "net/base/load_timing_info.h"
49#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2450#include "net/base/net_errors.h"
Matt Menkebdf777802019-04-22 19:38:5951#include "net/base/privacy_mode.h"
tbansal28e68f82016-02-04 02:56:1552#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4053#include "net/base/proxy_server.h"
[email protected]ac790b42009-12-02 04:31:3154#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5255#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1556#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0657#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2158#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0859#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1160#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5361#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2462#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1263#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0064#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2965#include "net/http/http_auth_handler_ntlm.h"
Asanka Herathbf0b55d2019-12-07 03:27:0966#include "net/http/http_auth_ntlm_mechanism.h"
aberentbba302d2015-12-03 10:20:1967#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5768#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5269#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5670#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0471#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2472#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1373#include "net/http/http_response_info.h"
Matt Menke609160742019-08-02 18:47:2674#include "net/http/http_server_properties.h"
[email protected]0877e3d2009-10-17 22:29:5775#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3876#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1977#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0778#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0079#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1980#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5181#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4682#include "net/log/test_net_log_util.h"
Nicolas Arciniegad2013f92020-02-07 23:00:5683#include "net/proxy_resolution/configured_proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4084#include "net/proxy_resolution/mock_proxy_resolver.h"
85#include "net/proxy_resolution/proxy_config_service_fixed.h"
86#include "net/proxy_resolution/proxy_info.h"
87#include "net/proxy_resolution/proxy_resolver.h"
88#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4489#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1590#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0391#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3692#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4793#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0294#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0795#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0496#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4497#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1298#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:4499#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:58100#include "net/spdy/spdy_session.h"
101#include "net/spdy/spdy_session_pool.h"
102#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:04103#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57104#include "net/ssl/ssl_cert_request_info.h"
David Benjaminef2f2a5a2019-07-16 19:21:31105#include "net/ssl/ssl_config.h"
[email protected]e86839fd2013-08-14 18:29:03106#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57107#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54108#include "net/ssl/ssl_private_key.h"
David Benjamin151ec6b2019-08-02 19:38:52109#include "net/ssl/test_ssl_config_service.h"
[email protected]6e7845ae2013-03-29 21:48:11110#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01111#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43112#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:40113#include "net/test/test_with_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14114#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23115#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00116#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44117#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06118#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18119#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52120#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15121#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27122#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52123
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37124#if defined(NTLM_PORTABLE)
125#include "base/base64.h"
126#include "net/ntlm/ntlm_test_data.h"
127#endif
128
Douglas Creager3cb042052018-11-06 23:08:52129#if BUILDFLAG(ENABLE_REPORTING)
130#include "net/network_error_logging/network_error_logging_service.h"
131#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14132#include "net/reporting/reporting_cache.h"
Lily Chenfc92ff42019-05-06 22:59:10133#include "net/reporting/reporting_endpoint.h"
Douglas Creager134b52e2018-11-09 18:00:14134#include "net/reporting/reporting_header_parser.h"
135#include "net/reporting/reporting_service.h"
136#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52137#endif // BUILDFLAG(ENABLE_REPORTING)
138
robpercival214763f2016-07-01 23:27:01139using net::test::IsError;
140using net::test::IsOk;
141
[email protected]ad65a3e2013-12-25 18:18:01142using base::ASCIIToUTF16;
143
David Benjamin3b94b0f2019-04-25 23:07:52144using testing::AnyOf;
Titouan Rigoudyba507a882020-07-31 12:15:15145using testing::ElementsAre;
146using testing::IsEmpty;
David Benjamin3b94b0f2019-04-25 23:07:52147
initial.commit586acc5fe2008-07-26 22:42:52148//-----------------------------------------------------------------------------
149
ttuttle859dc7a2015-04-23 19:42:29150namespace net {
151
[email protected]13c8a092010-07-29 06:15:44152namespace {
153
[email protected]42cba2fb2013-03-29 19:58:57154const base::string16 kBar(ASCIIToUTF16("bar"));
155const base::string16 kBar2(ASCIIToUTF16("bar2"));
156const base::string16 kBar3(ASCIIToUTF16("bar3"));
157const base::string16 kBaz(ASCIIToUTF16("baz"));
158const base::string16 kFirst(ASCIIToUTF16("first"));
159const base::string16 kFoo(ASCIIToUTF16("foo"));
160const base::string16 kFoo2(ASCIIToUTF16("foo2"));
161const base::string16 kFoo3(ASCIIToUTF16("foo3"));
162const base::string16 kFou(ASCIIToUTF16("fou"));
163const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57164const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44165
bnc2df4b522016-07-08 18:17:43166const char kAlternativeServiceHttpHeader[] =
167 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
168
ttuttle859dc7a2015-04-23 19:42:29169int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40170 return session
171 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
172 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29173 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02174}
175
ttuttle859dc7a2015-04-23 19:42:29176bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40177 return session
178 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
179 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29180 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52181}
182
[email protected]f3da152d2012-06-02 01:00:57183// Takes in a Value created from a NetLogHttpResponseParameter, and returns
184// a JSONified list of headers as a single string. Uses single quotes instead
Eric Roman79cc7552019-07-19 02:17:54185// of double quotes for easier comparison.
186std::string GetHeaders(const base::Value& params) {
187 if (!params.is_dict())
188 return "";
189 const base::Value* header_list = params.FindListKey("headers");
190 if (!header_list)
191 return "";
192 std::string headers;
193 base::JSONWriter::Write(*header_list, &headers);
194 base::ReplaceChars(headers, "\"", "'", &headers);
195 return headers;
[email protected]f3da152d2012-06-02 01:00:57196}
197
[email protected]029c83b62013-01-24 05:28:20198// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
199// used.
ttuttle859dc7a2015-04-23 19:42:29200void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20201 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19202 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25203
[email protected]029c83b62013-01-24 05:28:20204 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
205 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
206
ttuttle859dc7a2015-04-23 19:42:29207 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20208 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25209
210 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25211
[email protected]3b23a222013-05-15 21:33:25212 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25213 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
214 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25215 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25216}
217
[email protected]029c83b62013-01-24 05:28:20218// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
219// used.
ttuttle859dc7a2015-04-23 19:42:29220void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25221 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20222 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19223 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20224
225 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
226 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
227
ttuttle859dc7a2015-04-23 19:42:29228 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
229 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20230 EXPECT_LE(load_timing_info.connect_timing.connect_end,
231 load_timing_info.send_start);
232
233 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20234
[email protected]3b23a222013-05-15 21:33:25235 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20236 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
237 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25238 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20239}
240
241// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
242// used.
ttuttle859dc7a2015-04-23 19:42:29243void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20244 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19245 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20246
ttuttle859dc7a2015-04-23 19:42:29247 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20248
249 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
250 EXPECT_LE(load_timing_info.proxy_resolve_start,
251 load_timing_info.proxy_resolve_end);
252 EXPECT_LE(load_timing_info.proxy_resolve_end,
253 load_timing_info.send_start);
254 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20255
[email protected]3b23a222013-05-15 21:33:25256 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20257 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
258 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25259 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20260}
261
262// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
263// used.
ttuttle859dc7a2015-04-23 19:42:29264void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20265 int connect_timing_flags) {
266 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19267 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20268
269 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
270 EXPECT_LE(load_timing_info.proxy_resolve_start,
271 load_timing_info.proxy_resolve_end);
272 EXPECT_LE(load_timing_info.proxy_resolve_end,
273 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29274 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
275 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20276 EXPECT_LE(load_timing_info.connect_timing.connect_end,
277 load_timing_info.send_start);
278
279 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20280
[email protected]3b23a222013-05-15 21:33:25281 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20282 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
283 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25284 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25285}
286
Matt Menke2436b2f2018-12-11 18:07:11287// ProxyResolver that records URLs passed to it, and that can be told what
288// result to return.
289class CapturingProxyResolver : public ProxyResolver {
290 public:
Matt Menke8045afd2019-11-14 20:31:19291 struct LookupInfo {
292 GURL url;
293 NetworkIsolationKey network_isolation_key;
294 };
295
Matt Menke2436b2f2018-12-11 18:07:11296 CapturingProxyResolver()
297 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
298 ~CapturingProxyResolver() override = default;
299
300 int GetProxyForURL(const GURL& url,
Matt Menkecd522ee02019-11-13 19:53:39301 const NetworkIsolationKey& network_isolation_key,
Matt Menke2436b2f2018-12-11 18:07:11302 ProxyInfo* results,
303 CompletionOnceCallback callback,
304 std::unique_ptr<Request>* request,
305 const NetLogWithSource& net_log) override {
306 results->UseProxyServer(proxy_server_);
Matt Menke8045afd2019-11-14 20:31:19307 lookup_info_.push_back(LookupInfo{url, network_isolation_key});
Matt Menke2436b2f2018-12-11 18:07:11308 return OK;
309 }
310
311 // Sets whether the resolver should use direct connections, instead of a
312 // proxy.
313 void set_proxy_server(ProxyServer proxy_server) {
314 proxy_server_ = proxy_server;
315 }
316
Matt Menke8045afd2019-11-14 20:31:19317 const std::vector<LookupInfo>& lookup_info() const { return lookup_info_; }
Matt Menke2436b2f2018-12-11 18:07:11318
319 private:
Matt Menke8045afd2019-11-14 20:31:19320 std::vector<LookupInfo> lookup_info_;
Matt Menke2436b2f2018-12-11 18:07:11321
322 ProxyServer proxy_server_;
323
324 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
325};
326
327class CapturingProxyResolverFactory : public ProxyResolverFactory {
328 public:
329 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
330 : ProxyResolverFactory(false), resolver_(resolver) {}
331
332 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
333 std::unique_ptr<ProxyResolver>* resolver,
334 CompletionOnceCallback callback,
335 std::unique_ptr<Request>* request) override {
336 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
337 return OK;
338 }
339
340 private:
341 ProxyResolver* resolver_;
342};
343
danakj1fd259a02016-04-16 03:17:09344std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42345 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34346 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14347}
348
xunjieli96f2a402017-06-05 17:24:27349class FailingProxyResolverFactory : public ProxyResolverFactory {
350 public:
351 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
352
353 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42354 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
355 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17356 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42357 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27358 return ERR_PAC_SCRIPT_FAILED;
359 }
360};
361
Titouan Rigoudyba507a882020-07-31 12:15:15362// A default minimal HttpRequestInfo for use in tests, targeting HTTP.
Titouan Rigoudy78af7da2020-07-07 14:30:12363HttpRequestInfo DefaultRequestInfo() {
364 HttpRequestInfo info;
365 info.method = "GET";
Titouan Rigoudyba507a882020-07-31 12:15:15366 info.url = GURL("http://foo.test");
Titouan Rigoudy78af7da2020-07-07 14:30:12367 info.traffic_annotation =
368 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
369 return info;
370}
371
Titouan Rigoudyba507a882020-07-31 12:15:15372// The default info for transports to the embedded HTTP server.
373TransportInfo EmbeddedHttpServerTransportInfo() {
374 TransportInfo info;
375 info.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 80);
376 return info;
377}
378
[email protected]448d4ca52012-03-04 04:12:23379} // namespace
380
Bence Béky98447b12018-05-08 03:14:01381class HttpNetworkTransactionTest : public PlatformTest,
Gabriel Charette694c3c332019-08-19 14:53:05382 public WithTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03383 public:
bncd16676a2016-07-20 16:23:01384 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03385 // Important to restore the per-pool limit first, since the pool limit must
386 // always be greater than group limit, and the tests reduce both limits.
387 ClientSocketPoolManager::set_max_sockets_per_pool(
388 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
389 ClientSocketPoolManager::set_max_sockets_per_group(
390 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
391 }
392
[email protected]e3ceb682011-06-28 23:55:46393 protected:
[email protected]23e482282013-06-14 16:08:02394 HttpNetworkTransactionTest()
Gabriel Charette694c3c332019-08-19 14:53:05395 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
Matt Menked6fd2a52019-03-20 06:14:36396 dummy_connect_job_params_(
397 nullptr /* client_socket_factory */,
398 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40399 nullptr /* http_auth_cache */,
400 nullptr /* http_auth_handler_factory */,
401 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13402 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40403 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36404 nullptr /* proxy_delegate */,
405 nullptr /* http_user_agent_settings */,
David Benjamin24725be2019-07-24 20:57:18406 nullptr /* ssl_client_context */,
Matt Menked6fd2a52019-03-20 06:14:36407 nullptr /* socket_performance_watcher_factory */,
408 nullptr /* network_quality_estimator */,
409 nullptr /* net_log */,
410 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56411 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15412 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03413 HttpNetworkSession::NORMAL_SOCKET_POOL)),
414 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
415 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28416 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03417 }
[email protected]bb88e1d32013-05-03 23:11:07418
[email protected]e3ceb682011-06-28 23:55:46419 struct SimpleGetHelperResult {
420 int rv;
421 std::string status_line;
422 std::string response_data;
sclittlefb249892015-09-10 21:33:22423 int64_t total_received_bytes;
424 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25425 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47426 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59427 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46428 };
429
dcheng67be2b1f2014-10-27 21:47:29430 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50431 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55432 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56433 // Set an initial delay to ensure that the first call to TimeTicks::Now()
434 // before incrementing the counter does not return a null value.
Matt Menke6dc08232019-10-03 18:00:28435 FastForwardBy(base::TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54436 }
437
dcheng67be2b1f2014-10-27 21:47:29438 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50439 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55440 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09441 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55442 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09443 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50444 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55445 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09446 }
447
Andrew Comminos1f2ff1cc2018-12-14 05:22:38448 void Check100ResponseTiming(bool use_spdy);
449
[email protected]202965992011-12-07 23:04:51450 // Either |write_failure| specifies a write failure or |read_failure|
451 // specifies a read failure when using a reused socket. In either case, the
452 // failure should cause the network transaction to resend the request, and the
453 // other argument should be NULL.
454 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
455 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52456
[email protected]a34f61ee2014-03-18 20:59:49457 // Either |write_failure| specifies a write failure or |read_failure|
458 // specifies a read failure when using a reused socket. In either case, the
459 // failure should cause the network transaction to resend the request, and the
460 // other argument should be NULL.
461 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10462 const MockRead* read_failure,
Yoichi Osatof17bc892020-08-05 01:49:04463 bool use_spdy,
464 bool upload = false);
[email protected]a34f61ee2014-03-18 20:59:49465
Ryan Sleevib8d7ea02018-05-07 20:01:01466 SimpleGetHelperResult SimpleGetHelperForData(
467 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15468 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52469
[email protected]ff007e162009-05-23 09:13:15470 HttpRequestInfo request;
471 request.method = "GET";
bncce36dca22015-04-21 22:11:23472 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10473 request.traffic_annotation =
474 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52475
Matt Muellerd9342e3a2019-11-26 01:41:14476 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07477 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09478 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16479 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27480
Ryan Sleevib8d7ea02018-05-07 20:01:01481 for (auto* provider : providers) {
482 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29483 }
initial.commit586acc5fe2008-07-26 22:42:52484
[email protected]49639fa2011-12-20 23:22:41485 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52486
eroman24bc6a12015-05-06 19:55:48487 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16488 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01489 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52490
[email protected]ff007e162009-05-23 09:13:15491 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16492 out.total_received_bytes = trans.GetTotalReceivedBytes();
493 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25494
495 // Even in the failure cases that use this function, connections are always
496 // successfully established before the error.
bnc691fda62016-08-12 00:43:16497 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25498 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
499
[email protected]ff007e162009-05-23 09:13:15500 if (out.rv != OK)
501 return out;
502
bnc691fda62016-08-12 00:43:16503 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50504 // Can't use ASSERT_* inside helper functions like this, so
505 // return an error.
wezca1070932016-05-26 20:30:52506 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50507 out.rv = ERR_UNEXPECTED;
508 return out;
509 }
[email protected]ff007e162009-05-23 09:13:15510 out.status_line = response->headers->GetStatusLine();
511
Tsuyoshi Horo01faed62019-02-20 22:11:37512 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
513 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19514
ttuttled9dbc652015-09-29 20:00:59515 bool got_endpoint =
bnc691fda62016-08-12 00:43:16516 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59517 EXPECT_EQ(got_endpoint,
518 out.remote_endpoint_after_start.address().size() > 0);
519
bnc691fda62016-08-12 00:43:16520 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01521 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40522
Eric Roman79cc7552019-07-19 02:17:54523 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:39524 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00525 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
526 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39527 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00528 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
529 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15530
Eric Roman79cc7552019-07-19 02:17:54531 EXPECT_EQ("GET / HTTP/1.1\r\n",
532 GetStringValueFromParams(entries[pos], "line"));
[email protected]f3da152d2012-06-02 01:00:57533
bncce36dca22015-04-21 22:11:23534 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
Eric Roman79cc7552019-07-19 02:17:54535 GetHeaders(entries[pos].params));
[email protected]3deb9a52010-11-11 00:24:40536
bnc691fda62016-08-12 00:43:16537 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22538 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16539 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22540
bnc691fda62016-08-12 00:43:16541 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47542 return out;
[email protected]ff007e162009-05-23 09:13:15543 }
initial.commit586acc5fe2008-07-26 22:42:52544
Ryan Sleevib8d7ea02018-05-07 20:01:01545 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22546 MockWrite data_writes[] = {
547 MockWrite("GET / HTTP/1.1\r\n"
548 "Host: www.example.org\r\n"
549 "Connection: keep-alive\r\n\r\n"),
550 };
[email protected]5a60c8b2011-10-19 20:14:29551
Ryan Sleevib8d7ea02018-05-07 20:01:01552 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22553 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01554 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22555
Ryan Sleevib8d7ea02018-05-07 20:01:01556 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22557 return out;
[email protected]b8015c42013-12-24 15:18:19558 }
559
bnc032658ba2016-09-26 18:17:15560 void AddSSLSocketData() {
561 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49562 ssl_.ssl_info.cert =
563 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
564 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15565 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
566 }
567
[email protected]ff007e162009-05-23 09:13:15568 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
569 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52570
[email protected]ff007e162009-05-23 09:13:15571 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07572
[email protected]bb88e1d32013-05-03 23:11:07573 void CheckErrorIsPassedBack(int error, IoMode mode);
574
David Benjaminbae08ba2019-10-18 21:06:15575 base::RepeatingClosure FastForwardByCallback(base::TimeDelta delta) {
576 return base::BindRepeating(&HttpNetworkTransactionTest::FastForwardBy,
577 base::Unretained(this), delta);
578 }
579
Matt Menked6fd2a52019-03-20 06:14:36580 const CommonConnectJobParams dummy_connect_job_params_;
581
Douglas Creager134b52e2018-11-09 18:00:14582 // These clocks are defined here, even though they're only used in the
583 // Reporting tests below, since they need to be destroyed after
584 // |session_deps_|.
585 base::SimpleTestClock clock_;
586 base::SimpleTestTickClock tick_clock_;
587
[email protected]4bd46222013-05-14 19:32:23588 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07589 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15590 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03591
592 // Original socket limits. Some tests set these. Safest to always restore
593 // them once each test has been run.
594 int old_max_group_sockets_;
595 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15596};
[email protected]231d5a32008-09-13 00:45:27597
[email protected]448d4ca52012-03-04 04:12:23598namespace {
599
[email protected]15a5ccf82008-10-23 19:57:43600// Fill |str| with a long header list that consumes >= |size| bytes.
601void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51602 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19603 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
604 const int sizeof_row = strlen(row);
605 const int num_rows = static_cast<int>(
606 ceil(static_cast<float>(size) / sizeof_row));
607 const int sizeof_data = num_rows * sizeof_row;
608 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43609 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51610
[email protected]4ddaf2502008-10-23 18:26:19611 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43612 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19613}
614
thakis84dff942015-07-28 20:47:38615#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09616uint64_t MockGetMSTime() {
617 // Tue, 23 May 2017 20:13:07 +0000
618 return 131400439870000000;
619}
620
[email protected]385a4672009-03-11 22:21:29621// Alternative functions that eliminate randomness and dependency on the local
622// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37623void MockGenerateRandom(uint8_t* output, size_t n) {
624 // This is set to 0xaa because the client challenge for testing in
625 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
626 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29627}
628
[email protected]fe2bc6a2009-03-23 16:52:20629std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37630 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29631}
thakis84dff942015-07-28 20:47:38632#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29633
Matt Menked6fd2a52019-03-20 06:14:36634class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31635 public:
Matt Menked6fd2a52019-03-20 06:14:36636 explicit CaptureGroupIdTransportSocketPool(
637 const CommonConnectJobParams* common_connect_job_params)
638 : TransportClientSocketPool(0,
639 0,
640 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36641 ProxyServer::Direct(),
642 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52643 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18644
Matt Menkef6edce752019-03-19 17:21:56645 const ClientSocketPool::GroupId& last_group_id_received() const {
646 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49647 }
648
Tarun Bansal162eabe52018-01-20 01:16:39649 bool socket_requested() const { return socket_requested_; }
650
Matt Menke28ac03e2019-02-25 22:25:50651 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56652 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03653 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28654 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50655 RequestPriority priority,
656 const SocketTag& socket_tag,
657 ClientSocketPool::RespectLimits respect_limits,
658 ClientSocketHandle* handle,
659 CompletionOnceCallback callback,
660 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
661 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56662 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39663 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31664 return ERR_IO_PENDING;
665 }
Matt Menkef6edce752019-03-19 17:21:56666 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21667 ClientSocketHandle* handle,
668 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56669 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09670 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24671 int64_t generation) override {}
Matt Menke433de6d2020-03-04 00:24:11672 void CloseIdleSockets(const char* net_log_reason_utf8) override {}
673 void CloseIdleSocketsInGroup(const ClientSocketPool::GroupId& group_id,
674 const char* net_log_reason_utf8) override {}
dmichaeld6e570d2014-12-18 22:30:57675 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56676 size_t IdleSocketCountInGroup(
677 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31678 return 0;
679 }
Matt Menkef6edce752019-03-19 17:21:56680 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57681 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31682 return LOAD_STATE_IDLE;
683 }
[email protected]d80a4322009-08-14 07:07:49684
685 private:
Matt Menkef6edce752019-03-19 17:21:56686 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39687 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31688};
689
[email protected]231d5a32008-09-13 00:45:27690//-----------------------------------------------------------------------------
691
[email protected]79cb5c12011-09-12 13:12:04692// Helper functions for validating that AuthChallengeInfo's are correctly
693// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58694bool CheckBasicServerAuth(
695 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04696 if (!auth_challenge)
697 return false;
698 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43699 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04700 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19701 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04702 return true;
703}
704
David Benjamin2eb827f2019-04-29 18:31:04705bool CheckBasicSecureServerAuth(
706 const base::Optional<AuthChallengeInfo>& auth_challenge) {
707 if (!auth_challenge)
708 return false;
709 EXPECT_FALSE(auth_challenge->is_proxy);
710 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
711 EXPECT_EQ("MyRealm1", auth_challenge->realm);
712 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
713 return true;
714}
715
Emily Starkf2c9bbd2019-04-09 17:08:58716bool CheckBasicProxyAuth(
717 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04718 if (!auth_challenge)
719 return false;
720 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43721 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
722 EXPECT_EQ("MyRealm1", auth_challenge->realm);
723 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
724 return true;
725}
726
Emily Starkf2c9bbd2019-04-09 17:08:58727bool CheckBasicSecureProxyAuth(
728 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43729 if (!auth_challenge)
730 return false;
731 EXPECT_TRUE(auth_challenge->is_proxy);
732 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04733 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19734 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04735 return true;
736}
737
Emily Starkf2c9bbd2019-04-09 17:08:58738bool CheckDigestServerAuth(
739 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04740 if (!auth_challenge)
741 return false;
742 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43743 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04744 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19745 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04746 return true;
747}
748
thakis84dff942015-07-28 20:47:38749#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58750bool CheckNTLMServerAuth(
751 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04752 if (!auth_challenge)
753 return false;
754 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55755 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04756 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19757 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04758 return true;
759}
David Benjamin5cb91132018-04-06 05:54:49760
Emily Starkf2c9bbd2019-04-09 17:08:58761bool CheckNTLMProxyAuth(
762 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49763 if (!auth_challenge)
764 return false;
765 EXPECT_TRUE(auth_challenge->is_proxy);
766 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
767 EXPECT_EQ(std::string(), auth_challenge->realm);
768 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
769 return true;
770}
thakis84dff942015-07-28 20:47:38771#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04772
[email protected]448d4ca52012-03-04 04:12:23773} // namespace
774
Shivani Sharma8ae506c2019-07-21 21:08:27775// TODO(950069): Add testing for frame_origin in NetworkIsolationKey
776// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
777
bncd16676a2016-07-20 16:23:01778TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09779 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16780 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27781}
782
bncd16676a2016-07-20 16:23:01783TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27784 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35785 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
786 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06787 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27788 };
Ryan Sleevib8d7ea02018-05-07 20:01:01789 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01790 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27791 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
792 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01793 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22794 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47795 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59796
797 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27798}
799
800// Response with no status line.
bncd16676a2016-07-20 16:23:01801TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27802 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35803 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06804 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27805 };
Ryan Sleevib8d7ea02018-05-07 20:01:01806 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41807 EXPECT_THAT(out.rv, IsOk());
808 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
809 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01810 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41811 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27812}
813
mmenkea7da6da2016-09-01 21:56:52814// Response with no status line, and a weird port. Should fail by default.
815TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
816 MockRead data_reads[] = {
817 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
818 };
819
Ryan Sleevib8d7ea02018-05-07 20:01:01820 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52821 session_deps_.socket_factory->AddSocketDataProvider(&data);
822
823 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
824
krasinc06a72a2016-12-21 03:42:46825 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58826 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19827 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52828
mmenkea7da6da2016-09-01 21:56:52829 request.method = "GET";
830 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10831 request.traffic_annotation =
832 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
833
mmenkea7da6da2016-09-01 21:56:52834 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20835 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52836 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
837}
838
Shivani Sharmafdcaefd2017-11-02 00:12:26839// Tests that request info can be destroyed after the headers phase is complete.
840TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
841 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
842 auto trans =
843 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
844
845 MockRead data_reads[] = {
846 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
847 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
848 };
Ryan Sleevib8d7ea02018-05-07 20:01:01849 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26850 session_deps_.socket_factory->AddSocketDataProvider(&data);
851
852 TestCompletionCallback callback;
853
854 {
855 auto request = std::make_unique<HttpRequestInfo>();
856 request->method = "GET";
857 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10858 request->traffic_annotation =
859 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26860
861 int rv =
862 trans->Start(request.get(), callback.callback(), NetLogWithSource());
863
864 EXPECT_THAT(callback.GetResult(rv), IsOk());
865 } // Let request info be destroyed.
866
867 trans.reset();
868}
869
dalyk6d7a8c52019-12-18 21:43:01870// Test that a failure in resolving the hostname is retrievable.
871TEST_F(HttpNetworkTransactionTest, SimpleGETHostResolutionFailure) {
872 HttpRequestInfo request;
873 request.method = "GET";
874 request.url = GURL("http://www.example.org/");
875 request.traffic_annotation =
876 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
877
878 RecordingTestNetLog log;
879 MockHostResolver* resolver = new MockHostResolver();
880 resolver->rules()->AddSimulatedTimeoutFailure("www.example.org");
881 session_deps_.net_log = &log;
882 session_deps_.host_resolver.reset(resolver);
883 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
884 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
885 TestCompletionCallback callback;
886
887 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
888 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
889 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
890
891 const HttpResponseInfo* response = trans.GetResponseInfo();
892 ASSERT_TRUE(response);
893 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
894}
895
Titouan Rigoudy78af7da2020-07-07 14:30:12896// This test verifies that if the transaction fails before even connecting to a
897// remote endpoint, the ConnectedCallback is never called.
898TEST_F(HttpNetworkTransactionTest, ConnectedCallbackNeverCalled) {
899 auto resolver = std::make_unique<MockHostResolver>();
Titouan Rigoudyba507a882020-07-31 12:15:15900 resolver->rules()->AddSimulatedTimeoutFailure("bar.test");
Titouan Rigoudy78af7da2020-07-07 14:30:12901 session_deps_.host_resolver = std::move(resolver);
902
903 ConnectedHandler connected_handler;
904 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
Titouan Rigoudyba507a882020-07-31 12:15:15905
Titouan Rigoudy78af7da2020-07-07 14:30:12906 auto request = DefaultRequestInfo();
Titouan Rigoudyba507a882020-07-31 12:15:15907 request.url = GURL("http://bar.test");
908
Titouan Rigoudy78af7da2020-07-07 14:30:12909 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
910 transaction.SetConnectedCallback(connected_handler.Callback());
911
912 TestCompletionCallback callback;
913 transaction.Start(&request, callback.callback(), NetLogWithSource());
914 callback.WaitForResult();
915
Titouan Rigoudyba507a882020-07-31 12:15:15916 EXPECT_THAT(connected_handler.transports(), IsEmpty());
Titouan Rigoudy78af7da2020-07-07 14:30:12917}
918
919// This test verifies that if the ConnectedCallback returns an error, the
920// entire transaction fails with that error.
921TEST_F(HttpNetworkTransactionTest, ConnectedCallbackFailure) {
922 // The exact error code does not matter, as long as it is the same one
923 // returned by the transaction overall.
924 ConnectedHandler connected_handler;
925 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
926
927 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
928 auto request = DefaultRequestInfo();
929 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
930 transaction.SetConnectedCallback(connected_handler.Callback());
931
932 // We never get to writing any data, but we still need a socket.
933 StaticSocketDataProvider data;
934 session_deps_.socket_factory->AddSocketDataProvider(&data);
935
936 TestCompletionCallback callback;
937 EXPECT_THAT(
938 transaction.Start(&request, callback.callback(), NetLogWithSource()),
939 IsError(ERR_IO_PENDING));
940 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));
941
Titouan Rigoudyba507a882020-07-31 12:15:15942 EXPECT_THAT(connected_handler.transports(),
943 ElementsAre(EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:12944}
945
946// This test verifies that the ConnectedCallback is called once in the case of
947// simple requests.
948TEST_F(HttpNetworkTransactionTest, ConnectedCallbackCalledOnce) {
949 MockRead data_reads[] = {
950 MockRead("HTTP/1.0 200 OK\r\n"),
951 MockRead(SYNCHRONOUS, OK),
952 };
953 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
954 session_deps_.socket_factory->AddSocketDataProvider(&data);
955
956 ConnectedHandler connected_handler;
957 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
958 auto request = DefaultRequestInfo();
959 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
960 transaction.SetConnectedCallback(connected_handler.Callback());
961
962 TestCompletionCallback callback;
963 EXPECT_THAT(
964 transaction.Start(&request, callback.callback(), NetLogWithSource()),
965 IsError(ERR_IO_PENDING));
966 EXPECT_THAT(callback.WaitForResult(), IsOk());
967
Titouan Rigoudyba507a882020-07-31 12:15:15968 EXPECT_THAT(connected_handler.transports(),
969 ElementsAre(EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:12970}
971
972// This test verifies that the ConnectedCallback is called once more per
973// authentication challenge.
974TEST_F(HttpNetworkTransactionTest, ConnectedCallbackCalledOnEachAuthChallenge) {
975 ConnectedHandler connected_handler;
976 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
977 auto request = DefaultRequestInfo();
978 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
979 transaction.SetConnectedCallback(connected_handler.Callback());
980
981 // First request receives an auth challenge.
982 MockRead data_reads1[] = {
983 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
984 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
985 MockRead(SYNCHRONOUS, ERR_FAILED),
986 };
987 StaticSocketDataProvider data1(data_reads1, base::span<MockWrite>());
988 session_deps_.socket_factory->AddSocketDataProvider(&data1);
989
990 // Second request is allowed through.
991 MockRead data_reads2[] = {
992 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
993 MockRead(SYNCHRONOUS, OK),
994 };
995 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
996 session_deps_.socket_factory->AddSocketDataProvider(&data2);
997
998 // First request, connects once.
999 TestCompletionCallback callback1;
1000 EXPECT_THAT(
1001 transaction.Start(&request, callback1.callback(), NetLogWithSource()),
1002 IsError(ERR_IO_PENDING));
1003 EXPECT_THAT(callback1.WaitForResult(), IsOk());
1004
Titouan Rigoudyba507a882020-07-31 12:15:151005 EXPECT_THAT(connected_handler.transports(),
1006 ElementsAre(EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:121007
1008 // Second request, connects again.
1009 TestCompletionCallback callback2;
1010 EXPECT_THAT(transaction.RestartWithAuth(AuthCredentials(kFoo, kBar),
1011 callback2.callback()),
1012 IsError(ERR_IO_PENDING));
1013 EXPECT_THAT(callback2.WaitForResult(), IsOk());
1014
Titouan Rigoudyba507a882020-07-31 12:15:151015 EXPECT_THAT(connected_handler.transports(),
1016 ElementsAre(EmbeddedHttpServerTransportInfo(),
1017 EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:121018}
1019
1020// This test verifies that the ConnectedCallback is called once more per retry.
1021TEST_F(HttpNetworkTransactionTest, ConnectedCallbackCalledOnEachRetry) {
1022 ConnectedHandler connected_handler;
1023 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
1024 auto request = DefaultRequestInfo();
1025 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1026 transaction.SetConnectedCallback(connected_handler.Callback());
1027
1028 // First request receives a retryable error.
1029 MockRead data_reads1[] = {
1030 MockRead(SYNCHRONOUS, ERR_HTTP2_SERVER_REFUSED_STREAM),
1031 };
1032 StaticSocketDataProvider data1(data_reads1, base::span<MockWrite>());
1033 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1034
1035 // Second request is allowed through.
1036 MockRead data_reads2[] = {
1037 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1038 MockRead(SYNCHRONOUS, OK),
1039 };
1040 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
1041 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1042
1043 TestCompletionCallback callback1;
1044 EXPECT_THAT(
1045 transaction.Start(&request, callback1.callback(), NetLogWithSource()),
1046 IsError(ERR_IO_PENDING));
1047 EXPECT_THAT(callback1.WaitForResult(), IsOk());
1048
Titouan Rigoudyba507a882020-07-31 12:15:151049 EXPECT_THAT(connected_handler.transports(),
1050 ElementsAre(EmbeddedHttpServerTransportInfo(),
1051 EmbeddedHttpServerTransportInfo()));
Titouan Rigoudy78af7da2020-07-07 14:30:121052}
1053
[email protected]231d5a32008-09-13 00:45:271054// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:011055TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:271056 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351057 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:061058 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271059 };
Ryan Sleevib8d7ea02018-05-07 20:01:011060 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011061 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:271062 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1063 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011064 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221065 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:271066}
1067
1068// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:011069TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:271070 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351071 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:061072 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271073 };
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]231d5a32008-09-13 00:45:271076 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1077 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011078 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221079 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:271080}
1081
1082// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:011083TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:271084 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351085 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:061086 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271087 };
Ryan Sleevib8d7ea02018-05-07 20:01:011088 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411089 EXPECT_THAT(out.rv, IsOk());
1090 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1091 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011092 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411093 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:271094}
1095
1096// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:011097TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:271098 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351099 MockRead("\n"),
1100 MockRead("\n"),
1101 MockRead("Q"),
1102 MockRead("J"),
1103 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:061104 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271105 };
Ryan Sleevib8d7ea02018-05-07 20:01:011106 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011107 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:271108 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1109 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011110 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221111 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:271112}
1113
1114// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:011115TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:271116 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351117 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:061118 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271119 };
Ryan Sleevib8d7ea02018-05-07 20:01:011120 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411121 EXPECT_THAT(out.rv, IsOk());
1122 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1123 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011124 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411125 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:521126}
1127
[email protected]f9d44aa2008-09-23 23:57:171128// Simulate a 204 response, lacking a Content-Length header, sent over a
1129// persistent connection. The response should still terminate since a 204
1130// cannot have a response body.
bncd16676a2016-07-20 16:23:011131TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:191132 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:171133 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351134 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:191135 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:061136 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:171137 };
Ryan Sleevib8d7ea02018-05-07 20:01:011138 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011139 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:171140 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
1141 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011142 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221143 int64_t response_size = reads_size - strlen(junk);
1144 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:171145}
1146
[email protected]0877e3d2009-10-17 22:29:571147// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:011148TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:191149 std::string final_chunk = "0\r\n\r\n";
1150 std::string extra_data = "HTTP/1.1 200 OK\r\n";
1151 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:571152 MockRead data_reads[] = {
1153 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
1154 MockRead("5\r\nHello\r\n"),
1155 MockRead("1\r\n"),
1156 MockRead(" \r\n"),
1157 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:191158 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:061159 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:571160 };
Ryan Sleevib8d7ea02018-05-07 20:01:011161 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011162 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:571163 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1164 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011165 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221166 int64_t response_size = reads_size - extra_data.size();
1167 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:571168}
1169
[email protected]9fe44f52010-09-23 18:36:001170// Next tests deal with http://crbug.com/56344.
1171
bncd16676a2016-07-20 16:23:011172TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001173 MultipleContentLengthHeadersNoTransferEncoding) {
1174 MockRead data_reads[] = {
1175 MockRead("HTTP/1.1 200 OK\r\n"),
1176 MockRead("Content-Length: 10\r\n"),
1177 MockRead("Content-Length: 5\r\n\r\n"),
1178 };
Ryan Sleevib8d7ea02018-05-07 20:01:011179 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011180 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001181}
1182
bncd16676a2016-07-20 16:23:011183TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041184 DuplicateContentLengthHeadersNoTransferEncoding) {
1185 MockRead data_reads[] = {
1186 MockRead("HTTP/1.1 200 OK\r\n"),
1187 MockRead("Content-Length: 5\r\n"),
1188 MockRead("Content-Length: 5\r\n\r\n"),
1189 MockRead("Hello"),
1190 };
Ryan Sleevib8d7ea02018-05-07 20:01:011191 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011192 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041193 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1194 EXPECT_EQ("Hello", out.response_data);
1195}
1196
bncd16676a2016-07-20 16:23:011197TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041198 ComplexContentLengthHeadersNoTransferEncoding) {
1199 // More than 2 dupes.
1200 {
1201 MockRead data_reads[] = {
1202 MockRead("HTTP/1.1 200 OK\r\n"),
1203 MockRead("Content-Length: 5\r\n"),
1204 MockRead("Content-Length: 5\r\n"),
1205 MockRead("Content-Length: 5\r\n\r\n"),
1206 MockRead("Hello"),
1207 };
Ryan Sleevib8d7ea02018-05-07 20:01:011208 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011209 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041210 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1211 EXPECT_EQ("Hello", out.response_data);
1212 }
1213 // HTTP/1.0
1214 {
1215 MockRead data_reads[] = {
1216 MockRead("HTTP/1.0 200 OK\r\n"),
1217 MockRead("Content-Length: 5\r\n"),
1218 MockRead("Content-Length: 5\r\n"),
1219 MockRead("Content-Length: 5\r\n\r\n"),
1220 MockRead("Hello"),
1221 };
Ryan Sleevib8d7ea02018-05-07 20:01:011222 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011223 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041224 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1225 EXPECT_EQ("Hello", out.response_data);
1226 }
1227 // 2 dupes and one mismatched.
1228 {
1229 MockRead data_reads[] = {
1230 MockRead("HTTP/1.1 200 OK\r\n"),
1231 MockRead("Content-Length: 10\r\n"),
1232 MockRead("Content-Length: 10\r\n"),
1233 MockRead("Content-Length: 5\r\n\r\n"),
1234 };
Ryan Sleevib8d7ea02018-05-07 20:01:011235 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011236 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041237 }
1238}
1239
bncd16676a2016-07-20 16:23:011240TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001241 MultipleContentLengthHeadersTransferEncoding) {
1242 MockRead data_reads[] = {
1243 MockRead("HTTP/1.1 200 OK\r\n"),
1244 MockRead("Content-Length: 666\r\n"),
1245 MockRead("Content-Length: 1337\r\n"),
1246 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1247 MockRead("5\r\nHello\r\n"),
1248 MockRead("1\r\n"),
1249 MockRead(" \r\n"),
1250 MockRead("5\r\nworld\r\n"),
1251 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061252 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001253 };
Ryan Sleevib8d7ea02018-05-07 20:01:011254 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011255 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001256 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1257 EXPECT_EQ("Hello world", out.response_data);
1258}
1259
[email protected]1628fe92011-10-04 23:04:551260// Next tests deal with http://crbug.com/98895.
1261
1262// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011263TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551264 MockRead data_reads[] = {
1265 MockRead("HTTP/1.1 200 OK\r\n"),
1266 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1267 MockRead("Content-Length: 5\r\n\r\n"),
1268 MockRead("Hello"),
1269 };
Ryan Sleevib8d7ea02018-05-07 20:01:011270 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011271 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551272 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1273 EXPECT_EQ("Hello", out.response_data);
1274}
1275
[email protected]54a9c6e52012-03-21 20:10:591276// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011277TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551278 MockRead data_reads[] = {
1279 MockRead("HTTP/1.1 200 OK\r\n"),
1280 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1281 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1282 MockRead("Content-Length: 5\r\n\r\n"),
1283 MockRead("Hello"),
1284 };
Ryan Sleevib8d7ea02018-05-07 20:01:011285 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011286 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591287 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1288 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551289}
1290
1291// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011292TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551293 MockRead data_reads[] = {
1294 MockRead("HTTP/1.1 200 OK\r\n"),
1295 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1296 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1297 MockRead("Content-Length: 5\r\n\r\n"),
1298 MockRead("Hello"),
1299 };
Ryan Sleevib8d7ea02018-05-07 20:01:011300 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011301 EXPECT_THAT(out.rv,
1302 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551303}
1304
[email protected]54a9c6e52012-03-21 20:10:591305// Checks that two identical Location headers result in no error.
1306// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011307TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551308 MockRead data_reads[] = {
1309 MockRead("HTTP/1.1 302 Redirect\r\n"),
1310 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591311 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551312 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061313 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551314 };
1315
1316 HttpRequestInfo request;
1317 request.method = "GET";
1318 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101319 request.traffic_annotation =
1320 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551321
danakj1fd259a02016-04-16 03:17:091322 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161323 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551324
Ryan Sleevib8d7ea02018-05-07 20:01:011325 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071326 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551327
[email protected]49639fa2011-12-20 23:22:411328 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551329
tfarina42834112016-09-22 13:38:201330 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011331 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551332
robpercival214763f2016-07-01 23:27:011333 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551334
bnc691fda62016-08-12 00:43:161335 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521336 ASSERT_TRUE(response);
1337 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551338 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1339 std::string url;
1340 EXPECT_TRUE(response->headers->IsRedirect(&url));
1341 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471342 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551343}
1344
[email protected]1628fe92011-10-04 23:04:551345// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011346TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551347 MockRead data_reads[] = {
1348 MockRead("HTTP/1.1 302 Redirect\r\n"),
1349 MockRead("Location: http://good.com/\r\n"),
1350 MockRead("Location: http://evil.com/\r\n"),
1351 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061352 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551353 };
Ryan Sleevib8d7ea02018-05-07 20:01:011354 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011355 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551356}
1357
[email protected]ef0faf2e72009-03-05 23:27:231358// Do a request using the HEAD method. Verify that we don't try to read the
1359// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011360TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421361 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231362 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231363 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101364 request.traffic_annotation =
1365 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231366
danakj1fd259a02016-04-16 03:17:091367 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161368 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Titouan Rigoudy78af7da2020-07-07 14:30:121369 ConnectedHandler connected_handler;
1370 trans.SetConnectedCallback(connected_handler.Callback());
[email protected]cb9bf6ca2011-01-28 13:15:271371
[email protected]ef0faf2e72009-03-05 23:27:231372 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131373 MockWrite("HEAD / HTTP/1.1\r\n"
1374 "Host: www.example.org\r\n"
1375 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231376 };
1377 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231378 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1379 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231380
mmenked39192ee2015-12-09 00:57:231381 // No response body because the test stops reading here.
1382 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231383 };
1384
Ryan Sleevib8d7ea02018-05-07 20:01:011385 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071386 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231387
[email protected]49639fa2011-12-20 23:22:411388 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231389
tfarina42834112016-09-22 13:38:201390 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011391 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231392
1393 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011394 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231395
bnc691fda62016-08-12 00:43:161396 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521397 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231398
1399 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521400 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231401 EXPECT_EQ(1234, response->headers->GetContentLength());
1402 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471403 EXPECT_TRUE(response->proxy_server.is_direct());
Titouan Rigoudyba507a882020-07-31 12:15:151404 EXPECT_THAT(connected_handler.transports(),
1405 ElementsAre(EmbeddedHttpServerTransportInfo()));
[email protected]ef0faf2e72009-03-05 23:27:231406
1407 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101408 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231409 bool has_server_header = response->headers->EnumerateHeader(
1410 &iter, "Server", &server_header);
1411 EXPECT_TRUE(has_server_header);
1412 EXPECT_EQ("Blah", server_header);
1413
1414 // Reading should give EOF right away, since there is no message body
1415 // (despite non-zero content-length).
1416 std::string response_data;
bnc691fda62016-08-12 00:43:161417 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011418 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231419 EXPECT_EQ("", response_data);
1420}
1421
bncd16676a2016-07-20 16:23:011422TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091423 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521424
1425 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351426 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1427 MockRead("hello"),
1428 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1429 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061430 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521431 };
Ryan Sleevib8d7ea02018-05-07 20:01:011432 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071433 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521434
[email protected]0b0bf032010-09-21 18:08:501435 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521436 "hello", "world"
1437 };
1438
1439 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421440 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521441 request.method = "GET";
bncce36dca22015-04-21 22:11:231442 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101443 request.traffic_annotation =
1444 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521445
bnc691fda62016-08-12 00:43:161446 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271447
[email protected]49639fa2011-12-20 23:22:411448 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521449
tfarina42834112016-09-22 13:38:201450 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011451 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521452
1453 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011454 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521455
bnc691fda62016-08-12 00:43:161456 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521457 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521458
wezca1070932016-05-26 20:30:521459 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251460 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471461 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521462
1463 std::string response_data;
bnc691fda62016-08-12 00:43:161464 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011465 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251466 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521467 }
1468}
1469
bncd16676a2016-07-20 16:23:011470TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091471 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221472 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191473 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221474 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271475
[email protected]1c773ea12009-04-28 19:58:421476 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521477 request.method = "POST";
1478 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271479 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:101480 request.traffic_annotation =
1481 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521482
shivanishab9a143952016-09-19 17:23:411483 // Check the upload progress returned before initialization is correct.
1484 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1485 EXPECT_EQ(0u, progress.size());
1486 EXPECT_EQ(0u, progress.position());
1487
danakj1fd259a02016-04-16 03:17:091488 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161489 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271490
initial.commit586acc5fe2008-07-26 22:42:521491 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351492 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1493 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1494 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061495 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521496 };
Ryan Sleevib8d7ea02018-05-07 20:01:011497 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071498 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521499
[email protected]49639fa2011-12-20 23:22:411500 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521501
tfarina42834112016-09-22 13:38:201502 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011503 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521504
1505 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011506 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521507
bnc691fda62016-08-12 00:43:161508 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521509 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521510
wezca1070932016-05-26 20:30:521511 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251512 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521513
1514 std::string response_data;
bnc691fda62016-08-12 00:43:161515 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011516 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251517 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521518}
1519
[email protected]3a2d3662009-03-27 03:49:141520// This test is almost the same as Ignores100 above, but the response contains
1521// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571522// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011523TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421524 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141525 request.method = "GET";
1526 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101527 request.traffic_annotation =
1528 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141529
danakj1fd259a02016-04-16 03:17:091530 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161531 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271532
[email protected]3a2d3662009-03-27 03:49:141533 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571534 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1535 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141536 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061537 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141538 };
Ryan Sleevib8d7ea02018-05-07 20:01:011539 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071540 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141541
[email protected]49639fa2011-12-20 23:22:411542 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141543
tfarina42834112016-09-22 13:38:201544 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011545 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141546
1547 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011548 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141549
bnc691fda62016-08-12 00:43:161550 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521551 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141552
wezca1070932016-05-26 20:30:521553 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141554 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1555
1556 std::string response_data;
bnc691fda62016-08-12 00:43:161557 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011558 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141559 EXPECT_EQ("hello world", response_data);
1560}
1561
Andrew Comminos517a92c2019-01-14 17:49:561562TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1563 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381564 base::TimeDelta::FromMilliseconds(10);
1565
1566 HttpRequestInfo request;
1567 request.method = "GET";
1568 request.url = GURL("http://www.foo.com/");
1569 request.traffic_annotation =
1570 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1571
1572 std::vector<MockWrite> data_writes = {
1573 MockWrite(ASYNC, 0,
1574 "GET / HTTP/1.1\r\n"
1575 "Host: www.foo.com\r\n"
1576 "Connection: keep-alive\r\n\r\n"),
1577 };
1578
1579 std::vector<MockRead> data_reads = {
1580 // Write one byte of the status line, followed by a pause.
1581 MockRead(ASYNC, 1, "H"),
1582 MockRead(ASYNC, ERR_IO_PENDING, 2),
1583 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1584 MockRead(ASYNC, 4, "hello world"),
1585 MockRead(SYNCHRONOUS, OK, 5),
1586 };
1587
1588 SequencedSocketData data(data_reads, data_writes);
1589 session_deps_.socket_factory->AddSocketDataProvider(&data);
1590
1591 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1592
1593 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1594
1595 TestCompletionCallback callback;
1596
1597 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1598 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1599
1600 data.RunUntilPaused();
1601 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561602 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381603 data.Resume();
1604
1605 rv = callback.WaitForResult();
1606 EXPECT_THAT(rv, IsOk());
1607
1608 const HttpResponseInfo* response = trans.GetResponseInfo();
1609 ASSERT_TRUE(response);
1610
1611 EXPECT_TRUE(response->headers);
1612 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1613
1614 LoadTimingInfo load_timing_info;
1615 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1616 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1617 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561618 // Ensure we didn't include the delay in the TTFB time.
1619 EXPECT_EQ(load_timing_info.receive_headers_start,
1620 load_timing_info.connect_timing.connect_end);
1621 // Ensure that the mock clock advanced at all.
1622 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1623 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381624
1625 std::string response_data;
1626 rv = ReadTransaction(&trans, &response_data);
1627 EXPECT_THAT(rv, IsOk());
1628 EXPECT_EQ("hello world", response_data);
1629}
1630
1631// Tests that the time-to-first-byte reported in a transaction's load timing
1632// info uses the first response, even if 1XX/informational.
1633void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561634 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381635 base::TimeDelta::FromMilliseconds(10);
1636
1637 HttpRequestInfo request;
1638 request.method = "GET";
1639 request.url = GURL("https://www.foo.com/");
1640 request.traffic_annotation =
1641 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1642
1643 SSLSocketDataProvider ssl(ASYNC, OK);
1644 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1645
1646 std::vector<MockWrite> data_writes;
1647 std::vector<MockRead> data_reads;
1648
1649 spdy::SpdySerializedFrame spdy_req(
1650 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1651
1652 spdy::SpdyHeaderBlock spdy_resp1_headers;
1653 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1654 spdy::SpdySerializedFrame spdy_resp1(
1655 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1656 spdy::SpdySerializedFrame spdy_resp2(
1657 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1658 spdy::SpdySerializedFrame spdy_data(
1659 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1660
1661 if (use_spdy) {
1662 ssl.next_proto = kProtoHTTP2;
1663
1664 data_writes = {CreateMockWrite(spdy_req, 0)};
1665
1666 data_reads = {
1667 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1668 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1669 MockRead(SYNCHRONOUS, OK, 5),
1670 };
1671 } else {
1672 data_writes = {
1673 MockWrite(ASYNC, 0,
1674 "GET / HTTP/1.1\r\n"
1675 "Host: www.foo.com\r\n"
1676 "Connection: keep-alive\r\n\r\n"),
1677 };
1678
1679 data_reads = {
1680 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1681 MockRead(ASYNC, ERR_IO_PENDING, 2),
1682
1683 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1684 MockRead(ASYNC, 4, "hello world"),
1685 MockRead(SYNCHRONOUS, OK, 5),
1686 };
1687 }
1688
1689 SequencedSocketData data(data_reads, data_writes);
1690 session_deps_.socket_factory->AddSocketDataProvider(&data);
1691
1692 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1693
1694 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1695
1696 TestCompletionCallback callback;
1697
1698 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1699 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1700
1701 data.RunUntilPaused();
1702 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1703 // the delay before parsing the 200 response.
1704 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561705 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381706 data.Resume();
1707
1708 rv = callback.WaitForResult();
1709 EXPECT_THAT(rv, IsOk());
1710
1711 const HttpResponseInfo* response = trans.GetResponseInfo();
1712 ASSERT_TRUE(response);
1713
1714 LoadTimingInfo load_timing_info;
1715 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1716 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1717 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561718 // Ensure we didn't include the delay in the TTFB time.
1719 EXPECT_EQ(load_timing_info.receive_headers_start,
1720 load_timing_info.connect_timing.connect_end);
1721 // Ensure that the mock clock advanced at all.
1722 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1723 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381724
1725 std::string response_data;
1726 rv = ReadTransaction(&trans, &response_data);
1727 EXPECT_THAT(rv, IsOk());
1728 EXPECT_EQ("hello world", response_data);
1729}
1730
Andrew Comminos517a92c2019-01-14 17:49:561731TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381732 Check100ResponseTiming(false /* use_spdy */);
1733}
1734
Andrew Comminos517a92c2019-01-14 17:49:561735TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381736 Check100ResponseTiming(true /* use_spdy */);
1737}
1738
bncd16676a2016-07-20 16:23:011739TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081740 HttpRequestInfo request;
1741 request.method = "POST";
1742 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101743 request.traffic_annotation =
1744 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081745
danakj1fd259a02016-04-16 03:17:091746 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161747 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081748
1749 MockRead data_reads[] = {
1750 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1751 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381752 };
Ryan Sleevib8d7ea02018-05-07 20:01:011753 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081754 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381755
zmo9528c9f42015-08-04 22:12:081756 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381757
tfarina42834112016-09-22 13:38:201758 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011759 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381760
zmo9528c9f42015-08-04 22:12:081761 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011762 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381763
zmo9528c9f42015-08-04 22:12:081764 std::string response_data;
bnc691fda62016-08-12 00:43:161765 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011766 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081767 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381768}
1769
bncd16676a2016-07-20 16:23:011770TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381771 HttpRequestInfo request;
1772 request.method = "POST";
1773 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101774 request.traffic_annotation =
1775 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381776
danakj1fd259a02016-04-16 03:17:091777 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161778 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271779
[email protected]ee9410e72010-01-07 01:42:381780 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061781 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381782 };
Ryan Sleevib8d7ea02018-05-07 20:01:011783 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071784 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381785
[email protected]49639fa2011-12-20 23:22:411786 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381787
tfarina42834112016-09-22 13:38:201788 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011789 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381790
1791 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011792 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381793}
1794
[email protected]23e482282013-06-14 16:08:021795void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511796 const MockWrite* write_failure,
1797 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421798 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521799 request.method = "GET";
1800 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101801 request.traffic_annotation =
1802 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521803
Matt Muellerd9342e3a2019-11-26 01:41:141804 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071805 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091806 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271807
[email protected]202965992011-12-07 23:04:511808 // Written data for successfully sending both requests.
1809 MockWrite data1_writes[] = {
1810 MockWrite("GET / HTTP/1.1\r\n"
1811 "Host: www.foo.com\r\n"
1812 "Connection: keep-alive\r\n\r\n"),
1813 MockWrite("GET / HTTP/1.1\r\n"
1814 "Host: www.foo.com\r\n"
1815 "Connection: keep-alive\r\n\r\n")
1816 };
1817
1818 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521819 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351820 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1821 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061822 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521823 };
[email protected]202965992011-12-07 23:04:511824
1825 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491826 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511827 data1_writes[1] = *write_failure;
1828 } else {
1829 ASSERT_TRUE(read_failure);
1830 data1_reads[2] = *read_failure;
1831 }
1832
Ryan Sleevib8d7ea02018-05-07 20:01:011833 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071834 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521835
1836 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351837 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1838 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061839 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521840 };
Ryan Sleevib8d7ea02018-05-07 20:01:011841 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071842 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521843
thestig9d3bb0c2015-01-24 00:49:511844 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521845 "hello", "world"
1846 };
1847
mikecironef22f9812016-10-04 03:40:191848 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521849 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411850 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521851
bnc691fda62016-08-12 00:43:161852 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521853
tfarina42834112016-09-22 13:38:201854 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011855 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521856
1857 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011858 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521859
[email protected]58e32bb2013-01-21 18:23:251860 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161861 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251862 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1863 if (i == 0) {
1864 first_socket_log_id = load_timing_info.socket_log_id;
1865 } else {
1866 // The second request should be using a new socket.
1867 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1868 }
1869
bnc691fda62016-08-12 00:43:161870 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521871 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521872
wezca1070932016-05-26 20:30:521873 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471874 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251875 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521876
1877 std::string response_data;
bnc691fda62016-08-12 00:43:161878 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011879 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251880 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521881 }
1882}
[email protected]3d2a59b2008-09-26 19:44:251883
[email protected]a34f61ee2014-03-18 20:59:491884void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1885 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101886 const MockRead* read_failure,
Yoichi Osatof17bc892020-08-05 01:49:041887 bool use_spdy,
1888 bool chunked_upload) {
1889 SpdyTestUtil spdy_util;
[email protected]a34f61ee2014-03-18 20:59:491890 HttpRequestInfo request;
1891 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101892 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101893 request.traffic_annotation =
1894 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491895
Yoichi Osatof17bc892020-08-05 01:49:041896 const char upload_data[] = "foobar";
1897 ChunkedUploadDataStream upload_data_stream(0);
1898 if (chunked_upload) {
1899 request.method = "POST";
1900 upload_data_stream.AppendData(upload_data, base::size(upload_data) - 1,
1901 true);
1902 request.upload_data_stream = &upload_data_stream;
1903 }
1904
Matt Muellerd9342e3a2019-11-26 01:41:141905 RecordingTestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491906 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091907 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491908
[email protected]09356c652014-03-25 15:36:101909 SSLSocketDataProvider ssl1(ASYNC, OK);
1910 SSLSocketDataProvider ssl2(ASYNC, OK);
1911 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361912 ssl1.next_proto = kProtoHTTP2;
1913 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101914 }
1915 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1916 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491917
[email protected]09356c652014-03-25 15:36:101918 // SPDY versions of the request and response.
Yoichi Osatof17bc892020-08-05 01:49:041919
1920 spdy::SpdyHeaderBlock spdy_post_header_block;
1921 spdy_post_header_block[spdy::kHttp2MethodHeader] = "POST";
1922 spdy_util.AddUrlToHeaderBlock(request.url.spec(), &spdy_post_header_block);
1923 spdy::SpdySerializedFrame spdy_request(
1924 chunked_upload
1925 ? spdy_util.ConstructSpdyHeaders(1, std::move(spdy_post_header_block),
1926 DEFAULT_PRIORITY, false)
1927 : spdy_util.ConstructSpdyGet(request.url.spec().c_str(), 1,
1928 DEFAULT_PRIORITY));
1929
1930 spdy::SpdySerializedFrame spdy_request_body(
1931 spdy_util.ConstructSpdyDataFrame(1, "foobar", true));
Ryan Hamilton0239aac2018-05-19 00:03:131932 spdy::SpdySerializedFrame spdy_response(
Yoichi Osatof17bc892020-08-05 01:49:041933 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131934 spdy::SpdySerializedFrame spdy_data(
Yoichi Osatof17bc892020-08-05 01:49:041935 spdy_util.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491936
[email protected]09356c652014-03-25 15:36:101937 // HTTP/1.1 versions of the request and response.
Yoichi Osatof17bc892020-08-05 01:49:041938 const std::string http_request =
1939 std::string(chunked_upload ? "POST" : "GET") +
1940 " / HTTP/1.1\r\n"
[email protected]09356c652014-03-25 15:36:101941 "Host: www.foo.com\r\n"
Yoichi Osatof17bc892020-08-05 01:49:041942 "Connection: keep-alive\r\n" +
1943 (chunked_upload ? "Transfer-Encoding: chunked\r\n\r\n" : "\r\n");
1944 const char* kHttpRequest = http_request.c_str();
[email protected]09356c652014-03-25 15:36:101945 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1946 const char kHttpData[] = "hello";
1947
1948 std::vector<MockRead> data1_reads;
1949 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491950 if (write_failure) {
1951 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101952 data1_writes.push_back(*write_failure);
1953 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491954 } else {
1955 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101956 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411957 data1_writes.push_back(CreateMockWrite(spdy_request));
Yoichi Osatof17bc892020-08-05 01:49:041958 if (chunked_upload)
1959 data1_writes.push_back(CreateMockWrite(spdy_request_body));
[email protected]09356c652014-03-25 15:36:101960 } else {
1961 data1_writes.push_back(MockWrite(kHttpRequest));
Yoichi Osatof17bc892020-08-05 01:49:041962 if (chunked_upload) {
1963 data1_writes.push_back(MockWrite("6\r\nfoobar\r\n"));
1964 data1_writes.push_back(MockWrite("0\r\n\r\n"));
1965 }
[email protected]09356c652014-03-25 15:36:101966 }
1967 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491968 }
1969
Ryan Sleevib8d7ea02018-05-07 20:01:011970 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491971 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1972
[email protected]09356c652014-03-25 15:36:101973 std::vector<MockRead> data2_reads;
1974 std::vector<MockWrite> data2_writes;
1975
1976 if (use_spdy) {
Yoichi Osatof17bc892020-08-05 01:49:041977 int seq = 0;
1978 data2_writes.push_back(CreateMockWrite(spdy_request, seq++, ASYNC));
1979 if (chunked_upload)
1980 data2_writes.push_back(CreateMockWrite(spdy_request_body, seq++, ASYNC));
1981 data2_reads.push_back(CreateMockRead(spdy_response, seq++, ASYNC));
1982 data2_reads.push_back(CreateMockRead(spdy_data, seq++, ASYNC));
1983 data2_reads.push_back(MockRead(ASYNC, OK, seq++));
[email protected]09356c652014-03-25 15:36:101984 } else {
Yoichi Osatof17bc892020-08-05 01:49:041985 int seq = 0;
[email protected]09356c652014-03-25 15:36:101986 data2_writes.push_back(
Yoichi Osatof17bc892020-08-05 01:49:041987 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), seq++));
1988 if (chunked_upload) {
1989 data2_writes.push_back(MockWrite(ASYNC, "6\r\nfoobar\r\n", 11, seq++));
1990 data2_writes.push_back(MockWrite(ASYNC, "0\r\n\r\n", 5, seq++));
1991 }
[email protected]09356c652014-03-25 15:36:101992 data2_reads.push_back(
Yoichi Osatof17bc892020-08-05 01:49:041993 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), seq++));
1994 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), seq++));
1995 data2_reads.push_back(MockRead(ASYNC, OK, seq++));
[email protected]09356c652014-03-25 15:36:101996 }
Ryan Sleevib8d7ea02018-05-07 20:01:011997 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491998 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1999
2000 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:592001 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:492002 // Wait for the preconnect to complete.
2003 // TODO(davidben): Some way to wait for an idle socket count might be handy.
2004 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:232005 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:492006
2007 // Make the request.
2008 TestCompletionCallback callback;
2009
bnc691fda62016-08-12 00:43:162010 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:492011
tfarina42834112016-09-22 13:38:202012 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012013 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:492014
2015 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012016 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:492017
2018 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:162019 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:102020 TestLoadTimingNotReused(
2021 load_timing_info,
2022 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:492023
bnc691fda62016-08-12 00:43:162024 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522025 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:492026
wezca1070932016-05-26 20:30:522027 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:022028 if (response->was_fetched_via_spdy) {
2029 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2030 } else {
2031 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2032 }
[email protected]a34f61ee2014-03-18 20:59:492033
2034 std::string response_data;
bnc691fda62016-08-12 00:43:162035 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012036 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:102037 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:492038}
2039
Biljith Jayan45a41722017-08-16 18:43:142040// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:182041// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:142042// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
2043TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
2044 HttpRequestInfo request;
2045 request.method = "GET";
2046 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102047 request.traffic_annotation =
2048 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:142049
2050 // Check whether we give up after the third try.
2051
2052 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:132053 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:142054 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:132055 spdy::SpdySerializedFrame spdy_response_go_away(
2056 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:012057 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
2058 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:142059
2060 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:012061 StaticSocketDataProvider data1(data_read1, data_write);
2062 StaticSocketDataProvider data2(data_read1, data_write);
2063 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:142064
2065 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2066 AddSSLSocketData();
2067 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2068 AddSSLSocketData();
2069 session_deps_.socket_factory->AddSocketDataProvider(&data3);
2070 AddSSLSocketData();
2071
2072 TestCompletionCallback callback;
2073 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2074 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2075
2076 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2077 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2078
2079 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:182080 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:142081}
2082
2083TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
2084 HttpRequestInfo request;
2085 request.method = "GET";
2086 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102087 request.traffic_annotation =
2088 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:142089
2090 // Check whether we try atleast thrice before giving up.
2091
2092 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:132093 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:142094 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:132095 spdy::SpdySerializedFrame spdy_response_go_away(
2096 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:012097 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
2098 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:142099
2100 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:132101 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:142102 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:132103 spdy::SpdySerializedFrame spdy_data(
2104 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:142105 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
2106 CreateMockRead(spdy_data, 2)};
2107
2108 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:012109 StaticSocketDataProvider data1(data_read1, data_write);
2110 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:142111 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:012112 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:142113
2114 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2115 AddSSLSocketData();
2116 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2117 AddSSLSocketData();
2118 session_deps_.socket_factory->AddSocketDataProvider(&data3);
2119 AddSSLSocketData();
2120
2121 TestCompletionCallback callback;
2122 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2123 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2124
2125 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2126 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2127
2128 rv = callback.WaitForResult();
2129 EXPECT_THAT(rv, IsOk());
2130}
2131
bncd16676a2016-07-20 16:23:012132TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:062133 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352134 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:512135}
2136
bncd16676a2016-07-20 16:23:012137TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:062138 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352139 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:252140}
2141
bncd16676a2016-07-20 16:23:012142TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:062143 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352144 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:252145}
2146
[email protected]d58ceea82014-06-04 10:55:542147// Make sure that on a 408 response (Request Timeout), the request is retried,
2148// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:012149TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:542150 MockRead read_failure(SYNCHRONOUS,
2151 "HTTP/1.1 408 Request Timeout\r\n"
2152 "Connection: Keep-Alive\r\n"
2153 "Content-Length: 6\r\n\r\n"
2154 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352155 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:542156}
2157
bncd16676a2016-07-20 16:23:012158TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:492159 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Yoichi Osatof17bc892020-08-05 01:49:042160 PreconnectErrorResendRequestTest(&write_failure, nullptr,
2161 false /* use_spdy */);
2162 PreconnectErrorResendRequestTest(
2163 &write_failure, nullptr, false /* use_spdy */, true /* chunked_upload */);
[email protected]a34f61ee2014-03-18 20:59:492164}
2165
bncd16676a2016-07-20 16:23:012166TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:492167 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Yoichi Osatof17bc892020-08-05 01:49:042168 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2169 false /* use_spdy */);
2170 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2171 true /* chunked_upload */);
[email protected]a34f61ee2014-03-18 20:59:492172}
2173
bncd16676a2016-07-20 16:23:012174TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:492175 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Yoichi Osatof17bc892020-08-05 01:49:042176 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2177 false /* use_spdy */);
2178 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2179 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102180}
2181
bncd16676a2016-07-20 16:23:012182TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102183 MockRead read_failure(ASYNC, OK); // EOF
Yoichi Osatof17bc892020-08-05 01:49:042184 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2185 false /* use_spdy */);
2186 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2187 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102188}
2189
[email protected]d58ceea82014-06-04 10:55:542190// Make sure that on a 408 response (Request Timeout), the request is retried,
2191// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:012192TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:542193 MockRead read_failure(SYNCHRONOUS,
2194 "HTTP/1.1 408 Request Timeout\r\n"
2195 "Connection: Keep-Alive\r\n"
2196 "Content-Length: 6\r\n\r\n"
2197 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352198 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
Yoichi Osatof17bc892020-08-05 01:49:042199 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2200 false /* use_spdy */);
2201 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2202 true /* chunked_upload */);
[email protected]d58ceea82014-06-04 10:55:542203}
2204
bncd16676a2016-07-20 16:23:012205TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:102206 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Yoichi Osatof17bc892020-08-05 01:49:042207 PreconnectErrorResendRequestTest(&write_failure, nullptr,
2208 true /* use_spdy */);
2209 PreconnectErrorResendRequestTest(&write_failure, nullptr, true /* use_spdy */,
2210 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102211}
2212
bncd16676a2016-07-20 16:23:012213TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:102214 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Yoichi Osatof17bc892020-08-05 01:49:042215 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2216 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2217 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102218}
2219
bncd16676a2016-07-20 16:23:012220TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:102221 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Yoichi Osatof17bc892020-08-05 01:49:042222 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2223 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2224 true /* chunked_upload */);
[email protected]09356c652014-03-25 15:36:102225}
2226
bncd16676a2016-07-20 16:23:012227TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102228 MockRead read_failure(ASYNC, OK); // EOF
Yoichi Osatof17bc892020-08-05 01:49:042229 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2230 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2231 true /* chunked_upload */);
[email protected]a34f61ee2014-03-18 20:59:492232}
2233
bncd16676a2016-07-20 16:23:012234TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:422235 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:252236 request.method = "GET";
bncce36dca22015-04-21 22:11:232237 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102238 request.traffic_annotation =
2239 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252240
danakj1fd259a02016-04-16 03:17:092241 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162242 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272243
[email protected]3d2a59b2008-09-26 19:44:252244 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062245 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352246 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2247 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062248 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252249 };
Ryan Sleevib8d7ea02018-05-07 20:01:012250 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072251 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252252
[email protected]49639fa2011-12-20 23:22:412253 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252254
tfarina42834112016-09-22 13:38:202255 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012256 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252257
2258 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012259 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592260
2261 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162262 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592263 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252264}
2265
2266// What do various browsers do when the server closes a non-keepalive
2267// connection without sending any response header or body?
2268//
2269// IE7: error page
2270// Safari 3.1.2 (Windows): error page
2271// Firefox 3.0.1: blank page
2272// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422273// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2274// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012275TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252276 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062277 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352278 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2279 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062280 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252281 };
Ryan Sleevib8d7ea02018-05-07 20:01:012282 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012283 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252284}
[email protected]1826a402014-01-08 15:40:482285
[email protected]7a5378b2012-11-04 03:25:172286// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2287// tests. There was a bug causing HttpNetworkTransaction to hang in the
2288// destructor in such situations.
2289// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012290TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172291 HttpRequestInfo request;
2292 request.method = "GET";
bncce36dca22015-04-21 22:11:232293 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102294 request.traffic_annotation =
2295 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172296
danakj1fd259a02016-04-16 03:17:092297 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582298 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192299 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172300
2301 MockRead data_reads[] = {
2302 MockRead("HTTP/1.0 200 OK\r\n"),
2303 MockRead("Connection: keep-alive\r\n"),
2304 MockRead("Content-Length: 100\r\n\r\n"),
2305 MockRead("hello"),
2306 MockRead(SYNCHRONOUS, 0),
2307 };
Ryan Sleevib8d7ea02018-05-07 20:01:012308 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072309 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172310
2311 TestCompletionCallback callback;
2312
tfarina42834112016-09-22 13:38:202313 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012314 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172315
2316 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012317 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172318
Victor Costan9c7302b2018-08-27 16:39:442319 scoped_refptr<IOBufferWithSize> io_buf =
2320 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502321 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172322 if (rv == ERR_IO_PENDING)
2323 rv = callback.WaitForResult();
2324 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502325 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012326 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172327
2328 trans.reset();
fdoray92e35a72016-06-10 15:54:552329 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172330 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2331}
2332
bncd16676a2016-07-20 16:23:012333TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172334 HttpRequestInfo request;
2335 request.method = "GET";
bncce36dca22015-04-21 22:11:232336 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102337 request.traffic_annotation =
2338 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172339
danakj1fd259a02016-04-16 03:17:092340 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582341 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192342 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172343
2344 MockRead data_reads[] = {
2345 MockRead("HTTP/1.0 200 OK\r\n"),
2346 MockRead("Connection: keep-alive\r\n"),
2347 MockRead("Content-Length: 100\r\n\r\n"),
2348 MockRead(SYNCHRONOUS, 0),
2349 };
Ryan Sleevib8d7ea02018-05-07 20:01:012350 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072351 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172352
2353 TestCompletionCallback callback;
2354
tfarina42834112016-09-22 13:38:202355 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012356 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172357
2358 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012359 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172360
Victor Costan9c7302b2018-08-27 16:39:442361 scoped_refptr<IOBufferWithSize> io_buf(
2362 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502363 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172364 if (rv == ERR_IO_PENDING)
2365 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012366 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172367
2368 trans.reset();
fdoray92e35a72016-06-10 15:54:552369 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172370 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2371}
2372
[email protected]0b0bf032010-09-21 18:08:502373// Test that we correctly reuse a keep-alive connection after not explicitly
2374// reading the body.
bncd16676a2016-07-20 16:23:012375TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132376 HttpRequestInfo request;
2377 request.method = "GET";
2378 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102379 request.traffic_annotation =
2380 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132381
Matt Muellerd9342e3a2019-11-26 01:41:142382 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072383 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092384 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272385
mmenkecc2298e2015-12-07 18:20:182386 const char* request_data =
2387 "GET / HTTP/1.1\r\n"
2388 "Host: www.foo.com\r\n"
2389 "Connection: keep-alive\r\n\r\n";
2390 MockWrite data_writes[] = {
2391 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2392 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2393 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2394 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2395 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2396 };
2397
[email protected]0b0bf032010-09-21 18:08:502398 // Note that because all these reads happen in the same
2399 // StaticSocketDataProvider, it shows that the same socket is being reused for
2400 // all transactions.
mmenkecc2298e2015-12-07 18:20:182401 MockRead data_reads[] = {
2402 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2403 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2404 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2405 MockRead(ASYNC, 7,
2406 "HTTP/1.1 302 Found\r\n"
2407 "Content-Length: 0\r\n\r\n"),
2408 MockRead(ASYNC, 9,
2409 "HTTP/1.1 302 Found\r\n"
2410 "Content-Length: 5\r\n\r\n"
2411 "hello"),
2412 MockRead(ASYNC, 11,
2413 "HTTP/1.1 301 Moved Permanently\r\n"
2414 "Content-Length: 0\r\n\r\n"),
2415 MockRead(ASYNC, 13,
2416 "HTTP/1.1 301 Moved Permanently\r\n"
2417 "Content-Length: 5\r\n\r\n"
2418 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132419
mmenkecc2298e2015-12-07 18:20:182420 // In the next two rounds, IsConnectedAndIdle returns false, due to
2421 // the set_busy_before_sync_reads(true) call, while the
2422 // HttpNetworkTransaction is being shut down, but the socket is still
2423 // reuseable. See http://crbug.com/544255.
2424 MockRead(ASYNC, 15,
2425 "HTTP/1.1 200 Hunky-Dory\r\n"
2426 "Content-Length: 5\r\n\r\n"),
2427 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132428
mmenkecc2298e2015-12-07 18:20:182429 MockRead(ASYNC, 18,
2430 "HTTP/1.1 200 Hunky-Dory\r\n"
2431 "Content-Length: 5\r\n\r\n"
2432 "he"),
2433 MockRead(SYNCHRONOUS, 19, "llo"),
2434
2435 // The body of the final request is actually read.
2436 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2437 MockRead(ASYNC, 22, "hello"),
2438 };
Ryan Sleevib8d7ea02018-05-07 20:01:012439 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182440 data.set_busy_before_sync_reads(true);
2441 session_deps_.socket_factory->AddSocketDataProvider(&data);
2442
Avi Drissman4365a4782018-12-28 19:26:242443 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502444 std::string response_lines[kNumUnreadBodies];
2445
mikecironef22f9812016-10-04 03:40:192446 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182447 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412448 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132449
Jeremy Roman0579ed62017-08-29 15:56:192450 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582451 session.get());
[email protected]fc31d6a42010-06-24 18:05:132452
tfarina42834112016-09-22 13:38:202453 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012454 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132455
[email protected]58e32bb2013-01-21 18:23:252456 LoadTimingInfo load_timing_info;
2457 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2458 if (i == 0) {
2459 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2460 first_socket_log_id = load_timing_info.socket_log_id;
2461 } else {
2462 TestLoadTimingReused(load_timing_info);
2463 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2464 }
2465
[email protected]fc31d6a42010-06-24 18:05:132466 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182467 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132468
mmenkecc2298e2015-12-07 18:20:182469 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502470 response_lines[i] = response->headers->GetStatusLine();
2471
mmenkecc2298e2015-12-07 18:20:182472 // Delete the transaction without reading the response bodies. Then spin
2473 // the message loop, so the response bodies are drained.
2474 trans.reset();
2475 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132476 }
[email protected]0b0bf032010-09-21 18:08:502477
2478 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182479 "HTTP/1.1 204 No Content",
2480 "HTTP/1.1 205 Reset Content",
2481 "HTTP/1.1 304 Not Modified",
2482 "HTTP/1.1 302 Found",
2483 "HTTP/1.1 302 Found",
2484 "HTTP/1.1 301 Moved Permanently",
2485 "HTTP/1.1 301 Moved Permanently",
2486 "HTTP/1.1 200 Hunky-Dory",
2487 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502488 };
2489
Avi Drissman4365a4782018-12-28 19:26:242490 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272491 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502492
2493 for (int i = 0; i < kNumUnreadBodies; ++i)
2494 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2495
[email protected]49639fa2011-12-20 23:22:412496 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162497 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202498 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012499 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162500 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182501 ASSERT_TRUE(response);
2502 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502503 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2504 std::string response_data;
bnc691fda62016-08-12 00:43:162505 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012506 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502507 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132508}
2509
mmenke5f94fda2016-06-02 20:54:132510// Sockets that receive extra data after a response is complete should not be
2511// reused.
bncd16676a2016-07-20 16:23:012512TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132513 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2514 MockWrite data_writes1[] = {
2515 MockWrite("HEAD / HTTP/1.1\r\n"
2516 "Host: www.borked.com\r\n"
2517 "Connection: keep-alive\r\n\r\n"),
2518 };
2519
2520 MockRead data_reads1[] = {
2521 MockRead("HTTP/1.1 200 OK\r\n"
2522 "Connection: keep-alive\r\n"
2523 "Content-Length: 22\r\n\r\n"
2524 "This server is borked."),
2525 };
2526
2527 MockWrite data_writes2[] = {
2528 MockWrite("GET /foo HTTP/1.1\r\n"
2529 "Host: www.borked.com\r\n"
2530 "Connection: keep-alive\r\n\r\n"),
2531 };
2532
2533 MockRead data_reads2[] = {
2534 MockRead("HTTP/1.1 200 OK\r\n"
2535 "Content-Length: 3\r\n\r\n"
2536 "foo"),
2537 };
Ryan Sleevib8d7ea02018-05-07 20:01:012538 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132539 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012540 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132541 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2542
2543 TestCompletionCallback callback;
2544 HttpRequestInfo request1;
2545 request1.method = "HEAD";
2546 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102547 request1.traffic_annotation =
2548 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132549
bnc87dcefc2017-05-25 12:47:582550 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192551 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202552 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012553 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132554
2555 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2556 ASSERT_TRUE(response1);
2557 ASSERT_TRUE(response1->headers);
2558 EXPECT_EQ(200, response1->headers->response_code());
2559 EXPECT_TRUE(response1->headers->IsKeepAlive());
2560
2561 std::string response_data1;
robpercival214763f2016-07-01 23:27:012562 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132563 EXPECT_EQ("", response_data1);
2564 // Deleting the transaction attempts to release the socket back into the
2565 // socket pool.
2566 trans1.reset();
2567
2568 HttpRequestInfo request2;
2569 request2.method = "GET";
2570 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102571 request2.traffic_annotation =
2572 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132573
bnc87dcefc2017-05-25 12:47:582574 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192575 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202576 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012577 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132578
2579 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2580 ASSERT_TRUE(response2);
2581 ASSERT_TRUE(response2->headers);
2582 EXPECT_EQ(200, response2->headers->response_code());
2583
2584 std::string response_data2;
robpercival214763f2016-07-01 23:27:012585 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132586 EXPECT_EQ("foo", response_data2);
2587}
2588
bncd16676a2016-07-20 16:23:012589TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132590 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2591 MockWrite data_writes1[] = {
2592 MockWrite("GET / HTTP/1.1\r\n"
2593 "Host: www.borked.com\r\n"
2594 "Connection: keep-alive\r\n\r\n"),
2595 };
2596
2597 MockRead data_reads1[] = {
2598 MockRead("HTTP/1.1 200 OK\r\n"
2599 "Connection: keep-alive\r\n"
2600 "Content-Length: 22\r\n\r\n"
2601 "This server is borked."
2602 "Bonus data!"),
2603 };
2604
2605 MockWrite data_writes2[] = {
2606 MockWrite("GET /foo HTTP/1.1\r\n"
2607 "Host: www.borked.com\r\n"
2608 "Connection: keep-alive\r\n\r\n"),
2609 };
2610
2611 MockRead data_reads2[] = {
2612 MockRead("HTTP/1.1 200 OK\r\n"
2613 "Content-Length: 3\r\n\r\n"
2614 "foo"),
2615 };
Ryan Sleevib8d7ea02018-05-07 20:01:012616 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132617 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012618 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132619 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2620
2621 TestCompletionCallback callback;
2622 HttpRequestInfo request1;
2623 request1.method = "GET";
2624 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102625 request1.traffic_annotation =
2626 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132627
bnc87dcefc2017-05-25 12:47:582628 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192629 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202630 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012631 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132632
2633 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2634 ASSERT_TRUE(response1);
2635 ASSERT_TRUE(response1->headers);
2636 EXPECT_EQ(200, response1->headers->response_code());
2637 EXPECT_TRUE(response1->headers->IsKeepAlive());
2638
2639 std::string response_data1;
robpercival214763f2016-07-01 23:27:012640 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132641 EXPECT_EQ("This server is borked.", response_data1);
2642 // Deleting the transaction attempts to release the socket back into the
2643 // socket pool.
2644 trans1.reset();
2645
2646 HttpRequestInfo request2;
2647 request2.method = "GET";
2648 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102649 request2.traffic_annotation =
2650 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132651
bnc87dcefc2017-05-25 12:47:582652 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192653 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202654 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012655 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132656
2657 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2658 ASSERT_TRUE(response2);
2659 ASSERT_TRUE(response2->headers);
2660 EXPECT_EQ(200, response2->headers->response_code());
2661
2662 std::string response_data2;
robpercival214763f2016-07-01 23:27:012663 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132664 EXPECT_EQ("foo", response_data2);
2665}
2666
bncd16676a2016-07-20 16:23:012667TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132668 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2669 MockWrite data_writes1[] = {
2670 MockWrite("GET / HTTP/1.1\r\n"
2671 "Host: www.borked.com\r\n"
2672 "Connection: keep-alive\r\n\r\n"),
2673 };
2674
2675 MockRead data_reads1[] = {
2676 MockRead("HTTP/1.1 200 OK\r\n"
2677 "Connection: keep-alive\r\n"
2678 "Transfer-Encoding: chunked\r\n\r\n"),
2679 MockRead("16\r\nThis server is borked.\r\n"),
2680 MockRead("0\r\n\r\nBonus data!"),
2681 };
2682
2683 MockWrite data_writes2[] = {
2684 MockWrite("GET /foo HTTP/1.1\r\n"
2685 "Host: www.borked.com\r\n"
2686 "Connection: keep-alive\r\n\r\n"),
2687 };
2688
2689 MockRead data_reads2[] = {
2690 MockRead("HTTP/1.1 200 OK\r\n"
2691 "Content-Length: 3\r\n\r\n"
2692 "foo"),
2693 };
Ryan Sleevib8d7ea02018-05-07 20:01:012694 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132695 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012696 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132697 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2698
2699 TestCompletionCallback callback;
2700 HttpRequestInfo request1;
2701 request1.method = "GET";
2702 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102703 request1.traffic_annotation =
2704 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132705
bnc87dcefc2017-05-25 12:47:582706 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192707 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202708 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012709 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132710
2711 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2712 ASSERT_TRUE(response1);
2713 ASSERT_TRUE(response1->headers);
2714 EXPECT_EQ(200, response1->headers->response_code());
2715 EXPECT_TRUE(response1->headers->IsKeepAlive());
2716
2717 std::string response_data1;
robpercival214763f2016-07-01 23:27:012718 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132719 EXPECT_EQ("This server is borked.", response_data1);
2720 // Deleting the transaction attempts to release the socket back into the
2721 // socket pool.
2722 trans1.reset();
2723
2724 HttpRequestInfo request2;
2725 request2.method = "GET";
2726 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102727 request2.traffic_annotation =
2728 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132729
bnc87dcefc2017-05-25 12:47:582730 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192731 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202732 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012733 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132734
2735 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2736 ASSERT_TRUE(response2);
2737 ASSERT_TRUE(response2->headers);
2738 EXPECT_EQ(200, response2->headers->response_code());
2739
2740 std::string response_data2;
robpercival214763f2016-07-01 23:27:012741 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132742 EXPECT_EQ("foo", response_data2);
2743}
2744
2745// This is a little different from the others - it tests the case that the
2746// HttpStreamParser doesn't know if there's extra data on a socket or not when
2747// the HttpNetworkTransaction is torn down, because the response body hasn't
2748// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012749TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132750 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2751 MockWrite data_writes1[] = {
2752 MockWrite("GET / HTTP/1.1\r\n"
2753 "Host: www.borked.com\r\n"
2754 "Connection: keep-alive\r\n\r\n"),
2755 };
2756
2757 MockRead data_reads1[] = {
2758 MockRead("HTTP/1.1 200 OK\r\n"
2759 "Connection: keep-alive\r\n"
2760 "Transfer-Encoding: chunked\r\n\r\n"),
2761 MockRead("16\r\nThis server is borked.\r\n"),
2762 MockRead("0\r\n\r\nBonus data!"),
2763 };
Ryan Sleevib8d7ea02018-05-07 20:01:012764 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132765 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2766
2767 TestCompletionCallback callback;
2768 HttpRequestInfo request1;
2769 request1.method = "GET";
2770 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102771 request1.traffic_annotation =
2772 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132773
bnc87dcefc2017-05-25 12:47:582774 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192775 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582776 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012777 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132778
bnc87dcefc2017-05-25 12:47:582779 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132780 ASSERT_TRUE(response1);
2781 ASSERT_TRUE(response1->headers);
2782 EXPECT_EQ(200, response1->headers->response_code());
2783 EXPECT_TRUE(response1->headers->IsKeepAlive());
2784
2785 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2786 // response body.
bnc87dcefc2017-05-25 12:47:582787 trans.reset();
mmenke5f94fda2016-06-02 20:54:132788
2789 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2790 // socket can't be reused, rather than returning it to the socket pool.
2791 base::RunLoop().RunUntilIdle();
2792
2793 // There should be no idle sockets in the pool.
2794 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2795}
2796
[email protected]038e9a32008-10-08 22:40:162797// Test the request-challenge-retry sequence for basic auth.
2798// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012799TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422800 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162801 request.method = "GET";
bncce36dca22015-04-21 22:11:232802 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102803 request.traffic_annotation =
2804 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162805
Matt Muellerd9342e3a2019-11-26 01:41:142806 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072807 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092808 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162809 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272810
[email protected]f9ee6b52008-11-08 06:46:232811 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232812 MockWrite(
2813 "GET / HTTP/1.1\r\n"
2814 "Host: www.example.org\r\n"
2815 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232816 };
2817
[email protected]038e9a32008-10-08 22:40:162818 MockRead data_reads1[] = {
2819 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2820 // Give a couple authenticate options (only the middle one is actually
2821 // supported).
[email protected]22927ad2009-09-21 19:56:192822 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162823 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2824 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2825 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2826 // Large content-length -- won't matter, as connection will be reset.
2827 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062828 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162829 };
2830
2831 // After calling trans->RestartWithAuth(), this is the request we should
2832 // be issuing -- the final header line contains the credentials.
2833 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232834 MockWrite(
2835 "GET / HTTP/1.1\r\n"
2836 "Host: www.example.org\r\n"
2837 "Connection: keep-alive\r\n"
2838 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162839 };
2840
2841 // Lastly, the server responds with the actual content.
2842 MockRead data_reads2[] = {
2843 MockRead("HTTP/1.0 200 OK\r\n"),
2844 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2845 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062846 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162847 };
2848
Ryan Sleevib8d7ea02018-05-07 20:01:012849 StaticSocketDataProvider data1(data_reads1, data_writes1);
2850 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072851 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2852 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162853
[email protected]49639fa2011-12-20 23:22:412854 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162855
tfarina42834112016-09-22 13:38:202856 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012857 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162858
2859 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012860 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162861
[email protected]58e32bb2013-01-21 18:23:252862 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162863 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252864 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2865
Ryan Sleevib8d7ea02018-05-07 20:01:012866 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162867 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012868 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162869 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192870
bnc691fda62016-08-12 00:43:162871 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522872 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582873 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162874
[email protected]49639fa2011-12-20 23:22:412875 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162876
bnc691fda62016-08-12 00:43:162877 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012878 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162879
2880 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012881 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162882
[email protected]58e32bb2013-01-21 18:23:252883 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162884 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252885 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2886 // The load timing after restart should have a new socket ID, and times after
2887 // those of the first load timing.
2888 EXPECT_LE(load_timing_info1.receive_headers_end,
2889 load_timing_info2.connect_timing.connect_start);
2890 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2891
Ryan Sleevib8d7ea02018-05-07 20:01:012892 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162893 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012894 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162895 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192896
bnc691fda62016-08-12 00:43:162897 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522898 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582899 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162900 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162901}
2902
ttuttled9dbc652015-09-29 20:00:592903// Test the request-challenge-retry sequence for basic auth.
2904// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012905TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592906 HttpRequestInfo request;
2907 request.method = "GET";
2908 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102909 request.traffic_annotation =
2910 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592911
Matt Muellerd9342e3a2019-11-26 01:41:142912 RecordingTestNetLog log;
ttuttled9dbc652015-09-29 20:00:592913 MockHostResolver* resolver = new MockHostResolver();
2914 session_deps_.net_log = &log;
2915 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092916 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162917 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592918
2919 resolver->rules()->ClearRules();
2920 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2921
2922 MockWrite data_writes1[] = {
2923 MockWrite("GET / HTTP/1.1\r\n"
2924 "Host: www.example.org\r\n"
2925 "Connection: keep-alive\r\n\r\n"),
2926 };
2927
2928 MockRead data_reads1[] = {
2929 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2930 // Give a couple authenticate options (only the middle one is actually
2931 // supported).
2932 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2933 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2934 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2935 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2936 // Large content-length -- won't matter, as connection will be reset.
2937 MockRead("Content-Length: 10000\r\n\r\n"),
2938 MockRead(SYNCHRONOUS, ERR_FAILED),
2939 };
2940
2941 // After calling trans->RestartWithAuth(), this is the request we should
2942 // be issuing -- the final header line contains the credentials.
2943 MockWrite data_writes2[] = {
2944 MockWrite("GET / HTTP/1.1\r\n"
2945 "Host: www.example.org\r\n"
2946 "Connection: keep-alive\r\n"
2947 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2948 };
2949
2950 // Lastly, the server responds with the actual content.
2951 MockRead data_reads2[] = {
2952 MockRead("HTTP/1.0 200 OK\r\n"),
2953 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2954 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2955 };
2956
Ryan Sleevib8d7ea02018-05-07 20:01:012957 StaticSocketDataProvider data1(data_reads1, data_writes1);
2958 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592959 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2960 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2961
2962 TestCompletionCallback callback1;
2963
bnc691fda62016-08-12 00:43:162964 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202965 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592966
2967 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162968 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592969 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2970
Ryan Sleevib8d7ea02018-05-07 20:01:012971 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162972 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012973 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162974 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592975
bnc691fda62016-08-12 00:43:162976 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592977 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582978 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592979
2980 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162981 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592982 ASSERT_FALSE(endpoint.address().empty());
2983 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2984
2985 resolver->rules()->ClearRules();
2986 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2987
2988 TestCompletionCallback callback2;
2989
bnc691fda62016-08-12 00:43:162990 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592991 AuthCredentials(kFoo, kBar), callback2.callback())));
2992
2993 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162994 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592995 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2996 // The load timing after restart should have a new socket ID, and times after
2997 // those of the first load timing.
2998 EXPECT_LE(load_timing_info1.receive_headers_end,
2999 load_timing_info2.connect_timing.connect_start);
3000 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3001
Ryan Sleevib8d7ea02018-05-07 20:01:013002 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:163003 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013004 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:163005 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:593006
bnc691fda62016-08-12 00:43:163007 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:593008 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583009 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:593010 EXPECT_EQ(100, response->headers->GetContentLength());
3011
bnc691fda62016-08-12 00:43:163012 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:593013 ASSERT_FALSE(endpoint.address().empty());
3014 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
3015}
3016
David Benjamin83ddfb32018-03-30 01:07:523017// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
3018// will eventually give up.
3019TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
3020 HttpRequestInfo request;
3021 request.method = "GET";
3022 request.url = GURL("http://www.example.org/");
3023 request.traffic_annotation =
3024 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3025
Matt Muellerd9342e3a2019-11-26 01:41:143026 RecordingTestNetLog log;
David Benjamin83ddfb32018-03-30 01:07:523027 session_deps_.net_log = &log;
3028 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3029 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3030
3031 MockWrite data_writes[] = {
3032 MockWrite("GET / HTTP/1.1\r\n"
3033 "Host: www.example.org\r\n"
3034 "Connection: keep-alive\r\n\r\n"),
3035 };
3036
3037 MockRead data_reads[] = {
3038 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3039 // Give a couple authenticate options (only the middle one is actually
3040 // supported).
3041 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
3042 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3043 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3044 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3045 // Large content-length -- won't matter, as connection will be reset.
3046 MockRead("Content-Length: 10000\r\n\r\n"),
3047 MockRead(SYNCHRONOUS, ERR_FAILED),
3048 };
3049
3050 // After calling trans->RestartWithAuth(), this is the request we should
3051 // be issuing -- the final header line contains the credentials.
3052 MockWrite data_writes_restart[] = {
3053 MockWrite("GET / HTTP/1.1\r\n"
3054 "Host: www.example.org\r\n"
3055 "Connection: keep-alive\r\n"
3056 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3057 };
3058
Ryan Sleevib8d7ea02018-05-07 20:01:013059 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:523060 session_deps_.socket_factory->AddSocketDataProvider(&data);
3061
3062 TestCompletionCallback callback;
3063 int rv = callback.GetResult(
3064 trans.Start(&request, callback.callback(), NetLogWithSource()));
3065
3066 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
3067 for (int i = 0; i < 32; i++) {
3068 // Check the previous response was a 401.
3069 EXPECT_THAT(rv, IsOk());
3070 const HttpResponseInfo* response = trans.GetResponseInfo();
3071 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583072 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:523073
3074 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:013075 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:523076 session_deps_.socket_factory->AddSocketDataProvider(
3077 data_restarts.back().get());
3078 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3079 callback.callback()));
3080 }
3081
3082 // After too many tries, the transaction should have given up.
3083 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
3084}
3085
bncd16676a2016-07-20 16:23:013086TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:463087 HttpRequestInfo request;
3088 request.method = "GET";
bncce36dca22015-04-21 22:11:233089 request.url = GURL("http://www.example.org/");
Matt Menke25eaa432020-08-25 00:10:003090 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:103091 request.traffic_annotation =
3092 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:463093
danakj1fd259a02016-04-16 03:17:093094 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:163095 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:273096
[email protected]861fcd52009-08-26 02:33:463097 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:233098 MockWrite(
3099 "GET / HTTP/1.1\r\n"
3100 "Host: www.example.org\r\n"
3101 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:463102 };
3103
3104 MockRead data_reads[] = {
3105 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3106 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3107 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3108 // Large content-length -- won't matter, as connection will be reset.
3109 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063110 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:463111 };
3112
Ryan Sleevib8d7ea02018-05-07 20:01:013113 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073114 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:413115 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:463116
tfarina42834112016-09-22 13:38:203117 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:463119
3120 rv = callback.WaitForResult();
3121 EXPECT_EQ(0, rv);
3122
Ryan Sleevib8d7ea02018-05-07 20:01:013123 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163124 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013125 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163126 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:193127
bnc691fda62016-08-12 00:43:163128 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523129 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583130 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:463131}
3132
[email protected]2d2697f92009-02-18 21:00:323133// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3134// connection.
bncd16676a2016-07-20 16:23:013135TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:183136 // On the second pass, the body read of the auth challenge is synchronous, so
3137 // IsConnectedAndIdle returns false. The socket should still be drained and
3138 // reused. See http://crbug.com/544255.
3139 for (int i = 0; i < 2; ++i) {
3140 HttpRequestInfo request;
3141 request.method = "GET";
3142 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103143 request.traffic_annotation =
3144 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323145
Matt Muellerd9342e3a2019-11-26 01:41:143146 RecordingTestNetLog log;
mmenkecc2298e2015-12-07 18:20:183147 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:093148 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273149
mmenkecc2298e2015-12-07 18:20:183150 MockWrite data_writes[] = {
3151 MockWrite(ASYNC, 0,
3152 "GET / HTTP/1.1\r\n"
3153 "Host: www.example.org\r\n"
3154 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323155
bnc691fda62016-08-12 00:43:163156 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:183157 // be issuing -- the final header line contains the credentials.
3158 MockWrite(ASYNC, 6,
3159 "GET / HTTP/1.1\r\n"
3160 "Host: www.example.org\r\n"
3161 "Connection: keep-alive\r\n"
3162 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3163 };
[email protected]2d2697f92009-02-18 21:00:323164
mmenkecc2298e2015-12-07 18:20:183165 MockRead data_reads[] = {
3166 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
3167 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3168 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
3169 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
3170 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:323171
mmenkecc2298e2015-12-07 18:20:183172 // Lastly, the server responds with the actual content.
3173 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
3174 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
3175 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
3176 MockRead(ASYNC, 10, "Hello"),
3177 };
[email protected]2d2697f92009-02-18 21:00:323178
Ryan Sleevib8d7ea02018-05-07 20:01:013179 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:183180 data.set_busy_before_sync_reads(true);
3181 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:463182
mmenkecc2298e2015-12-07 18:20:183183 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323184
bnc691fda62016-08-12 00:43:163185 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203186 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013187 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323188
mmenkecc2298e2015-12-07 18:20:183189 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:163190 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:183191 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:323192
bnc691fda62016-08-12 00:43:163193 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183194 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583195 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323196
mmenkecc2298e2015-12-07 18:20:183197 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:253198
bnc691fda62016-08-12 00:43:163199 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3200 callback2.callback());
robpercival214763f2016-07-01 23:27:013201 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323202
mmenkecc2298e2015-12-07 18:20:183203 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:163204 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:183205 TestLoadTimingReused(load_timing_info2);
3206 // The load timing after restart should have the same socket ID, and times
3207 // those of the first load timing.
3208 EXPECT_LE(load_timing_info1.receive_headers_end,
3209 load_timing_info2.send_start);
3210 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:323211
bnc691fda62016-08-12 00:43:163212 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183213 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583214 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:183215 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323216
mmenkecc2298e2015-12-07 18:20:183217 std::string response_data;
bnc691fda62016-08-12 00:43:163218 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:323219
Ryan Sleevib8d7ea02018-05-07 20:01:013220 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163221 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013222 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163223 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:183224 }
[email protected]2d2697f92009-02-18 21:00:323225}
3226
3227// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3228// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:013229TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:423230 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323231 request.method = "GET";
bncce36dca22015-04-21 22:11:233232 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103233 request.traffic_annotation =
3234 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323235
danakj1fd259a02016-04-16 03:17:093236 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273237
[email protected]2d2697f92009-02-18 21:00:323238 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163239 MockWrite("GET / HTTP/1.1\r\n"
3240 "Host: www.example.org\r\n"
3241 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323242
bnc691fda62016-08-12 00:43:163243 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233244 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163245 MockWrite("GET / HTTP/1.1\r\n"
3246 "Host: www.example.org\r\n"
3247 "Connection: keep-alive\r\n"
3248 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323249 };
3250
[email protected]2d2697f92009-02-18 21:00:323251 MockRead data_reads1[] = {
3252 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3253 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313254 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323255
3256 // Lastly, the server responds with the actual content.
3257 MockRead("HTTP/1.1 200 OK\r\n"),
3258 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503259 MockRead("Content-Length: 5\r\n\r\n"),
3260 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323261 };
3262
[email protected]2d0a4f92011-05-05 16:38:463263 // An incorrect reconnect would cause this to be read.
3264 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063265 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463266 };
3267
Ryan Sleevib8d7ea02018-05-07 20:01:013268 StaticSocketDataProvider data1(data_reads1, data_writes1);
3269 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073270 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3271 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323272
[email protected]49639fa2011-12-20 23:22:413273 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323274
bnc691fda62016-08-12 00:43:163275 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203276 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013277 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323278
3279 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013280 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323281
bnc691fda62016-08-12 00:43:163282 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523283 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583284 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323285
[email protected]49639fa2011-12-20 23:22:413286 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323287
bnc691fda62016-08-12 00:43:163288 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013289 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323290
3291 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013292 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323293
bnc691fda62016-08-12 00:43:163294 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523295 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583296 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503297 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323298}
3299
3300// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3301// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013302TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423303 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323304 request.method = "GET";
bncce36dca22015-04-21 22:11:233305 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103306 request.traffic_annotation =
3307 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323308
danakj1fd259a02016-04-16 03:17:093309 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273310
[email protected]2d2697f92009-02-18 21:00:323311 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163312 MockWrite("GET / HTTP/1.1\r\n"
3313 "Host: www.example.org\r\n"
3314 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323315
bnc691fda62016-08-12 00:43:163316 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233317 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163318 MockWrite("GET / HTTP/1.1\r\n"
3319 "Host: www.example.org\r\n"
3320 "Connection: keep-alive\r\n"
3321 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323322 };
3323
3324 // Respond with 5 kb of response body.
3325 std::string large_body_string("Unauthorized");
3326 large_body_string.append(5 * 1024, ' ');
3327 large_body_string.append("\r\n");
3328
3329 MockRead data_reads1[] = {
3330 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3331 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3332 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3333 // 5134 = 12 + 5 * 1024 + 2
3334 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063335 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323336
3337 // Lastly, the server responds with the actual content.
3338 MockRead("HTTP/1.1 200 OK\r\n"),
3339 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503340 MockRead("Content-Length: 5\r\n\r\n"),
3341 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323342 };
3343
[email protected]2d0a4f92011-05-05 16:38:463344 // An incorrect reconnect would cause this to be read.
3345 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063346 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463347 };
3348
Ryan Sleevib8d7ea02018-05-07 20:01:013349 StaticSocketDataProvider data1(data_reads1, data_writes1);
3350 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073351 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3352 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323353
[email protected]49639fa2011-12-20 23:22:413354 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323355
bnc691fda62016-08-12 00:43:163356 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203357 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323359
3360 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013361 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323362
bnc691fda62016-08-12 00:43:163363 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523364 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583365 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323366
[email protected]49639fa2011-12-20 23:22:413367 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323368
bnc691fda62016-08-12 00:43:163369 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323371
3372 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013373 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323374
bnc691fda62016-08-12 00:43:163375 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523376 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583377 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503378 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323379}
3380
3381// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313382// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013383TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313384 HttpRequestInfo request;
3385 request.method = "GET";
bncce36dca22015-04-21 22:11:233386 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103387 request.traffic_annotation =
3388 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313389
danakj1fd259a02016-04-16 03:17:093390 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273391
[email protected]11203f012009-11-12 23:02:313392 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233393 MockWrite(
3394 "GET / HTTP/1.1\r\n"
3395 "Host: www.example.org\r\n"
3396 "Connection: keep-alive\r\n\r\n"),
3397 // This simulates the seemingly successful write to a closed connection
3398 // if the bug is not fixed.
3399 MockWrite(
3400 "GET / HTTP/1.1\r\n"
3401 "Host: www.example.org\r\n"
3402 "Connection: keep-alive\r\n"
3403 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313404 };
3405
3406 MockRead data_reads1[] = {
3407 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3408 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3409 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3410 MockRead("Content-Length: 14\r\n\r\n"),
3411 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063412 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313413 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063414 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313415 };
3416
bnc691fda62016-08-12 00:43:163417 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313418 // be issuing -- the final header line contains the credentials.
3419 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233420 MockWrite(
3421 "GET / HTTP/1.1\r\n"
3422 "Host: www.example.org\r\n"
3423 "Connection: keep-alive\r\n"
3424 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313425 };
3426
3427 // Lastly, the server responds with the actual content.
3428 MockRead data_reads2[] = {
3429 MockRead("HTTP/1.1 200 OK\r\n"),
3430 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503431 MockRead("Content-Length: 5\r\n\r\n"),
3432 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313433 };
3434
Ryan Sleevib8d7ea02018-05-07 20:01:013435 StaticSocketDataProvider data1(data_reads1, data_writes1);
3436 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073437 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3438 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313439
[email protected]49639fa2011-12-20 23:22:413440 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313441
bnc691fda62016-08-12 00:43:163442 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203443 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013444 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313445
3446 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013447 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313448
bnc691fda62016-08-12 00:43:163449 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523450 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583451 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313452
[email protected]49639fa2011-12-20 23:22:413453 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313454
bnc691fda62016-08-12 00:43:163455 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013456 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313457
3458 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013459 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313460
bnc691fda62016-08-12 00:43:163461 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523462 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583463 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503464 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313465}
3466
[email protected]394816e92010-08-03 07:38:593467// Test the request-challenge-retry sequence for basic auth, over a connection
3468// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013469TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013470 HttpRequestInfo request;
3471 request.method = "GET";
bncce36dca22015-04-21 22:11:233472 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013473 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003474 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:103475 request.traffic_annotation =
3476 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013477
3478 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593479 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563480 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493481 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143482 RecordingBoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013483 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093484 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013485
3486 // Since we have proxy, should try to establish tunnel.
3487 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543488 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173489 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543490 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013491 };
3492
mmenkee71e15332015-10-07 16:39:543493 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013494 // connection.
3495 MockRead data_reads1[] = {
3496 // No credentials.
3497 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3498 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543499 };
ttuttle34f63b52015-03-05 04:33:013500
mmenkee71e15332015-10-07 16:39:543501 // Since the first connection couldn't be reused, need to establish another
3502 // once given credentials.
3503 MockWrite data_writes2[] = {
3504 // After calling trans->RestartWithAuth(), this is the request we should
3505 // be issuing -- the final header line contains the credentials.
3506 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173507 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543508 "Proxy-Connection: keep-alive\r\n"
3509 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3510
3511 MockWrite("GET / HTTP/1.1\r\n"
3512 "Host: www.example.org\r\n"
3513 "Connection: keep-alive\r\n\r\n"),
3514 };
3515
3516 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013517 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3518
3519 MockRead("HTTP/1.1 200 OK\r\n"),
3520 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3521 MockRead("Content-Length: 5\r\n\r\n"),
3522 MockRead(SYNCHRONOUS, "hello"),
3523 };
3524
Ryan Sleevib8d7ea02018-05-07 20:01:013525 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013526 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013527 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543528 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013529 SSLSocketDataProvider ssl(ASYNC, OK);
3530 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3531
3532 TestCompletionCallback callback1;
Titouan Rigoudyba507a882020-07-31 12:15:153533 ConnectedHandler connected_handler;
ttuttle34f63b52015-03-05 04:33:013534
bnc87dcefc2017-05-25 12:47:583535 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193536 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013537
Titouan Rigoudyba507a882020-07-31 12:15:153538 trans->SetConnectedCallback(connected_handler.Callback());
3539
ttuttle34f63b52015-03-05 04:33:013540 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013541 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013542
3543 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013544 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543545 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013546 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003547 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3548 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013549 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003550 entries, pos,
3551 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3552 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013553
Titouan Rigoudyba507a882020-07-31 12:15:153554 // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy
3555 // authentication is required. We should notify the callback that a connection
3556 // was established, even though the stream might not be ready for us to send
3557 // data through it.
3558 EXPECT_THAT(connected_handler.transports(), IsEmpty());
3559
ttuttle34f63b52015-03-05 04:33:013560 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523561 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013562 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523563 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013564 EXPECT_EQ(407, response->headers->response_code());
3565 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583566 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013567
3568 LoadTimingInfo load_timing_info;
3569 // CONNECT requests and responses are handled at the connect job level, so
3570 // the transaction does not yet have a connection.
3571 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3572
3573 TestCompletionCallback callback2;
3574
3575 rv =
3576 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013577 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013578
3579 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013580 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013581
3582 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523583 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013584
3585 EXPECT_TRUE(response->headers->IsKeepAlive());
3586 EXPECT_EQ(200, response->headers->response_code());
3587 EXPECT_EQ(5, response->headers->GetContentLength());
3588 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3589
Titouan Rigoudyba507a882020-07-31 12:15:153590 TransportInfo expected_transport;
3591 expected_transport.type = TransportType::kProxied;
3592 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
3593 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
3594
Matt Menke96092e62019-10-18 04:09:333595 // Check that credentials were successfully cached, with the right target.
3596 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
3597 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:263598 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:333599 ASSERT_TRUE(entry);
3600 ASSERT_EQ(kFoo, entry->credentials().username());
3601 ASSERT_EQ(kBar, entry->credentials().password());
3602
ttuttle34f63b52015-03-05 04:33:013603 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583604 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013605
3606 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3607 TestLoadTimingNotReusedWithPac(load_timing_info,
3608 CONNECT_TIMING_HAS_SSL_TIMES);
3609
3610 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113611 session->CloseAllConnections(ERR_FAILED, "Very good reason");
ttuttle34f63b52015-03-05 04:33:013612}
3613
3614// Test the request-challenge-retry sequence for basic auth, over a connection
3615// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013616TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593617 HttpRequestInfo request;
3618 request.method = "GET";
bncce36dca22015-04-21 22:11:233619 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593620 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003621 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:103622 request.traffic_annotation =
3623 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593624
[email protected]cb9bf6ca2011-01-28 13:15:273625 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593626 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563627 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493628 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143629 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073630 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093631 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273632
[email protected]394816e92010-08-03 07:38:593633 // Since we have proxy, should try to establish tunnel.
3634 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543635 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173636 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543637 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113638 };
3639
mmenkee71e15332015-10-07 16:39:543640 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083641 // connection.
3642 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543643 // No credentials.
3644 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3645 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3646 MockRead("Proxy-Connection: close\r\n\r\n"),
3647 };
mmenkee0b5c882015-08-26 20:29:113648
mmenkee71e15332015-10-07 16:39:543649 MockWrite data_writes2[] = {
3650 // After calling trans->RestartWithAuth(), this is the request we should
3651 // be issuing -- the final header line contains the credentials.
3652 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173653 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543654 "Proxy-Connection: keep-alive\r\n"
3655 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083656
mmenkee71e15332015-10-07 16:39:543657 MockWrite("GET / HTTP/1.1\r\n"
3658 "Host: www.example.org\r\n"
3659 "Connection: keep-alive\r\n\r\n"),
3660 };
3661
3662 MockRead data_reads2[] = {
3663 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3664
3665 MockRead("HTTP/1.1 200 OK\r\n"),
3666 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3667 MockRead("Content-Length: 5\r\n\r\n"),
3668 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593669 };
3670
Ryan Sleevib8d7ea02018-05-07 20:01:013671 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073672 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013673 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543674 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063675 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073676 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593677
Titouan Rigoudyba507a882020-07-31 12:15:153678 ConnectedHandler connected_handler;
[email protected]49639fa2011-12-20 23:22:413679 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593680
bnc87dcefc2017-05-25 12:47:583681 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193682 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503683
Titouan Rigoudyba507a882020-07-31 12:15:153684 trans->SetConnectedCallback(connected_handler.Callback());
3685
[email protected]49639fa2011-12-20 23:22:413686 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013687 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593688
3689 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013690 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543691 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593692 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003693 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3694 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593695 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403696 entries, pos,
mikecirone8b85c432016-09-08 19:11:003697 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3698 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593699
3700 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523701 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013702 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523703 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593704 EXPECT_EQ(407, response->headers->response_code());
3705 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583706 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593707
Titouan Rigoudyba507a882020-07-31 12:15:153708 // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy
3709 // authentication is required. We should notify the callback that a connection
3710 // was established, even though the stream might not be ready for us to send
3711 // data through it.
3712 EXPECT_THAT(connected_handler.transports(), IsEmpty());
3713
[email protected]029c83b62013-01-24 05:28:203714 LoadTimingInfo load_timing_info;
3715 // CONNECT requests and responses are handled at the connect job level, so
3716 // the transaction does not yet have a connection.
3717 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3718
[email protected]49639fa2011-12-20 23:22:413719 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593720
[email protected]49639fa2011-12-20 23:22:413721 rv = trans->RestartWithAuth(
3722 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013723 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593724
3725 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013726 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593727
3728 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523729 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593730
3731 EXPECT_TRUE(response->headers->IsKeepAlive());
3732 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503733 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593734 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3735
Titouan Rigoudyba507a882020-07-31 12:15:153736 TransportInfo expected_transport;
3737 expected_transport.type = TransportType::kProxied;
3738 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
3739 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
3740
[email protected]394816e92010-08-03 07:38:593741 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583742 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503743
[email protected]029c83b62013-01-24 05:28:203744 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3745 TestLoadTimingNotReusedWithPac(load_timing_info,
3746 CONNECT_TIMING_HAS_SSL_TIMES);
3747
[email protected]0b0bf032010-09-21 18:08:503748 trans.reset();
Matt Menke433de6d2020-03-04 00:24:113749 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]394816e92010-08-03 07:38:593750}
3751
[email protected]11203f012009-11-12 23:02:313752// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013753// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013754TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233755 // On the second pass, the body read of the auth challenge is synchronous, so
3756 // IsConnectedAndIdle returns false. The socket should still be drained and
3757 // reused. See http://crbug.com/544255.
3758 for (int i = 0; i < 2; ++i) {
3759 HttpRequestInfo request;
3760 request.method = "GET";
3761 request.url = GURL("https://www.example.org/");
3762 // Ensure that proxy authentication is attempted even
3763 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003764 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:103765 request.traffic_annotation =
3766 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013767
mmenked39192ee2015-12-09 00:57:233768 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593769 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563770 ConfiguredProxyResolutionService::CreateFixed(
3771 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143772 RecordingBoundTestNetLog log;
mmenked39192ee2015-12-09 00:57:233773 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093774 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013775
bnc691fda62016-08-12 00:43:163776 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013777
mmenked39192ee2015-12-09 00:57:233778 // Since we have proxy, should try to establish tunnel.
3779 MockWrite data_writes1[] = {
3780 MockWrite(ASYNC, 0,
3781 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3782 "Host: www.example.org:443\r\n"
3783 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013784
bnc691fda62016-08-12 00:43:163785 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233786 // be issuing -- the final header line contains the credentials.
3787 MockWrite(ASYNC, 3,
3788 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3789 "Host: www.example.org:443\r\n"
3790 "Proxy-Connection: keep-alive\r\n"
3791 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3792 };
ttuttle34f63b52015-03-05 04:33:013793
mmenked39192ee2015-12-09 00:57:233794 // The proxy responds to the connect with a 407, using a persistent
3795 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3796 MockRead data_reads1[] = {
3797 // No credentials.
3798 MockRead(ASYNC, 1,
3799 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3800 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3801 "Proxy-Connection: keep-alive\r\n"
3802 "Content-Length: 10\r\n\r\n"),
3803 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013804
mmenked39192ee2015-12-09 00:57:233805 // Wrong credentials (wrong password).
3806 MockRead(ASYNC, 4,
3807 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3808 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3809 "Proxy-Connection: keep-alive\r\n"
3810 "Content-Length: 10\r\n\r\n"),
3811 // No response body because the test stops reading here.
3812 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3813 };
ttuttle34f63b52015-03-05 04:33:013814
Ryan Sleevib8d7ea02018-05-07 20:01:013815 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233816 data1.set_busy_before_sync_reads(true);
3817 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013818
mmenked39192ee2015-12-09 00:57:233819 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013820
bnc691fda62016-08-12 00:43:163821 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013822 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013823
Eric Roman79cc7552019-07-19 02:17:543824 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233825 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003826 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3827 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233828 ExpectLogContainsSomewhere(
3829 entries, pos,
mikecirone8b85c432016-09-08 19:11:003830 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3831 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013832
bnc691fda62016-08-12 00:43:163833 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233834 ASSERT_TRUE(response);
3835 ASSERT_TRUE(response->headers);
3836 EXPECT_TRUE(response->headers->IsKeepAlive());
3837 EXPECT_EQ(407, response->headers->response_code());
3838 EXPECT_EQ(10, response->headers->GetContentLength());
3839 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583840 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013841
mmenked39192ee2015-12-09 00:57:233842 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013843
mmenked39192ee2015-12-09 00:57:233844 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163845 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3846 callback2.callback());
robpercival214763f2016-07-01 23:27:013847 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013848
bnc691fda62016-08-12 00:43:163849 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233850 ASSERT_TRUE(response);
3851 ASSERT_TRUE(response->headers);
3852 EXPECT_TRUE(response->headers->IsKeepAlive());
3853 EXPECT_EQ(407, response->headers->response_code());
3854 EXPECT_EQ(10, response->headers->GetContentLength());
3855 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583856 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013857
mmenked39192ee2015-12-09 00:57:233858 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3859 // out of scope.
Matt Menke433de6d2020-03-04 00:24:113860 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenked39192ee2015-12-09 00:57:233861 }
ttuttle34f63b52015-03-05 04:33:013862}
3863
3864// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3865// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013866TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233867 // On the second pass, the body read of the auth challenge is synchronous, so
3868 // IsConnectedAndIdle returns false. The socket should still be drained and
3869 // reused. See http://crbug.com/544255.
3870 for (int i = 0; i < 2; ++i) {
3871 HttpRequestInfo request;
3872 request.method = "GET";
3873 request.url = GURL("https://www.example.org/");
3874 // Ensure that proxy authentication is attempted even
3875 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003876 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:103877 request.traffic_annotation =
3878 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233879
3880 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593881 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563882 ConfiguredProxyResolutionService::CreateFixed(
3883 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143884 RecordingBoundTestNetLog log;
mmenked39192ee2015-12-09 00:57:233885 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093886 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233887
bnc691fda62016-08-12 00:43:163888 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233889
3890 // Since we have proxy, should try to establish tunnel.
3891 MockWrite data_writes1[] = {
3892 MockWrite(ASYNC, 0,
3893 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3894 "Host: www.example.org:443\r\n"
3895 "Proxy-Connection: keep-alive\r\n\r\n"),
3896
bnc691fda62016-08-12 00:43:163897 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233898 // be issuing -- the final header line contains the credentials.
3899 MockWrite(ASYNC, 3,
3900 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3901 "Host: www.example.org:443\r\n"
3902 "Proxy-Connection: keep-alive\r\n"
3903 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3904 };
3905
3906 // The proxy responds to the connect with a 407, using a persistent
3907 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3908 MockRead data_reads1[] = {
3909 // No credentials.
3910 MockRead(ASYNC, 1,
3911 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3912 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3913 "Content-Length: 10\r\n\r\n"),
3914 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3915
3916 // Wrong credentials (wrong password).
3917 MockRead(ASYNC, 4,
3918 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3919 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3920 "Content-Length: 10\r\n\r\n"),
3921 // No response body because the test stops reading here.
3922 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3923 };
3924
Ryan Sleevib8d7ea02018-05-07 20:01:013925 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233926 data1.set_busy_before_sync_reads(true);
3927 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3928
3929 TestCompletionCallback callback1;
3930
bnc691fda62016-08-12 00:43:163931 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013932 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233933
Eric Roman79cc7552019-07-19 02:17:543934 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233935 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003936 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3937 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233938 ExpectLogContainsSomewhere(
3939 entries, pos,
mikecirone8b85c432016-09-08 19:11:003940 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3941 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233942
bnc691fda62016-08-12 00:43:163943 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233944 ASSERT_TRUE(response);
3945 ASSERT_TRUE(response->headers);
3946 EXPECT_TRUE(response->headers->IsKeepAlive());
3947 EXPECT_EQ(407, response->headers->response_code());
3948 EXPECT_EQ(10, response->headers->GetContentLength());
3949 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583950 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503951 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233952
3953 TestCompletionCallback callback2;
3954
3955 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163956 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3957 callback2.callback());
robpercival214763f2016-07-01 23:27:013958 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233959
bnc691fda62016-08-12 00:43:163960 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233961 ASSERT_TRUE(response);
3962 ASSERT_TRUE(response->headers);
3963 EXPECT_TRUE(response->headers->IsKeepAlive());
3964 EXPECT_EQ(407, response->headers->response_code());
3965 EXPECT_EQ(10, response->headers->GetContentLength());
3966 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583967 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503968 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233969
3970 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3971 // out of scope.
Matt Menke433de6d2020-03-04 00:24:113972 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenked39192ee2015-12-09 00:57:233973 }
3974}
3975
3976// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3977// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3978// the case the server sends extra data on the original socket, so it can't be
3979// reused.
bncd16676a2016-07-20 16:23:013980TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273981 HttpRequestInfo request;
3982 request.method = "GET";
bncce36dca22015-04-21 22:11:233983 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273984 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:003985 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:103986 request.traffic_annotation =
3987 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273988
[email protected]2d2697f92009-02-18 21:00:323989 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593990 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:563991 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:493992 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:143993 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073994 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323996
[email protected]2d2697f92009-02-18 21:00:323997 // Since we have proxy, should try to establish tunnel.
3998 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233999 MockWrite(ASYNC, 0,
4000 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174001 "Host: www.example.org:443\r\n"
4002 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234003 };
[email protected]2d2697f92009-02-18 21:00:324004
mmenked39192ee2015-12-09 00:57:234005 // The proxy responds to the connect with a 407, using a persistent, but sends
4006 // extra data, so the socket cannot be reused.
4007 MockRead data_reads1[] = {
4008 // No credentials.
4009 MockRead(ASYNC, 1,
4010 "HTTP/1.1 407 Proxy Authentication Required\r\n"
4011 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4012 "Content-Length: 10\r\n\r\n"),
4013 MockRead(SYNCHRONOUS, 2, "0123456789"),
4014 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
4015 };
4016
4017 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:234018 // After calling trans->RestartWithAuth(), this is the request we should
4019 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:234020 MockWrite(ASYNC, 0,
4021 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174022 "Host: www.example.org:443\r\n"
4023 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:234024 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4025
4026 MockWrite(ASYNC, 2,
4027 "GET / HTTP/1.1\r\n"
4028 "Host: www.example.org\r\n"
4029 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:324030 };
4031
mmenked39192ee2015-12-09 00:57:234032 MockRead data_reads2[] = {
4033 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:324034
mmenked39192ee2015-12-09 00:57:234035 MockRead(ASYNC, 3,
4036 "HTTP/1.1 200 OK\r\n"
4037 "Content-Type: text/html; charset=iso-8859-1\r\n"
4038 "Content-Length: 5\r\n\r\n"),
4039 // No response body because the test stops reading here.
4040 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:324041 };
4042
Ryan Sleevib8d7ea02018-05-07 20:01:014043 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:234044 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:074045 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014046 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:234047 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4048 SSLSocketDataProvider ssl(ASYNC, OK);
4049 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:324050
[email protected]49639fa2011-12-20 23:22:414051 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:324052
bnc87dcefc2017-05-25 12:47:584053 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194054 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:324055
mmenked39192ee2015-12-09 00:57:234056 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014057 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:234058
Eric Roman79cc7552019-07-19 02:17:544059 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:394060 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004061 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4062 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:394063 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404064 entries, pos,
mikecirone8b85c432016-09-08 19:11:004065 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4066 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:324067
[email protected]1c773ea12009-04-28 19:58:424068 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244069 ASSERT_TRUE(response);
4070 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:324071 EXPECT_TRUE(response->headers->IsKeepAlive());
4072 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424073 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:584074 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:324075
mmenked39192ee2015-12-09 00:57:234076 LoadTimingInfo load_timing_info;
4077 // CONNECT requests and responses are handled at the connect job level, so
4078 // the transaction does not yet have a connection.
4079 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4080
[email protected]49639fa2011-12-20 23:22:414081 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:324082
mmenked39192ee2015-12-09 00:57:234083 rv =
4084 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:014085 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:324086
[email protected]2d2697f92009-02-18 21:00:324087 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:234088 EXPECT_EQ(200, response->headers->response_code());
4089 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:424090 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:134091
mmenked39192ee2015-12-09 00:57:234092 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584093 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:234094
4095 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4096 TestLoadTimingNotReusedWithPac(load_timing_info,
4097 CONNECT_TIMING_HAS_SSL_TIMES);
4098
4099 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114100 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]2d2697f92009-02-18 21:00:324101}
4102
mmenkee71e15332015-10-07 16:39:544103// Test the case a proxy closes a socket while the challenge body is being
4104// drained.
bncd16676a2016-07-20 16:23:014105TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:544106 HttpRequestInfo request;
4107 request.method = "GET";
4108 request.url = GURL("https://www.example.org/");
4109 // Ensure that proxy authentication is attempted even
4110 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:004111 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:104112 request.traffic_annotation =
4113 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:544114
4115 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:564116 session_deps_.proxy_resolution_service =
4117 ConfiguredProxyResolutionService::CreateFixed(
4118 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:094119 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:544120
bnc691fda62016-08-12 00:43:164121 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:544122
4123 // Since we have proxy, should try to establish tunnel.
4124 MockWrite data_writes1[] = {
4125 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174126 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:544127 "Proxy-Connection: keep-alive\r\n\r\n"),
4128 };
4129
4130 // The proxy responds to the connect with a 407, using a persistent
4131 // connection.
4132 MockRead data_reads1[] = {
4133 // No credentials.
4134 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4135 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4136 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
4137 // Server hands up in the middle of the body.
4138 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
4139 };
4140
4141 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:164142 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:544143 // be issuing -- the final header line contains the credentials.
4144 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174145 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:544146 "Proxy-Connection: keep-alive\r\n"
4147 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4148
4149 MockWrite("GET / HTTP/1.1\r\n"
4150 "Host: www.example.org\r\n"
4151 "Connection: keep-alive\r\n\r\n"),
4152 };
4153
4154 MockRead data_reads2[] = {
4155 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4156
4157 MockRead("HTTP/1.1 200 OK\r\n"),
4158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4159 MockRead("Content-Length: 5\r\n\r\n"),
4160 MockRead(SYNCHRONOUS, "hello"),
4161 };
4162
Ryan Sleevib8d7ea02018-05-07 20:01:014163 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:544164 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014165 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:544166 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4167 SSLSocketDataProvider ssl(ASYNC, OK);
4168 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4169
4170 TestCompletionCallback callback;
4171
tfarina42834112016-09-22 13:38:204172 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014173 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:544174
bnc691fda62016-08-12 00:43:164175 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:544176 ASSERT_TRUE(response);
4177 ASSERT_TRUE(response->headers);
4178 EXPECT_TRUE(response->headers->IsKeepAlive());
4179 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:584180 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:544181
bnc691fda62016-08-12 00:43:164182 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:014183 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:544184
bnc691fda62016-08-12 00:43:164185 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:544186 ASSERT_TRUE(response);
4187 ASSERT_TRUE(response->headers);
4188 EXPECT_TRUE(response->headers->IsKeepAlive());
4189 EXPECT_EQ(200, response->headers->response_code());
4190 std::string body;
bnc691fda62016-08-12 00:43:164191 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:544192 EXPECT_EQ("hello", body);
4193}
4194
[email protected]a8e9b162009-03-12 00:06:444195// Test that we don't read the response body when we fail to establish a tunnel,
4196// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:014197TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:274198 HttpRequestInfo request;
4199 request.method = "GET";
bncce36dca22015-04-21 22:11:234200 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104201 request.traffic_annotation =
4202 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274203
[email protected]a8e9b162009-03-12 00:06:444204 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:564205 session_deps_.proxy_resolution_service =
4206 ConfiguredProxyResolutionService::CreateFixed(
4207 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:444208
danakj1fd259a02016-04-16 03:17:094209 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:444210
bnc691fda62016-08-12 00:43:164211 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:444212
[email protected]a8e9b162009-03-12 00:06:444213 // Since we have proxy, should try to establish tunnel.
4214 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174215 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4216 "Host: www.example.org:443\r\n"
4217 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:444218 };
4219
4220 // The proxy responds to the connect with a 407.
4221 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:244222 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4223 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4224 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234225 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:244226 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:444227 };
4228
Ryan Sleevib8d7ea02018-05-07 20:01:014229 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:074230 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:444231
[email protected]49639fa2011-12-20 23:22:414232 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:444233
tfarina42834112016-09-22 13:38:204234 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014235 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:444236
4237 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014238 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:444239
bnc691fda62016-08-12 00:43:164240 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244241 ASSERT_TRUE(response);
4242 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:444243 EXPECT_TRUE(response->headers->IsKeepAlive());
4244 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424245 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:444246
4247 std::string response_data;
bnc691fda62016-08-12 00:43:164248 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014249 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:184250
4251 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
Matt Menke433de6d2020-03-04 00:24:114252 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]a8e9b162009-03-12 00:06:444253}
4254
Matt Menke96092e62019-10-18 04:09:334255// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4256// are the same, but the user/passwords are different. Serves to verify
4257// credentials are correctly separated based on HttpAuth::Target.
4258TEST_F(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
4259 HttpRequestInfo request;
4260 request.method = "GET";
4261 request.url = GURL("http://myproxy:70/");
4262 request.traffic_annotation =
4263 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4264
4265 // Proxy matches request URL.
4266 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564267 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke96092e62019-10-18 04:09:334268 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144269 RecordingBoundTestNetLog log;
Matt Menke96092e62019-10-18 04:09:334270 session_deps_.net_log = log.bound().net_log();
4271 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4272
4273 MockWrite data_writes[] = {
4274 // Initial request gets a proxy auth challenge.
4275 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4276 "Host: myproxy:70\r\n"
4277 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264278 // Retry with proxy auth credentials, which will result in a server auth
Matt Menke96092e62019-10-18 04:09:334279 // challenge.
4280 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4281 "Host: myproxy:70\r\n"
4282 "Proxy-Connection: keep-alive\r\n"
4283 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Matt Menkebe090422019-10-18 20:25:264284 // Retry with proxy and server auth credentials, which gets a response.
Matt Menke96092e62019-10-18 04:09:334285 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4286 "Host: myproxy:70\r\n"
4287 "Proxy-Connection: keep-alive\r\n"
4288 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4289 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4290 // A second request should preemptively send the correct proxy and server
4291 // auth headers.
4292 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4293 "Host: myproxy:70\r\n"
4294 "Proxy-Connection: keep-alive\r\n"
4295 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4296 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4297 };
4298
4299 MockRead data_reads[] = {
4300 // Proxy auth challenge.
4301 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4302 "Proxy-Connection: keep-alive\r\n"
4303 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4304 "Content-Length: 0\r\n\r\n"),
4305 // Server auth challenge.
4306 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4307 "Proxy-Connection: keep-alive\r\n"
4308 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4309 "Content-Length: 0\r\n\r\n"),
4310 // Response.
4311 MockRead("HTTP/1.1 200 OK\r\n"
4312 "Proxy-Connection: keep-alive\r\n"
4313 "Content-Length: 5\r\n\r\n"
4314 "hello"),
4315 // Response to second request.
4316 MockRead("HTTP/1.1 200 OK\r\n"
4317 "Proxy-Connection: keep-alive\r\n"
4318 "Content-Length: 2\r\n\r\n"
4319 "hi"),
4320 };
4321
4322 StaticSocketDataProvider data(data_reads, data_writes);
4323 session_deps_.socket_factory->AddSocketDataProvider(&data);
4324
4325 TestCompletionCallback callback;
4326
4327 auto trans =
4328 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4329 int rv = trans->Start(&request, callback.callback(), log.bound());
4330 EXPECT_THAT(callback.GetResult(rv), IsOk());
4331 const HttpResponseInfo* response = trans->GetResponseInfo();
4332 ASSERT_TRUE(response);
4333 ASSERT_TRUE(response->headers);
4334 EXPECT_EQ(407, response->headers->response_code());
4335 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4336
4337 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4338 EXPECT_THAT(callback.GetResult(rv), IsOk());
4339 response = trans->GetResponseInfo();
4340 ASSERT_TRUE(response);
4341 EXPECT_EQ(401, response->headers->response_code());
4342 EXPECT_FALSE(response->auth_challenge->is_proxy);
4343 EXPECT_EQ("http://myproxy:70",
4344 response->auth_challenge->challenger.Serialize());
4345 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4346 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4347
4348 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4349 callback.callback());
4350 EXPECT_THAT(callback.GetResult(rv), IsOk());
4351 response = trans->GetResponseInfo();
4352 ASSERT_TRUE(response);
4353 EXPECT_EQ(200, response->headers->response_code());
4354 // The password prompt info should not be set.
4355 EXPECT_FALSE(response->auth_challenge.has_value());
4356
4357 std::string response_data;
4358 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4359 EXPECT_EQ("hello", response_data);
4360
4361 // Check that the credentials were cached correctly.
4362 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4363 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:264364 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334365 ASSERT_TRUE(entry);
4366 ASSERT_EQ(kFoo, entry->credentials().username());
4367 ASSERT_EQ(kBar, entry->credentials().password());
Matt Menkebe090422019-10-18 20:25:264368 entry = session->http_auth_cache()->Lookup(
4369 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4370 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey());
Matt Menke96092e62019-10-18 04:09:334371 ASSERT_TRUE(entry);
4372 ASSERT_EQ(kFoo2, entry->credentials().username());
4373 ASSERT_EQ(kBar2, entry->credentials().password());
4374
4375 // Make another request, which should automatically send the correct proxy and
4376 // server auth credentials and get another response.
4377 trans =
4378 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4379 rv = trans->Start(&request, callback.callback(), log.bound());
4380 EXPECT_THAT(callback.GetResult(rv), IsOk());
4381 response = trans->GetResponseInfo();
4382 ASSERT_TRUE(response);
4383 EXPECT_EQ(200, response->headers->response_code());
4384 // The password prompt info should not be set.
4385 EXPECT_FALSE(response->auth_challenge.has_value());
4386
4387 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4388 EXPECT_EQ("hi", response_data);
4389
4390 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114391 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menke96092e62019-10-18 04:09:334392}
4393
Matt Menkebe090422019-10-18 20:25:264394// Test the no-tunnel HTTP auth case where proxy and server origins and realms
4395// are the same, but the user/passwords are different, and with different
4396// NetworkIsolationKeys. Sends one request with a NIK, response to both proxy
4397// and auth challenges, sends another request with another NIK, expecting only
4398// the proxy credentials to be cached, and thus sees only a server auth
4399// challenge. Then sends a request with the original NIK, expecting cached proxy
4400// and auth credentials that match the ones used in the first request.
4401//
4402// Serves to verify credentials are correctly separated based on
4403// HttpAuth::Target and NetworkIsolationKeys, but NetworkIsolationKey only
4404// affects server credentials, not proxy credentials.
4405TEST_F(HttpNetworkTransactionTest,
4406 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyNoTunnel) {
4407 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4408 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4409 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4410 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4411
4412 // This test would need to use a single socket without this option enabled.
4413 // Best to use this option when it would affect a test, as it will eventually
4414 // become the default behavior.
4415 base::test::ScopedFeatureList feature_list;
4416 feature_list.InitAndEnableFeature(
4417 features::kPartitionConnectionsByNetworkIsolationKey);
4418
4419 // Proxy matches request URL.
4420 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564421 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkebe090422019-10-18 20:25:264422 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144423 RecordingBoundTestNetLog log;
Matt Menkebe090422019-10-18 20:25:264424 session_deps_.net_log = log.bound().net_log();
4425 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4426 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4427
4428 MockWrite data_writes[] = {
4429 // Initial request gets a proxy auth challenge.
4430 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4431 "Host: myproxy:70\r\n"
4432 "Proxy-Connection: keep-alive\r\n\r\n"),
4433 // Retry with proxy auth credentials, which will result in a server auth
4434 // challenge.
4435 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4436 "Host: myproxy:70\r\n"
4437 "Proxy-Connection: keep-alive\r\n"
4438 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4439 // Retry with proxy and server auth credentials, which gets a response.
4440 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4441 "Host: myproxy:70\r\n"
4442 "Proxy-Connection: keep-alive\r\n"
4443 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4444 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4445 // Another request to the same server and using the same NIK should
4446 // preemptively send the correct cached proxy and server
4447 // auth headers.
4448 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4449 "Host: myproxy:70\r\n"
4450 "Proxy-Connection: keep-alive\r\n"
4451 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4452 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4453 };
4454
4455 MockRead data_reads[] = {
4456 // Proxy auth challenge.
4457 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4458 "Proxy-Connection: keep-alive\r\n"
4459 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4460 "Content-Length: 0\r\n\r\n"),
4461 // Server auth challenge.
4462 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4463 "Proxy-Connection: keep-alive\r\n"
4464 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4465 "Content-Length: 0\r\n\r\n"),
4466 // Response.
4467 MockRead("HTTP/1.1 200 OK\r\n"
4468 "Proxy-Connection: keep-alive\r\n"
4469 "Content-Length: 5\r\n\r\n"
4470 "hello"),
4471 // Response to second request.
4472 MockRead("HTTP/1.1 200 OK\r\n"
4473 "Proxy-Connection: keep-alive\r\n"
4474 "Content-Length: 2\r\n\r\n"
4475 "hi"),
4476 };
4477
4478 StaticSocketDataProvider data(data_reads, data_writes);
4479 session_deps_.socket_factory->AddSocketDataProvider(&data);
4480
4481 MockWrite data_writes2[] = {
4482 // Initial request using a different NetworkIsolationKey includes the
4483 // cached proxy credentials, but not server credentials.
4484 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4485 "Host: myproxy:70\r\n"
4486 "Proxy-Connection: keep-alive\r\n"
4487 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4488 // Retry with proxy and new server auth credentials, which gets a
4489 // response.
4490 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4491 "Host: myproxy:70\r\n"
4492 "Proxy-Connection: keep-alive\r\n"
4493 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4494 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4495 };
4496
4497 MockRead data_reads2[] = {
4498 // Server auth challenge.
4499 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4500 "Proxy-Connection: keep-alive\r\n"
4501 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4502 "Content-Length: 0\r\n\r\n"),
4503 // Response.
4504 MockRead("HTTP/1.1 200 OK\r\n"
4505 "Proxy-Connection: keep-alive\r\n"
4506 "Content-Length: 9\r\n\r\n"
4507 "greetings"),
4508 };
4509
4510 StaticSocketDataProvider data2(data_reads2, data_writes2);
4511 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4512
4513 TestCompletionCallback callback;
4514
4515 HttpRequestInfo request;
4516 request.method = "GET";
4517 request.url = GURL("http://myproxy:70/");
4518 request.traffic_annotation =
4519 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4520 request.network_isolation_key = kNetworkIsolationKey1;
4521
4522 auto trans =
4523 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4524 int rv = trans->Start(&request, callback.callback(), log.bound());
4525 EXPECT_THAT(callback.GetResult(rv), IsOk());
4526 const HttpResponseInfo* response = trans->GetResponseInfo();
4527 ASSERT_TRUE(response);
4528 ASSERT_TRUE(response->headers);
4529 EXPECT_EQ(407, response->headers->response_code());
4530 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4531
4532 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4533 EXPECT_THAT(callback.GetResult(rv), IsOk());
4534 response = trans->GetResponseInfo();
4535 ASSERT_TRUE(response);
4536 EXPECT_EQ(401, response->headers->response_code());
4537 EXPECT_FALSE(response->auth_challenge->is_proxy);
4538 EXPECT_EQ("http://myproxy:70",
4539 response->auth_challenge->challenger.Serialize());
4540 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4541 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4542
4543 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4544 callback.callback());
4545 EXPECT_THAT(callback.GetResult(rv), IsOk());
4546 response = trans->GetResponseInfo();
4547 ASSERT_TRUE(response);
4548 EXPECT_EQ(200, response->headers->response_code());
4549 // The password prompt info should not be set.
4550 EXPECT_FALSE(response->auth_challenge.has_value());
4551 std::string response_data;
4552 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4553 EXPECT_EQ("hello", response_data);
4554
4555 // Check that the proxy credentials were cached correctly. The should be
4556 // accessible with any NetworkIsolationKey.
4557 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4558 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4559 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4560 ASSERT_TRUE(entry);
4561 ASSERT_EQ(kFoo, entry->credentials().username());
4562 ASSERT_EQ(kBar, entry->credentials().password());
4563 EXPECT_EQ(entry,
4564 session->http_auth_cache()->Lookup(
4565 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4566 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4567
4568 // Check that the server credentials were cached correctly. The should be
4569 // accessible with only kNetworkIsolationKey1.
4570 entry = session->http_auth_cache()->Lookup(
4571 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4572 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4573 ASSERT_TRUE(entry);
4574 ASSERT_EQ(kFoo2, entry->credentials().username());
4575 ASSERT_EQ(kBar2, entry->credentials().password());
4576 // Looking up the server entry with another NetworkIsolationKey should fail.
4577 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4578 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4579 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4580
4581 // Make another request with a different NetworkIsolationKey. It should use
4582 // another socket, reuse the cached proxy credentials, but result in a server
4583 // auth challenge.
4584 request.network_isolation_key = kNetworkIsolationKey2;
4585 trans =
4586 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4587 rv = trans->Start(&request, callback.callback(), log.bound());
4588 EXPECT_THAT(callback.GetResult(rv), IsOk());
4589 response = trans->GetResponseInfo();
4590 ASSERT_TRUE(response);
4591 EXPECT_EQ(401, response->headers->response_code());
4592 EXPECT_FALSE(response->auth_challenge->is_proxy);
4593 EXPECT_EQ("http://myproxy:70",
4594 response->auth_challenge->challenger.Serialize());
4595 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4596 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4597
4598 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4599 callback.callback());
4600 EXPECT_THAT(callback.GetResult(rv), IsOk());
4601 response = trans->GetResponseInfo();
4602 ASSERT_TRUE(response);
4603 EXPECT_EQ(200, response->headers->response_code());
4604 // The password prompt info should not be set.
4605 EXPECT_FALSE(response->auth_challenge.has_value());
4606 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4607 EXPECT_EQ("greetings", response_data);
4608
4609 // Check that the proxy credentials are still cached.
4610 entry = session->http_auth_cache()->Lookup(
4611 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4612 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4613 ASSERT_TRUE(entry);
4614 ASSERT_EQ(kFoo, entry->credentials().username());
4615 ASSERT_EQ(kBar, entry->credentials().password());
4616 EXPECT_EQ(entry,
4617 session->http_auth_cache()->Lookup(
4618 GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4619 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4620
4621 // Check that the correct server credentials are cached for each
4622 // NetworkIsolationKey.
4623 entry = session->http_auth_cache()->Lookup(
4624 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4625 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4626 ASSERT_TRUE(entry);
4627 ASSERT_EQ(kFoo2, entry->credentials().username());
4628 ASSERT_EQ(kBar2, entry->credentials().password());
4629 entry = session->http_auth_cache()->Lookup(
4630 GURL("http://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4631 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4632 ASSERT_TRUE(entry);
4633 ASSERT_EQ(kFoo3, entry->credentials().username());
4634 ASSERT_EQ(kBar3, entry->credentials().password());
4635
4636 // Make a request with the original NetworkIsolationKey. It should reuse the
4637 // first socket, and the proxy credentials sent on the first socket.
4638 request.network_isolation_key = kNetworkIsolationKey1;
4639 trans =
4640 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4641 rv = trans->Start(&request, callback.callback(), log.bound());
4642 EXPECT_THAT(callback.GetResult(rv), IsOk());
4643 response = trans->GetResponseInfo();
4644 ASSERT_TRUE(response);
4645 EXPECT_EQ(200, response->headers->response_code());
4646 // The password prompt info should not be set.
4647 EXPECT_FALSE(response->auth_challenge.has_value());
4648 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4649 EXPECT_EQ("hi", response_data);
4650
4651 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114652 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menkebe090422019-10-18 20:25:264653}
4654
4655// Much like the test above, but uses tunnelled connections.
4656TEST_F(HttpNetworkTransactionTest,
4657 BasicAuthProxyMatchesServerAuthWithNetworkIsolationKeyWithTunnel) {
4658 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
4659 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
4660 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
4661 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
4662
4663 // This test would need to use a single socket without this option enabled.
4664 // Best to use this option when it would affect a test, as it will eventually
4665 // become the default behavior.
4666 base::test::ScopedFeatureList feature_list;
4667 feature_list.InitAndEnableFeature(
4668 features::kPartitionConnectionsByNetworkIsolationKey);
4669
4670 // Proxy matches request URL.
4671 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:564672 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkebe090422019-10-18 20:25:264673 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:144674 RecordingBoundTestNetLog log;
Matt Menkebe090422019-10-18 20:25:264675 session_deps_.net_log = log.bound().net_log();
4676 session_deps_.key_auth_cache_server_entries_by_network_isolation_key = true;
4677 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4678
4679 MockWrite data_writes[] = {
4680 // Initial tunnel request gets a proxy auth challenge.
4681 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4682 "Host: myproxy:70\r\n"
4683 "Proxy-Connection: keep-alive\r\n\r\n"),
4684 // Retry with proxy auth credentials, which will result in establishing a
4685 // tunnel.
4686 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4687 "Host: myproxy:70\r\n"
4688 "Proxy-Connection: keep-alive\r\n"
4689 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4690 // Request over the tunnel, which gets a server auth challenge.
4691 MockWrite("GET / HTTP/1.1\r\n"
4692 "Host: myproxy:70\r\n"
4693 "Connection: keep-alive\r\n\r\n"),
4694 // Retry with server auth credentials, which gets a response.
4695 MockWrite("GET / HTTP/1.1\r\n"
4696 "Host: myproxy:70\r\n"
4697 "Connection: keep-alive\r\n"
4698 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4699 // Another request to the same server and using the same NIK should
4700 // preemptively send the correct cached server
4701 // auth header. Since a tunnel was already established, the proxy headers
4702 // won't be sent again except when establishing another tunnel.
4703 MockWrite("GET / HTTP/1.1\r\n"
4704 "Host: myproxy:70\r\n"
4705 "Connection: keep-alive\r\n"
4706 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4707 };
4708
4709 MockRead data_reads[] = {
4710 // Proxy auth challenge.
4711 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4712 "Proxy-Connection: keep-alive\r\n"
4713 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4714 "Content-Length: 0\r\n\r\n"),
4715 // Tunnel success
4716 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4717 // Server auth challenge.
4718 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4719 "Connection: keep-alive\r\n"
4720 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4721 "Content-Length: 0\r\n\r\n"),
4722 // Response.
4723 MockRead("HTTP/1.1 200 OK\r\n"
4724 "Connection: keep-alive\r\n"
4725 "Content-Length: 5\r\n\r\n"
4726 "hello"),
4727 // Response to second request.
4728 MockRead("HTTP/1.1 200 OK\r\n"
4729 "Connection: keep-alive\r\n"
4730 "Content-Length: 2\r\n\r\n"
4731 "hi"),
4732 };
4733
4734 StaticSocketDataProvider data(data_reads, data_writes);
4735 session_deps_.socket_factory->AddSocketDataProvider(&data);
4736 // One for the proxy connection, one of the server connection.
4737 SSLSocketDataProvider ssl(ASYNC, OK);
4738 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4739 SSLSocketDataProvider ssl2(ASYNC, OK);
4740 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4741
4742 MockWrite data_writes2[] = {
4743 // Initial request using a different NetworkIsolationKey includes the
4744 // cached proxy credentials when establishing a tunnel.
4745 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4746 "Host: myproxy:70\r\n"
4747 "Proxy-Connection: keep-alive\r\n"
4748 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4749 // Request over the tunnel, which gets a server auth challenge. Cached
4750 // credentials cannot be used, since the NIK is different.
4751 MockWrite("GET / HTTP/1.1\r\n"
4752 "Host: myproxy:70\r\n"
4753 "Connection: keep-alive\r\n\r\n"),
4754 // Retry with server auth credentials, which gets a response.
4755 MockWrite("GET / HTTP/1.1\r\n"
4756 "Host: myproxy:70\r\n"
4757 "Connection: keep-alive\r\n"
4758 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4759 };
4760
4761 MockRead data_reads2[] = {
4762 // Tunnel success
4763 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4764 // Server auth challenge.
4765 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4766 "Connection: keep-alive\r\n"
4767 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4768 "Content-Length: 0\r\n\r\n"),
4769 // Response.
4770 MockRead("HTTP/1.1 200 OK\r\n"
4771 "Connection: keep-alive\r\n"
4772 "Content-Length: 9\r\n\r\n"
4773 "greetings"),
4774 };
4775
4776 StaticSocketDataProvider data2(data_reads2, data_writes2);
4777 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4778 // One for the proxy connection, one of the server connection.
4779 SSLSocketDataProvider ssl3(ASYNC, OK);
4780 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
4781 SSLSocketDataProvider ssl4(ASYNC, OK);
4782 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
4783
4784 TestCompletionCallback callback;
4785
4786 HttpRequestInfo request;
4787 request.method = "GET";
4788 request.url = GURL("https://myproxy:70/");
4789 request.traffic_annotation =
4790 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4791 request.network_isolation_key = kNetworkIsolationKey1;
4792
4793 auto trans =
4794 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4795 int rv = trans->Start(&request, callback.callback(), log.bound());
4796 EXPECT_THAT(callback.GetResult(rv), IsOk());
4797 const HttpResponseInfo* response = trans->GetResponseInfo();
4798 ASSERT_TRUE(response);
4799 ASSERT_TRUE(response->headers);
4800 EXPECT_EQ(407, response->headers->response_code());
4801 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
4802
4803 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4804 EXPECT_THAT(callback.GetResult(rv), IsOk());
4805 response = trans->GetResponseInfo();
4806 ASSERT_TRUE(response);
4807 EXPECT_EQ(401, response->headers->response_code());
4808 EXPECT_FALSE(response->auth_challenge->is_proxy);
4809 EXPECT_EQ("https://myproxy:70",
4810 response->auth_challenge->challenger.Serialize());
4811 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4812 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4813
4814 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4815 callback.callback());
4816 EXPECT_THAT(callback.GetResult(rv), IsOk());
4817 response = trans->GetResponseInfo();
4818 ASSERT_TRUE(response);
4819 EXPECT_EQ(200, response->headers->response_code());
4820 // The password prompt info should not be set.
4821 EXPECT_FALSE(response->auth_challenge.has_value());
4822 std::string response_data;
4823 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4824 EXPECT_EQ("hello", response_data);
4825
4826 // Check that the proxy credentials were cached correctly. The should be
4827 // accessible with any NetworkIsolationKey.
4828 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4829 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4830 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4831 ASSERT_TRUE(entry);
4832 ASSERT_EQ(kFoo, entry->credentials().username());
4833 ASSERT_EQ(kBar, entry->credentials().password());
4834 EXPECT_EQ(entry,
4835 session->http_auth_cache()->Lookup(
4836 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4837 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4838
4839 // Check that the server credentials were cached correctly. The should be
4840 // accessible with only kNetworkIsolationKey1.
4841 entry = session->http_auth_cache()->Lookup(
4842 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4843 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4844 ASSERT_TRUE(entry);
4845 ASSERT_EQ(kFoo2, entry->credentials().username());
4846 ASSERT_EQ(kBar2, entry->credentials().password());
4847 // Looking up the server entry with another NetworkIsolationKey should fail.
4848 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4849 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4850 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4851
4852 // Make another request with a different NetworkIsolationKey. It should use
4853 // another socket, reuse the cached proxy credentials, but result in a server
4854 // auth challenge.
4855 request.network_isolation_key = kNetworkIsolationKey2;
4856 trans =
4857 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4858 rv = trans->Start(&request, callback.callback(), log.bound());
4859 EXPECT_THAT(callback.GetResult(rv), IsOk());
4860 response = trans->GetResponseInfo();
4861 ASSERT_TRUE(response);
4862 EXPECT_EQ(401, response->headers->response_code());
4863 EXPECT_FALSE(response->auth_challenge->is_proxy);
4864 EXPECT_EQ("https://myproxy:70",
4865 response->auth_challenge->challenger.Serialize());
4866 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4867 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4868
4869 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4870 callback.callback());
4871 EXPECT_THAT(callback.GetResult(rv), IsOk());
4872 response = trans->GetResponseInfo();
4873 ASSERT_TRUE(response);
4874 EXPECT_EQ(200, response->headers->response_code());
4875 // The password prompt info should not be set.
4876 EXPECT_FALSE(response->auth_challenge.has_value());
4877 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4878 EXPECT_EQ("greetings", response_data);
4879
4880 // Check that the proxy credentials are still cached.
4881 entry = session->http_auth_cache()->Lookup(
4882 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4883 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4884 ASSERT_TRUE(entry);
4885 ASSERT_EQ(kFoo, entry->credentials().username());
4886 ASSERT_EQ(kBar, entry->credentials().password());
4887 EXPECT_EQ(entry,
4888 session->http_auth_cache()->Lookup(
4889 GURL("https://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1",
4890 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2));
4891
4892 // Check that the correct server credentials are cached for each
4893 // NetworkIsolationKey.
4894 entry = session->http_auth_cache()->Lookup(
4895 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4896 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey1);
4897 ASSERT_TRUE(entry);
4898 ASSERT_EQ(kFoo2, entry->credentials().username());
4899 ASSERT_EQ(kBar2, entry->credentials().password());
4900 entry = session->http_auth_cache()->Lookup(
4901 GURL("https://myproxy:70"), HttpAuth::AUTH_SERVER, "MyRealm1",
4902 HttpAuth::AUTH_SCHEME_BASIC, kNetworkIsolationKey2);
4903 ASSERT_TRUE(entry);
4904 ASSERT_EQ(kFoo3, entry->credentials().username());
4905 ASSERT_EQ(kBar3, entry->credentials().password());
4906
4907 // Make a request with the original NetworkIsolationKey. It should reuse the
4908 // first socket, and the proxy credentials sent on the first socket.
4909 request.network_isolation_key = kNetworkIsolationKey1;
4910 trans =
4911 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4912 rv = trans->Start(&request, callback.callback(), log.bound());
4913 EXPECT_THAT(callback.GetResult(rv), IsOk());
4914 response = trans->GetResponseInfo();
4915 ASSERT_TRUE(response);
4916 EXPECT_EQ(200, response->headers->response_code());
4917 // The password prompt info should not be set.
4918 EXPECT_FALSE(response->auth_challenge.has_value());
4919 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4920 EXPECT_EQ("hi", response_data);
4921
4922 trans.reset();
Matt Menke433de6d2020-03-04 00:24:114923 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Matt Menkebe090422019-10-18 20:25:264924}
4925
ttuttle7933c112015-01-06 00:55:244926// Test that we don't pass extraneous headers from the proxy's response to the
4927// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014928TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244929 HttpRequestInfo request;
4930 request.method = "GET";
bncce36dca22015-04-21 22:11:234931 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104932 request.traffic_annotation =
4933 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244934
4935 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:564936 session_deps_.proxy_resolution_service =
4937 ConfiguredProxyResolutionService::CreateFixed(
4938 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244939
danakj1fd259a02016-04-16 03:17:094940 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244941
bnc691fda62016-08-12 00:43:164942 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244943
4944 // Since we have proxy, should try to establish tunnel.
4945 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174946 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4947 "Host: www.example.org:443\r\n"
4948 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244949 };
4950
4951 // The proxy responds to the connect with a 407.
4952 MockRead data_reads[] = {
4953 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4954 MockRead("X-Foo: bar\r\n"),
4955 MockRead("Set-Cookie: foo=bar\r\n"),
4956 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4957 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234958 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244959 };
4960
Ryan Sleevib8d7ea02018-05-07 20:01:014961 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244962 session_deps_.socket_factory->AddSocketDataProvider(&data);
4963
4964 TestCompletionCallback callback;
4965
tfarina42834112016-09-22 13:38:204966 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014967 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244968
4969 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014970 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244971
bnc691fda62016-08-12 00:43:164972 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244973 ASSERT_TRUE(response);
4974 ASSERT_TRUE(response->headers);
4975 EXPECT_TRUE(response->headers->IsKeepAlive());
4976 EXPECT_EQ(407, response->headers->response_code());
4977 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4978 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4979 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4980
4981 std::string response_data;
bnc691fda62016-08-12 00:43:164982 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014983 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244984
4985 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
Matt Menke433de6d2020-03-04 00:24:114986 session->CloseAllConnections(ERR_FAILED, "Very good reason");
ttuttle7933c112015-01-06 00:55:244987}
4988
[email protected]8fdbcd22010-05-05 02:54:524989// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4990// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014991TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524992 HttpRequestInfo request;
4993 request.method = "GET";
bncce36dca22015-04-21 22:11:234994 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104995 request.traffic_annotation =
4996 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524997
[email protected]cb9bf6ca2011-01-28 13:15:274998 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094999 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:165000 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:275001
[email protected]8fdbcd22010-05-05 02:54:525002 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235003 MockWrite(
5004 "GET / HTTP/1.1\r\n"
5005 "Host: www.example.org\r\n"
5006 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:525007 };
5008
5009 MockRead data_reads1[] = {
5010 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
5011 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5012 // Large content-length -- won't matter, as connection will be reset.
5013 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065014 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:525015 };
5016
Ryan Sleevib8d7ea02018-05-07 20:01:015017 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075018 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:525019
[email protected]49639fa2011-12-20 23:22:415020 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:525021
tfarina42834112016-09-22 13:38:205022 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015023 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:525024
5025 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015026 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:525027}
5028
[email protected]7a67a8152010-11-05 18:31:105029// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
5030// through a non-authenticating proxy. The request should fail with
5031// ERR_UNEXPECTED_PROXY_AUTH.
5032// Note that it is impossible to detect if an HTTP server returns a 407 through
5033// a non-authenticating proxy - there is nothing to indicate whether the
5034// response came from the proxy or the server, so it is treated as if the proxy
5035// issued the challenge.
bncd16676a2016-07-20 16:23:015036TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:275037 HttpRequestInfo request;
5038 request.method = "GET";
bncce36dca22015-04-21 22:11:235039 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105040 request.traffic_annotation =
5041 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275042
Nicolas Arciniegad2013f92020-02-07 23:00:565043 session_deps_.proxy_resolution_service =
5044 ConfiguredProxyResolutionService::CreateFixed(
5045 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:145046 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075047 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095048 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:105049
[email protected]7a67a8152010-11-05 18:31:105050 // Since we have proxy, should try to establish tunnel.
5051 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175052 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5053 "Host: www.example.org:443\r\n"
5054 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:105055
rsleevidb16bb02015-11-12 23:47:175056 MockWrite("GET / HTTP/1.1\r\n"
5057 "Host: www.example.org\r\n"
5058 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:105059 };
5060
5061 MockRead data_reads1[] = {
5062 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5063
5064 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
5065 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5066 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:065067 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:105068 };
5069
Ryan Sleevib8d7ea02018-05-07 20:01:015070 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075071 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065072 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075073 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:105074
[email protected]49639fa2011-12-20 23:22:415075 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:105076
bnc691fda62016-08-12 00:43:165077 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:105078
bnc691fda62016-08-12 00:43:165079 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015080 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:105081
5082 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015083 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:545084 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:105085 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:005086 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
5087 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:105088 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:405089 entries, pos,
mikecirone8b85c432016-09-08 19:11:005090 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
5091 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:105092}
[email protected]2df19bb2010-08-25 20:13:465093
mmenke2a1781d2015-10-07 19:25:335094// Test a proxy auth scheme that allows default credentials and a proxy server
5095// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:015096TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335097 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
5098 HttpRequestInfo request;
5099 request.method = "GET";
5100 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105101 request.traffic_annotation =
5102 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335103
5104 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595105 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565106 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495107 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335108
Jeremy Roman0579ed62017-08-29 15:56:195109 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335110 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195111 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335112 mock_handler->set_allows_default_credentials(true);
5113 auth_handler_factory->AddMockHandler(mock_handler.release(),
5114 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485115 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335116
5117 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585118 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095119 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335120
5121 // Since we have proxy, should try to establish tunnel.
5122 MockWrite data_writes1[] = {
5123 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175124 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335125 "Proxy-Connection: keep-alive\r\n\r\n"),
5126 };
5127
5128 // The proxy responds to the connect with a 407, using a non-persistent
5129 // connection.
5130 MockRead data_reads1[] = {
5131 // No credentials.
5132 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5133 MockRead("Proxy-Authenticate: Mock\r\n"),
5134 MockRead("Proxy-Connection: close\r\n\r\n"),
5135 };
5136
5137 // Since the first connection couldn't be reused, need to establish another
5138 // once given credentials.
5139 MockWrite data_writes2[] = {
5140 // After calling trans->RestartWithAuth(), this is the request we should
5141 // be issuing -- the final header line contains the credentials.
5142 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175143 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335144 "Proxy-Connection: keep-alive\r\n"
5145 "Proxy-Authorization: auth_token\r\n\r\n"),
5146
5147 MockWrite("GET / HTTP/1.1\r\n"
5148 "Host: www.example.org\r\n"
5149 "Connection: keep-alive\r\n\r\n"),
5150 };
5151
5152 MockRead data_reads2[] = {
5153 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5154
5155 MockRead("HTTP/1.1 200 OK\r\n"),
5156 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5157 MockRead("Content-Length: 5\r\n\r\n"),
5158 MockRead(SYNCHRONOUS, "hello"),
5159 };
5160
Ryan Sleevib8d7ea02018-05-07 20:01:015161 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335162 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015163 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335164 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5165 SSLSocketDataProvider ssl(ASYNC, OK);
5166 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5167
bnc87dcefc2017-05-25 12:47:585168 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195169 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335170
5171 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205172 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015173 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335174
5175 const HttpResponseInfo* response = trans->GetResponseInfo();
5176 ASSERT_TRUE(response);
5177 ASSERT_TRUE(response->headers);
5178 EXPECT_FALSE(response->headers->IsKeepAlive());
5179 EXPECT_EQ(407, response->headers->response_code());
5180 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5181 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585182 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335183
5184 LoadTimingInfo load_timing_info;
5185 // CONNECT requests and responses are handled at the connect job level, so
5186 // the transaction does not yet have a connection.
5187 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5188
5189 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015190 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335191 response = trans->GetResponseInfo();
5192 ASSERT_TRUE(response);
5193 ASSERT_TRUE(response->headers);
5194 EXPECT_TRUE(response->headers->IsKeepAlive());
5195 EXPECT_EQ(200, response->headers->response_code());
5196 EXPECT_EQ(5, response->headers->GetContentLength());
5197 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5198
5199 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585200 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335201
5202 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5203 TestLoadTimingNotReusedWithPac(load_timing_info,
5204 CONNECT_TIMING_HAS_SSL_TIMES);
5205
5206 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115207 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335208}
5209
5210// Test a proxy auth scheme that allows default credentials and a proxy server
5211// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:015212TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335213 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
5214 HttpRequestInfo request;
5215 request.method = "GET";
5216 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105217 request.traffic_annotation =
5218 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335219
5220 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595221 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565222 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495223 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335224
Jeremy Roman0579ed62017-08-29 15:56:195225 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335226 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195227 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335228 mock_handler->set_allows_default_credentials(true);
5229 auth_handler_factory->AddMockHandler(mock_handler.release(),
5230 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485231 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335232
5233 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585234 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095235 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335236
5237 // Should try to establish tunnel.
5238 MockWrite data_writes1[] = {
5239 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175240 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335241 "Proxy-Connection: keep-alive\r\n\r\n"),
5242
5243 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175244 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335245 "Proxy-Connection: keep-alive\r\n"
5246 "Proxy-Authorization: auth_token\r\n\r\n"),
5247 };
5248
5249 // The proxy responds to the connect with a 407, using a non-persistent
5250 // connection.
5251 MockRead data_reads1[] = {
5252 // No credentials.
5253 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5254 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5255 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5256 };
5257
5258 // Since the first connection was closed, need to establish another once given
5259 // credentials.
5260 MockWrite data_writes2[] = {
5261 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175262 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335263 "Proxy-Connection: keep-alive\r\n"
5264 "Proxy-Authorization: auth_token\r\n\r\n"),
5265
5266 MockWrite("GET / HTTP/1.1\r\n"
5267 "Host: www.example.org\r\n"
5268 "Connection: keep-alive\r\n\r\n"),
5269 };
5270
5271 MockRead data_reads2[] = {
5272 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5273
5274 MockRead("HTTP/1.1 200 OK\r\n"),
5275 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5276 MockRead("Content-Length: 5\r\n\r\n"),
5277 MockRead(SYNCHRONOUS, "hello"),
5278 };
5279
Ryan Sleevib8d7ea02018-05-07 20:01:015280 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335281 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015282 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335283 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5284 SSLSocketDataProvider ssl(ASYNC, OK);
5285 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5286
bnc87dcefc2017-05-25 12:47:585287 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195288 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335289
5290 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205291 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015292 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335293
5294 const HttpResponseInfo* response = trans->GetResponseInfo();
5295 ASSERT_TRUE(response);
5296 ASSERT_TRUE(response->headers);
5297 EXPECT_TRUE(response->headers->IsKeepAlive());
5298 EXPECT_EQ(407, response->headers->response_code());
5299 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5300 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585301 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335302
5303 LoadTimingInfo load_timing_info;
5304 // CONNECT requests and responses are handled at the connect job level, so
5305 // the transaction does not yet have a connection.
5306 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5307
5308 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015309 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335310
5311 response = trans->GetResponseInfo();
5312 ASSERT_TRUE(response);
5313 ASSERT_TRUE(response->headers);
5314 EXPECT_TRUE(response->headers->IsKeepAlive());
5315 EXPECT_EQ(200, response->headers->response_code());
5316 EXPECT_EQ(5, response->headers->GetContentLength());
5317 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5318
5319 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585320 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335321
5322 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5323 TestLoadTimingNotReusedWithPac(load_timing_info,
5324 CONNECT_TIMING_HAS_SSL_TIMES);
5325
5326 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115327 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335328}
5329
5330// Test a proxy auth scheme that allows default credentials and a proxy server
5331// that hangs up when credentials are initially sent, and hangs up again when
5332// they are retried.
bncd16676a2016-07-20 16:23:015333TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335334 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
5335 HttpRequestInfo request;
5336 request.method = "GET";
5337 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105338 request.traffic_annotation =
5339 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335340
5341 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595342 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565343 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495344 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335345
Jeremy Roman0579ed62017-08-29 15:56:195346 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335347 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195348 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335349 mock_handler->set_allows_default_credentials(true);
5350 auth_handler_factory->AddMockHandler(mock_handler.release(),
5351 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485352 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335353
5354 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585355 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095356 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335357
5358 // Should try to establish tunnel.
5359 MockWrite data_writes1[] = {
5360 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175361 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335362 "Proxy-Connection: keep-alive\r\n\r\n"),
5363
5364 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175365 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335366 "Proxy-Connection: keep-alive\r\n"
5367 "Proxy-Authorization: auth_token\r\n\r\n"),
5368 };
5369
5370 // The proxy responds to the connect with a 407, and then hangs up after the
5371 // second request is sent.
5372 MockRead data_reads1[] = {
5373 // No credentials.
5374 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5375 MockRead("Content-Length: 0\r\n"),
5376 MockRead("Proxy-Connection: keep-alive\r\n"),
5377 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5378 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5379 };
5380
5381 // HttpNetworkTransaction sees a reused connection that was closed with
5382 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
5383 // request.
5384 MockWrite data_writes2[] = {
5385 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175386 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335387 "Proxy-Connection: keep-alive\r\n\r\n"),
5388 };
5389
5390 // The proxy, having had more than enough of us, just hangs up.
5391 MockRead data_reads2[] = {
5392 // No credentials.
5393 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5394 };
5395
Ryan Sleevib8d7ea02018-05-07 20:01:015396 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335397 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015398 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335399 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5400
bnc87dcefc2017-05-25 12:47:585401 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195402 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335403
5404 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205405 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015406 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335407
5408 const HttpResponseInfo* response = trans->GetResponseInfo();
5409 ASSERT_TRUE(response);
5410 ASSERT_TRUE(response->headers);
5411 EXPECT_TRUE(response->headers->IsKeepAlive());
5412 EXPECT_EQ(407, response->headers->response_code());
5413 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5414 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585415 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335416
5417 LoadTimingInfo load_timing_info;
5418 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5419
5420 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015421 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:335422
5423 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115424 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335425}
5426
Asanka Herathbc3f8f62018-11-16 23:08:305427// This test exercises an odd edge case where the proxy closes the connection
5428// after the authentication handshake is complete. Presumably this technique is
5429// used in lieu of returning a 403 or 5xx status code when the authentication
5430// succeeds, but the user is not authorized to connect to the destination
5431// server. There's no standard for what a proxy should do to indicate a blocked
5432// site.
5433TEST_F(HttpNetworkTransactionTest,
5434 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
5435 HttpRequestInfo request;
5436 request.method = "GET";
5437 request.url = GURL("https://www.example.org/");
5438 request.traffic_annotation =
5439 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5440
5441 // Configure against proxy server "myproxy:70".
5442 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565443 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Asanka Herathbc3f8f62018-11-16 23:08:305444 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5445
5446 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5447 auth_handler_factory->set_do_init_from_challenge(true);
5448
5449 // Create two mock AuthHandlers. This is because the transaction gets retried
5450 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
5451 // was a real network error.
5452 //
5453 // The handlers support both default and explicit credentials. The retry
5454 // mentioned above should be able to reuse the default identity. Thus there
5455 // should never be a need to prompt for explicit credentials.
5456 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5457 mock_handler->set_allows_default_credentials(true);
5458 mock_handler->set_allows_explicit_credentials(true);
5459 mock_handler->set_connection_based(true);
5460 auth_handler_factory->AddMockHandler(mock_handler.release(),
5461 HttpAuth::AUTH_PROXY);
5462 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5463 mock_handler->set_allows_default_credentials(true);
5464 mock_handler->set_allows_explicit_credentials(true);
5465 mock_handler->set_connection_based(true);
5466 auth_handler_factory->AddMockHandler(mock_handler.release(),
5467 HttpAuth::AUTH_PROXY);
5468 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5469
Matt Muellerde5dadf2019-11-27 20:11:585470 session_deps_.net_log = NetLog::Get();
Asanka Herathbc3f8f62018-11-16 23:08:305471 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5472
5473 // Data for both sockets.
5474 //
5475 // Writes are for the tunnel establishment attempts and the
5476 // authentication handshake.
5477 MockWrite data_writes1[] = {
5478 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5479 "Host: www.example.org:443\r\n"
5480 "Proxy-Connection: keep-alive\r\n\r\n"),
5481
5482 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5483 "Host: www.example.org:443\r\n"
5484 "Proxy-Connection: keep-alive\r\n"
5485 "Proxy-Authorization: auth_token\r\n\r\n"),
5486
5487 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5488 "Host: www.example.org:443\r\n"
5489 "Proxy-Connection: keep-alive\r\n"
5490 "Proxy-Authorization: auth_token\r\n\r\n"),
5491 };
5492
5493 // The server side of the authentication handshake. Note that the response to
5494 // the final CONNECT request is ERR_CONNECTION_CLOSED.
5495 MockRead data_reads1[] = {
5496 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5497 MockRead("Content-Length: 0\r\n"),
5498 MockRead("Proxy-Connection: keep-alive\r\n"),
5499 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5500
5501 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5502 MockRead("Content-Length: 0\r\n"),
5503 MockRead("Proxy-Connection: keep-alive\r\n"),
5504 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
5505
5506 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5507 };
5508
5509 StaticSocketDataProvider data1(data_reads1, data_writes1);
5510 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5511
5512 // The second socket is for the reconnection attempt. Data is identical to the
5513 // first attempt.
5514 StaticSocketDataProvider data2(data_reads1, data_writes1);
5515 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5516
5517 auto trans =
5518 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5519
5520 TestCompletionCallback callback;
5521 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5522
5523 // Two rounds per handshake. After one retry, the error is propagated up the
5524 // stack.
5525 for (int i = 0; i < 4; ++i) {
5526 EXPECT_THAT(callback.GetResult(rv), IsOk());
5527
5528 const HttpResponseInfo* response = trans->GetResponseInfo();
5529 ASSERT_TRUE(response);
5530 ASSERT_TRUE(response->headers);
5531 EXPECT_EQ(407, response->headers->response_code());
5532 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
5533
5534 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5535 }
5536
5537 // One shall be the number thou shalt retry, and the number of the retrying
5538 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
5539 // that thou then proceed to one. Three is right out. Once the number one,
5540 // being the first number, be reached, then lobbest thou thy
5541 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
5542 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
5543
5544 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115545 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Asanka Herathbc3f8f62018-11-16 23:08:305546}
5547
mmenke2a1781d2015-10-07 19:25:335548// Test a proxy auth scheme that allows default credentials and a proxy server
5549// that hangs up when credentials are initially sent, and sends a challenge
5550// again they are retried.
bncd16676a2016-07-20 16:23:015551TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:335552 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
5553 HttpRequestInfo request;
5554 request.method = "GET";
5555 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105556 request.traffic_annotation =
5557 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335558
5559 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595560 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565561 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:495562 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:335563
Jeremy Roman0579ed62017-08-29 15:56:195564 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:335565 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:195566 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335567 mock_handler->set_allows_default_credentials(true);
5568 auth_handler_factory->AddMockHandler(mock_handler.release(),
5569 HttpAuth::AUTH_PROXY);
5570 // Add another handler for the second challenge. It supports default
5571 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195572 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:335573 mock_handler->set_allows_default_credentials(true);
5574 auth_handler_factory->AddMockHandler(mock_handler.release(),
5575 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:485576 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:335577
5578 // Add NetLog just so can verify load timing information gets a NetLog ID.
Matt Muellerde5dadf2019-11-27 20:11:585579 session_deps_.net_log = NetLog::Get();
danakj1fd259a02016-04-16 03:17:095580 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:335581
5582 // Should try to establish tunnel.
5583 MockWrite data_writes1[] = {
5584 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175585 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335586 "Proxy-Connection: keep-alive\r\n\r\n"),
5587 };
5588
5589 // The proxy responds to the connect with a 407, using a non-persistent
5590 // connection.
5591 MockRead data_reads1[] = {
5592 // No credentials.
5593 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5594 MockRead("Proxy-Authenticate: Mock\r\n"),
5595 MockRead("Proxy-Connection: close\r\n\r\n"),
5596 };
5597
5598 // Since the first connection was closed, need to establish another once given
5599 // credentials.
5600 MockWrite data_writes2[] = {
5601 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:175602 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:335603 "Proxy-Connection: keep-alive\r\n"
5604 "Proxy-Authorization: auth_token\r\n\r\n"),
5605 };
5606
5607 MockRead data_reads2[] = {
5608 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5609 MockRead("Proxy-Authenticate: Mock\r\n"),
5610 MockRead("Proxy-Connection: close\r\n\r\n"),
5611 };
5612
Ryan Sleevib8d7ea02018-05-07 20:01:015613 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:335614 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:015615 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:335616 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5617 SSLSocketDataProvider ssl(ASYNC, OK);
5618 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5619
bnc87dcefc2017-05-25 12:47:585620 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195621 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:335622
5623 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:205624 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:015625 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335626
5627 const HttpResponseInfo* response = trans->GetResponseInfo();
5628 ASSERT_TRUE(response);
5629 ASSERT_TRUE(response->headers);
5630 EXPECT_EQ(407, response->headers->response_code());
5631 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5632 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585633 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335634
5635 LoadTimingInfo load_timing_info;
5636 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5637
5638 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:015639 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:335640 response = trans->GetResponseInfo();
5641 ASSERT_TRUE(response);
5642 ASSERT_TRUE(response->headers);
5643 EXPECT_EQ(407, response->headers->response_code());
5644 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585645 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:335646
5647 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115648 session->CloseAllConnections(ERR_FAILED, "Very good reason");
mmenke2a1781d2015-10-07 19:25:335649}
5650
asankae2257db2016-10-11 22:03:165651// A more nuanced test than GenerateAuthToken test which asserts that
5652// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
5653// unnecessarily invalidated, and that if the server co-operates, the
5654// authentication handshake can continue with the same scheme but with a
5655// different identity.
5656TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
5657 HttpRequestInfo request;
5658 request.method = "GET";
5659 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105660 request.traffic_annotation =
5661 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:165662
Jeremy Roman0579ed62017-08-29 15:56:195663 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:165664 auth_handler_factory->set_do_init_from_challenge(true);
5665
5666 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:195667 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165668 mock_handler->set_allows_default_credentials(true);
5669 mock_handler->set_allows_explicit_credentials(true);
5670 mock_handler->set_connection_based(true);
5671 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
5672 auth_handler_factory->AddMockHandler(mock_handler.release(),
5673 HttpAuth::AUTH_SERVER);
5674
5675 // Add another handler for the second challenge. It supports default
5676 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:195677 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:165678 mock_handler->set_allows_default_credentials(true);
5679 mock_handler->set_allows_explicit_credentials(true);
5680 mock_handler->set_connection_based(true);
5681 auth_handler_factory->AddMockHandler(mock_handler.release(),
5682 HttpAuth::AUTH_SERVER);
5683 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5684
5685 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5686
5687 MockWrite data_writes1[] = {
5688 MockWrite("GET / HTTP/1.1\r\n"
5689 "Host: www.example.org\r\n"
5690 "Connection: keep-alive\r\n\r\n"),
5691 };
5692
5693 MockRead data_reads1[] = {
5694 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5695 "WWW-Authenticate: Mock\r\n"
5696 "Connection: keep-alive\r\n\r\n"),
5697 };
5698
5699 // Identical to data_writes1[]. The AuthHandler encounters a
5700 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
5701 // transaction procceds without an authorization header.
5702 MockWrite data_writes2[] = {
5703 MockWrite("GET / HTTP/1.1\r\n"
5704 "Host: www.example.org\r\n"
5705 "Connection: keep-alive\r\n\r\n"),
5706 };
5707
5708 MockRead data_reads2[] = {
5709 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5710 "WWW-Authenticate: Mock\r\n"
5711 "Connection: keep-alive\r\n\r\n"),
5712 };
5713
5714 MockWrite data_writes3[] = {
5715 MockWrite("GET / HTTP/1.1\r\n"
5716 "Host: www.example.org\r\n"
5717 "Connection: keep-alive\r\n"
5718 "Authorization: auth_token\r\n\r\n"),
5719 };
5720
5721 MockRead data_reads3[] = {
5722 MockRead("HTTP/1.1 200 OK\r\n"
5723 "Content-Length: 5\r\n"
5724 "Content-Type: text/plain\r\n"
5725 "Connection: keep-alive\r\n\r\n"
5726 "Hello"),
5727 };
5728
Ryan Sleevib8d7ea02018-05-07 20:01:015729 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:165730 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5731
Ryan Sleevib8d7ea02018-05-07 20:01:015732 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:165733 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5734
Ryan Sleevib8d7ea02018-05-07 20:01:015735 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:165736 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5737
bnc87dcefc2017-05-25 12:47:585738 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:195739 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:165740
5741 TestCompletionCallback callback;
5742 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5743 EXPECT_THAT(callback.GetResult(rv), IsOk());
5744
5745 const HttpResponseInfo* response = trans->GetResponseInfo();
5746 ASSERT_TRUE(response);
5747 ASSERT_TRUE(response->headers);
5748 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5749
5750 // The following three tests assert that an authentication challenge was
5751 // received and that the stack is ready to respond to the challenge using
5752 // ambient credentials.
5753 EXPECT_EQ(401, response->headers->response_code());
5754 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585755 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165756
5757 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5758 EXPECT_THAT(callback.GetResult(rv), IsOk());
5759 response = trans->GetResponseInfo();
5760 ASSERT_TRUE(response);
5761 ASSERT_TRUE(response->headers);
5762
5763 // The following three tests assert that an authentication challenge was
5764 // received and that the stack needs explicit credentials before it is ready
5765 // to respond to the challenge.
5766 EXPECT_EQ(401, response->headers->response_code());
5767 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:585768 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:165769
5770 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5771 EXPECT_THAT(callback.GetResult(rv), IsOk());
5772 response = trans->GetResponseInfo();
5773 ASSERT_TRUE(response);
5774 ASSERT_TRUE(response->headers);
5775 EXPECT_EQ(200, response->headers->response_code());
5776
5777 trans.reset();
Matt Menke433de6d2020-03-04 00:24:115778 session->CloseAllConnections(ERR_FAILED, "Very good reason");
asankae2257db2016-10-11 22:03:165779}
5780
Matt Menked1eb6d42018-01-17 04:54:065781// Proxy resolver that returns a proxy with the same host and port for different
5782// schemes, based on the path of the URL being requests.
5783class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
5784 public:
5785 SameProxyWithDifferentSchemesProxyResolver() {}
5786 ~SameProxyWithDifferentSchemesProxyResolver() override {}
5787
Titouan Rigoudyba507a882020-07-31 12:15:155788 static constexpr uint16_t kProxyPort = 10000;
Matt Menked1eb6d42018-01-17 04:54:065789
5790 static HostPortPair ProxyHostPortPair() {
Titouan Rigoudyba507a882020-07-31 12:15:155791 return HostPortPair("proxy.test", kProxyPort);
5792 }
5793
5794 static std::string ProxyHostPortPairAsString() {
5795 return ProxyHostPortPair().ToString();
Matt Menked1eb6d42018-01-17 04:54:065796 }
5797
5798 // ProxyResolver implementation.
5799 int GetProxyForURL(const GURL& url,
Matt Menkecd522ee02019-11-13 19:53:395800 const NetworkIsolationKey& network_isolation_key,
Matt Menked1eb6d42018-01-17 04:54:065801 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:175802 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:065803 std::unique_ptr<Request>* request,
5804 const NetLogWithSource& /*net_log*/) override {
5805 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:575806 results->set_traffic_annotation(
5807 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:065808 if (url.path() == "/socks4") {
5809 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
5810 return OK;
5811 }
5812 if (url.path() == "/socks5") {
5813 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
5814 return OK;
5815 }
5816 if (url.path() == "/http") {
5817 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
5818 return OK;
5819 }
5820 if (url.path() == "/https") {
5821 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
5822 return OK;
5823 }
Matt Menkee8648fa2019-01-17 16:47:075824 if (url.path() == "/https_trusted") {
5825 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
5826 ProxyHostPortPair(),
5827 true /* is_trusted_proxy */));
5828 return OK;
5829 }
Matt Menked1eb6d42018-01-17 04:54:065830 NOTREACHED();
5831 return ERR_NOT_IMPLEMENTED;
5832 }
5833
5834 private:
5835 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
5836};
5837
5838class SameProxyWithDifferentSchemesProxyResolverFactory
5839 : public ProxyResolverFactory {
5840 public:
5841 SameProxyWithDifferentSchemesProxyResolverFactory()
5842 : ProxyResolverFactory(false) {}
5843
Lily Houghton99597862018-03-07 16:40:425844 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
5845 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:175846 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:425847 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:065848 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
5849 return OK;
5850 }
5851
5852 private:
5853 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
5854};
5855
5856// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:075857// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:065858// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
5859// request to foo.com using proxy.com as an HTTP proxy.
5860TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:495861 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:565862 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:495863 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5864 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
5865 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
Eric Roman3be01ba2020-04-03 21:37:095866 nullptr, /*quick_check_enabled=*/true);
Matt Menked1eb6d42018-01-17 04:54:065867
5868 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5869
5870 MockWrite socks_writes[] = {
5871 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
5872 kSOCKS4OkRequestLocalHostPort80Length),
5873 MockWrite(SYNCHRONOUS,
5874 "GET /socks4 HTTP/1.1\r\n"
5875 "Host: test\r\n"
5876 "Connection: keep-alive\r\n\r\n"),
5877 };
5878 MockRead socks_reads[] = {
5879 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
5880 MockRead("HTTP/1.0 200 OK\r\n"
5881 "Connection: keep-alive\r\n"
5882 "Content-Length: 15\r\n\r\n"
5883 "SOCKS4 Response"),
5884 };
Ryan Sleevib8d7ea02018-05-07 20:01:015885 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065886 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5887
5888 const char kSOCKS5Request[] = {
5889 0x05, // Version
5890 0x01, // Command (CONNECT)
5891 0x00, // Reserved
5892 0x03, // Address type (DOMAINNAME)
5893 0x04, // Length of domain (4)
5894 't', 'e', 's', 't', // Domain string
5895 0x00, 0x50, // 16-bit port (80)
5896 };
5897 MockWrite socks5_writes[] = {
5898 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245899 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065900 MockWrite(SYNCHRONOUS,
5901 "GET /socks5 HTTP/1.1\r\n"
5902 "Host: test\r\n"
5903 "Connection: keep-alive\r\n\r\n"),
5904 };
5905 MockRead socks5_reads[] = {
5906 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5907 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5908 MockRead("HTTP/1.0 200 OK\r\n"
5909 "Connection: keep-alive\r\n"
5910 "Content-Length: 15\r\n\r\n"
5911 "SOCKS5 Response"),
5912 };
Ryan Sleevib8d7ea02018-05-07 20:01:015913 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065914 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5915
5916 MockWrite http_writes[] = {
5917 MockWrite(SYNCHRONOUS,
5918 "GET http://test/http HTTP/1.1\r\n"
5919 "Host: test\r\n"
5920 "Proxy-Connection: keep-alive\r\n\r\n"),
5921 };
5922 MockRead http_reads[] = {
5923 MockRead("HTTP/1.1 200 OK\r\n"
5924 "Proxy-Connection: keep-alive\r\n"
5925 "Content-Length: 13\r\n\r\n"
5926 "HTTP Response"),
5927 };
Ryan Sleevib8d7ea02018-05-07 20:01:015928 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065929 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5930
5931 MockWrite https_writes[] = {
5932 MockWrite(SYNCHRONOUS,
5933 "GET http://test/https HTTP/1.1\r\n"
5934 "Host: test\r\n"
5935 "Proxy-Connection: keep-alive\r\n\r\n"),
5936 };
5937 MockRead https_reads[] = {
5938 MockRead("HTTP/1.1 200 OK\r\n"
5939 "Proxy-Connection: keep-alive\r\n"
5940 "Content-Length: 14\r\n\r\n"
5941 "HTTPS Response"),
5942 };
Ryan Sleevib8d7ea02018-05-07 20:01:015943 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065944 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5945 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5946 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5947
Matt Menkee8648fa2019-01-17 16:47:075948 MockWrite https_trusted_writes[] = {
5949 MockWrite(SYNCHRONOUS,
5950 "GET http://test/https_trusted HTTP/1.1\r\n"
5951 "Host: test\r\n"
5952 "Proxy-Connection: keep-alive\r\n\r\n"),
5953 };
5954 MockRead https_trusted_reads[] = {
5955 MockRead("HTTP/1.1 200 OK\r\n"
5956 "Proxy-Connection: keep-alive\r\n"
5957 "Content-Length: 22\r\n\r\n"
5958 "HTTPS Trusted Response"),
5959 };
5960 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5961 https_trusted_writes);
5962 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5963 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5964 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5965
Matt Menked1eb6d42018-01-17 04:54:065966 struct TestCase {
5967 GURL url;
5968 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075969 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065970 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075971 int expected_idle_socks4_sockets;
5972 int expected_idle_socks5_sockets;
5973 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5974 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065975 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075976 int expected_idle_https_sockets;
5977 // How many idle sockets there should be in the HTTPS proxy socket pool with
5978 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5979 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065980 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075981 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5982 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5983 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5984 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5985 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5986 1},
Matt Menked1eb6d42018-01-17 04:54:065987 };
5988
5989 for (const auto& test_case : kTestCases) {
Titouan Rigoudyba507a882020-07-31 12:15:155990 SCOPED_TRACE(test_case.url);
5991
Matt Menked1eb6d42018-01-17 04:54:065992 HttpRequestInfo request;
5993 request.method = "GET";
5994 request.url = test_case.url;
Ramin Halavatib5e433e62018-02-07 07:41:105995 request.traffic_annotation =
5996 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Titouan Rigoudyba507a882020-07-31 12:15:155997 ConnectedHandler connected_handler;
5998
5999 auto transaction = std::make_unique<HttpNetworkTransaction>(
6000 DEFAULT_PRIORITY, session.get());
6001
6002 transaction->SetConnectedCallback(connected_handler.Callback());
6003
Matt Menked1eb6d42018-01-17 04:54:066004 TestCompletionCallback callback;
Titouan Rigoudyba507a882020-07-31 12:15:156005 int rv =
6006 transaction->Start(&request, callback.callback(), NetLogWithSource());
Matt Menked1eb6d42018-01-17 04:54:066007 EXPECT_THAT(callback.GetResult(rv), IsOk());
6008
Titouan Rigoudyba507a882020-07-31 12:15:156009 const HttpResponseInfo* response = transaction->GetResponseInfo();
Matt Menked1eb6d42018-01-17 04:54:066010 ASSERT_TRUE(response);
6011 ASSERT_TRUE(response->headers);
6012 EXPECT_EQ(200, response->headers->response_code());
6013 std::string response_data;
Titouan Rigoudyba507a882020-07-31 12:15:156014 EXPECT_THAT(ReadTransaction(transaction.get(), &response_data), IsOk());
Matt Menked1eb6d42018-01-17 04:54:066015 EXPECT_EQ(test_case.expected_response, response_data);
6016
Titouan Rigoudyba507a882020-07-31 12:15:156017 TransportInfo expected_transport;
6018 expected_transport.type = TransportType::kProxied;
6019 expected_transport.endpoint =
6020 IPEndPoint(IPAddress::IPv4Localhost(),
6021 SameProxyWithDifferentSchemesProxyResolver::kProxyPort);
6022 EXPECT_THAT(connected_handler.transports(),
6023 ElementsAre(expected_transport));
6024
Matt Menked1eb6d42018-01-17 04:54:066025 // Return the socket to the socket pool, so can make sure it's not used for
6026 // the next requests.
Titouan Rigoudyba507a882020-07-31 12:15:156027 transaction.reset();
Matt Menked1eb6d42018-01-17 04:54:066028 base::RunLoop().RunUntilIdle();
6029
6030 // Check the number of idle sockets in the pool, to make sure that used
6031 // sockets are indeed being returned to the socket pool. If each request
6032 // doesn't return an idle socket to the pool, the test would incorrectly
6033 // pass.
Matt Menkee8648fa2019-01-17 16:47:076034 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
6035 session
Matt Menked23ab952019-03-06 00:24:406036 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076037 HttpNetworkSession::NORMAL_SOCKET_POOL,
6038 ProxyServer(ProxyServer::SCHEME_SOCKS4,
6039 SameProxyWithDifferentSchemesProxyResolver::
6040 ProxyHostPortPair()))
6041 ->IdleSocketCount());
6042 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
6043 session
Matt Menked23ab952019-03-06 00:24:406044 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076045 HttpNetworkSession::NORMAL_SOCKET_POOL,
6046 ProxyServer(ProxyServer::SCHEME_SOCKS5,
6047 SameProxyWithDifferentSchemesProxyResolver::
6048 ProxyHostPortPair()))
6049 ->IdleSocketCount());
6050 EXPECT_EQ(test_case.expected_idle_http_sockets,
6051 session
Matt Menked23ab952019-03-06 00:24:406052 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076053 HttpNetworkSession::NORMAL_SOCKET_POOL,
6054 ProxyServer(ProxyServer::SCHEME_HTTP,
6055 SameProxyWithDifferentSchemesProxyResolver::
6056 ProxyHostPortPair()))
6057 ->IdleSocketCount());
6058 EXPECT_EQ(test_case.expected_idle_https_sockets,
6059 session
Matt Menked23ab952019-03-06 00:24:406060 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076061 HttpNetworkSession::NORMAL_SOCKET_POOL,
6062 ProxyServer(ProxyServer::SCHEME_HTTPS,
6063 SameProxyWithDifferentSchemesProxyResolver::
6064 ProxyHostPortPair()))
6065 ->IdleSocketCount());
6066 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
6067 session
Matt Menked23ab952019-03-06 00:24:406068 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:076069 HttpNetworkSession::NORMAL_SOCKET_POOL,
6070 ProxyServer(ProxyServer::SCHEME_HTTPS,
6071 SameProxyWithDifferentSchemesProxyResolver::
6072 ProxyHostPortPair(),
6073 true /* is_trusted_proxy */))
6074 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:066075 }
6076}
6077
[email protected]029c83b62013-01-24 05:28:206078// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:016079TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:206080 HttpRequestInfo request1;
6081 request1.method = "GET";
bncce36dca22015-04-21 22:11:236082 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:106083 request1.traffic_annotation =
6084 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:206085
6086 HttpRequestInfo request2;
6087 request2.method = "GET";
bncce36dca22015-04-21 22:11:236088 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:106089 request2.traffic_annotation =
6090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:206091
6092 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566093 session_deps_.proxy_resolution_service =
6094 ConfiguredProxyResolutionService::CreateFixed(
6095 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146096 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076097 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096098 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:206099
6100 // Since we have proxy, should try to establish tunnel.
6101 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:176102 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6103 "Host: www.example.org:443\r\n"
6104 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206105
rsleevidb16bb02015-11-12 23:47:176106 MockWrite("GET /1 HTTP/1.1\r\n"
6107 "Host: www.example.org\r\n"
6108 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206109
rsleevidb16bb02015-11-12 23:47:176110 MockWrite("GET /2 HTTP/1.1\r\n"
6111 "Host: www.example.org\r\n"
6112 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206113 };
6114
6115 // The proxy responds to the connect with a 407, using a persistent
6116 // connection.
6117 MockRead data_reads1[] = {
6118 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6119
6120 MockRead("HTTP/1.1 200 OK\r\n"),
6121 MockRead("Content-Length: 1\r\n\r\n"),
6122 MockRead(SYNCHRONOUS, "1"),
6123
6124 MockRead("HTTP/1.1 200 OK\r\n"),
6125 MockRead("Content-Length: 2\r\n\r\n"),
6126 MockRead(SYNCHRONOUS, "22"),
6127 };
6128
Ryan Sleevib8d7ea02018-05-07 20:01:016129 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076130 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:206131 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076132 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:206133
6134 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:586135 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:196136 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206137
6138 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016139 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206140
6141 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016142 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206143
6144 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:526145 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:476146 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:526147 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:206148 EXPECT_EQ(1, response1->headers->GetContentLength());
6149
6150 LoadTimingInfo load_timing_info1;
6151 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
6152 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
6153
6154 trans1.reset();
6155
6156 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:586157 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196158 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206159
6160 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016161 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206162
6163 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016164 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206165
6166 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:526167 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:476168 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:526169 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:206170 EXPECT_EQ(2, response2->headers->GetContentLength());
6171
6172 LoadTimingInfo load_timing_info2;
6173 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6174 TestLoadTimingReused(load_timing_info2);
6175
6176 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
6177
6178 trans2.reset();
Matt Menke433de6d2020-03-04 00:24:116179 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]029c83b62013-01-24 05:28:206180}
6181
6182// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:016183TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:206184 HttpRequestInfo request1;
6185 request1.method = "GET";
bncce36dca22015-04-21 22:11:236186 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:106187 request1.traffic_annotation =
6188 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:206189
6190 HttpRequestInfo request2;
6191 request2.method = "GET";
bncce36dca22015-04-21 22:11:236192 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:106193 request2.traffic_annotation =
6194 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:206195
6196 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:596197 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566198 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:496199 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146200 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076201 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096202 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:206203
6204 // Since we have proxy, should try to establish tunnel.
6205 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:176206 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6207 "Host: www.example.org:443\r\n"
6208 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206209
rsleevidb16bb02015-11-12 23:47:176210 MockWrite("GET /1 HTTP/1.1\r\n"
6211 "Host: www.example.org\r\n"
6212 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206213
rsleevidb16bb02015-11-12 23:47:176214 MockWrite("GET /2 HTTP/1.1\r\n"
6215 "Host: www.example.org\r\n"
6216 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:206217 };
6218
6219 // The proxy responds to the connect with a 407, using a persistent
6220 // connection.
6221 MockRead data_reads1[] = {
6222 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6223
6224 MockRead("HTTP/1.1 200 OK\r\n"),
6225 MockRead("Content-Length: 1\r\n\r\n"),
6226 MockRead(SYNCHRONOUS, "1"),
6227
6228 MockRead("HTTP/1.1 200 OK\r\n"),
6229 MockRead("Content-Length: 2\r\n\r\n"),
6230 MockRead(SYNCHRONOUS, "22"),
6231 };
6232
Ryan Sleevib8d7ea02018-05-07 20:01:016233 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076234 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:206235 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076236 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:206237
6238 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:586239 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:196240 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206241
6242 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016243 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206244
6245 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016246 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206247
6248 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:526249 ASSERT_TRUE(response1);
6250 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:206251 EXPECT_EQ(1, response1->headers->GetContentLength());
6252
6253 LoadTimingInfo load_timing_info1;
6254 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
6255 TestLoadTimingNotReusedWithPac(load_timing_info1,
6256 CONNECT_TIMING_HAS_SSL_TIMES);
6257
6258 trans1.reset();
6259
6260 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:586261 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196262 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:206263
6264 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016265 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:206266
6267 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016268 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:206269
6270 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:526271 ASSERT_TRUE(response2);
6272 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:206273 EXPECT_EQ(2, response2->headers->GetContentLength());
6274
6275 LoadTimingInfo load_timing_info2;
6276 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6277 TestLoadTimingReusedWithPac(load_timing_info2);
6278
6279 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
6280
6281 trans2.reset();
Matt Menke433de6d2020-03-04 00:24:116282 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]029c83b62013-01-24 05:28:206283}
6284
Matt Menke8045afd2019-11-14 20:31:196285// Make sure that NetworkIsolationKeys are passed down to the proxy layer.
6286TEST_F(HttpNetworkTransactionTest, ProxyResolvedWithNetworkIsolationKey) {
6287 const url::Origin kOrigin = url::Origin::Create(GURL("https://foo.test/"));
6288 const net::NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin);
6289
6290 ProxyConfig proxy_config;
6291 proxy_config.set_auto_detect(true);
6292 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6293
6294 CapturingProxyResolver capturing_proxy_resolver;
6295 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6296 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566297 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke8045afd2019-11-14 20:31:196298 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6299 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6300 std::make_unique<CapturingProxyResolverFactory>(
6301 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:096302 nullptr, /*quick_check_enabled=*/true);
Matt Menke8045afd2019-11-14 20:31:196303
6304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6305
6306 // No need to continue with the network request - proxy resolution occurs
6307 // before establishing a data.
6308 StaticSocketDataProvider data{base::span<MockRead>(),
6309 base::span<MockWrite>()};
6310 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
6311 session_deps_.socket_factory->AddSocketDataProvider(&data);
6312
6313 // Run first request until an auth challenge is observed.
6314 HttpRequestInfo request;
6315 request.method = "GET";
6316 request.url = GURL("http://foo.test/");
6317 request.traffic_annotation =
6318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6319 HttpNetworkTransaction trans(LOWEST, session.get());
6320 TestCompletionCallback callback;
6321 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6322 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
6323}
6324
dalyk6d7a8c52019-12-18 21:43:016325// Test that a failure in resolving the proxy hostname is retrievable.
6326TEST_F(HttpNetworkTransactionTest, ProxyHostResolutionFailure) {
6327 HttpRequestInfo request;
6328 request.method = "GET";
6329 request.url = GURL("http://www.example.org/");
6330 request.traffic_annotation =
6331 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6332
6333 RecordingTestNetLog log;
6334 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566335 session_deps_.proxy_resolution_service =
6336 ConfiguredProxyResolutionService::CreateFixed(
6337 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
dalyk6d7a8c52019-12-18 21:43:016338 MockHostResolver* resolver = new MockHostResolver();
6339 resolver->rules()->AddSimulatedTimeoutFailure("proxy");
6340 session_deps_.net_log = &log;
6341 session_deps_.host_resolver.reset(resolver);
6342 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
6343 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6344 TestCompletionCallback callback;
6345
6346 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6347 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6348 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_PROXY_CONNECTION_FAILED));
6349
6350 const HttpResponseInfo* response = trans.GetResponseInfo();
6351 ASSERT_TRUE(response);
6352 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
6353}
6354
[email protected]2df19bb2010-08-25 20:13:466355// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016356TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276357 HttpRequestInfo request;
6358 request.method = "GET";
bncce36dca22015-04-21 22:11:236359 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106360 request.traffic_annotation =
6361 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276362
[email protected]2df19bb2010-08-25 20:13:466363 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566364 session_deps_.proxy_resolution_service =
6365 ConfiguredProxyResolutionService::CreateFixed(
6366 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146367 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076368 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096369 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:466370
[email protected]2df19bb2010-08-25 20:13:466371 // Since we have proxy, should use full url
6372 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236373 MockWrite(
6374 "GET http://www.example.org/ HTTP/1.1\r\n"
6375 "Host: www.example.org\r\n"
6376 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466377 };
6378
6379 MockRead data_reads1[] = {
6380 MockRead("HTTP/1.1 200 OK\r\n"),
6381 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6382 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066383 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466384 };
6385
Ryan Sleevib8d7ea02018-05-07 20:01:016386 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076387 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066388 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076389 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466390
Titouan Rigoudyba507a882020-07-31 12:15:156391 ConnectedHandler connected_handler;
[email protected]49639fa2011-12-20 23:22:416392 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466393
bnc691fda62016-08-12 00:43:166394 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506395
Titouan Rigoudyba507a882020-07-31 12:15:156396 trans.SetConnectedCallback(connected_handler.Callback());
6397
bnc691fda62016-08-12 00:43:166398 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016399 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466400
6401 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016402 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466403
[email protected]58e32bb2013-01-21 18:23:256404 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166405 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256406 TestLoadTimingNotReused(load_timing_info,
6407 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6408
bnc691fda62016-08-12 00:43:166409 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526410 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466411
tbansal2ecbbc72016-10-06 17:15:476412 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:466413 EXPECT_TRUE(response->headers->IsKeepAlive());
6414 EXPECT_EQ(200, response->headers->response_code());
6415 EXPECT_EQ(100, response->headers->GetContentLength());
6416 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6417
Titouan Rigoudyba507a882020-07-31 12:15:156418 TransportInfo expected_transport;
6419 expected_transport.type = TransportType::kProxied;
6420 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
6421 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
6422
[email protected]2df19bb2010-08-25 20:13:466423 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586424 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466425}
6426
[email protected]7642b5ae2010-09-01 20:55:176427// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016428TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:276429 HttpRequestInfo request;
6430 request.method = "GET";
bncce36dca22015-04-21 22:11:236431 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106432 request.traffic_annotation =
6433 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276434
[email protected]7642b5ae2010-09-01 20:55:176435 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566436 session_deps_.proxy_resolution_service =
6437 ConfiguredProxyResolutionService::CreateFixed(
6438 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146439 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076440 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096441 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:176442
bncce36dca22015-04-21 22:11:236443 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136444 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456445 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416446 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:176447
Ryan Hamilton0239aac2018-05-19 00:03:136448 spdy::SpdySerializedFrame resp(
6449 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6450 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:176451 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416452 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:176453 };
6454
Ryan Sleevib8d7ea02018-05-07 20:01:016455 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076456 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:176457
[email protected]8ddf8322012-02-23 18:08:066458 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366459 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076460 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:176461
Titouan Rigoudyba507a882020-07-31 12:15:156462 ConnectedHandler connected_handler;
[email protected]49639fa2011-12-20 23:22:416463 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:176464
bnc691fda62016-08-12 00:43:166465 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506466
Titouan Rigoudyba507a882020-07-31 12:15:156467 trans.SetConnectedCallback(connected_handler.Callback());
6468
bnc691fda62016-08-12 00:43:166469 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016470 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:176471
6472 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016473 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:176474
[email protected]58e32bb2013-01-21 18:23:256475 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166476 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256477 TestLoadTimingNotReused(load_timing_info,
6478 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6479
bnc691fda62016-08-12 00:43:166480 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526481 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:476482 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:526483 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026484 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:176485
Titouan Rigoudyba507a882020-07-31 12:15:156486 TransportInfo expected_transport;
6487 expected_transport.type = TransportType::kProxied;
6488 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
6489 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
6490
[email protected]7642b5ae2010-09-01 20:55:176491 std::string response_data;
bnc691fda62016-08-12 00:43:166492 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236493 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:176494}
6495
[email protected]1c173852014-06-19 12:51:506496// Verifies that a session which races and wins against the owning transaction
6497// (completing prior to host resolution), doesn't fail the transaction.
6498// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:016499TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:506500 HttpRequestInfo request;
6501 request.method = "GET";
bncce36dca22015-04-21 22:11:236502 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106503 request.traffic_annotation =
6504 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:506505
6506 // Configure SPDY proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566507 session_deps_.proxy_resolution_service =
6508 ConfiguredProxyResolutionService::CreateFixed(
6509 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146510 RecordingBoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:506511 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096512 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:506513
bncce36dca22015-04-21 22:11:236514 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:136515 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:456516 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:416517 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:506518
Raul Tambre94493c652019-03-11 17:18:356519 spdy::SpdySerializedFrame resp(
6520 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136521 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:506522 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416523 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:506524 };
6525
Ryan Sleevib8d7ea02018-05-07 20:01:016526 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:506527 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6528
6529 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366530 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:506531 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6532
6533 TestCompletionCallback callback1;
6534
bnc691fda62016-08-12 00:43:166535 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:506536
6537 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:506538 session_deps_.host_resolver->set_ondemand_mode(true);
6539
bnc691fda62016-08-12 00:43:166540 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016541 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:506542
6543 // Race a session to the proxy, which completes first.
6544 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:046545 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:116546 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:346547 SpdySessionKey::IsProxySession::kTrue, SocketTag(),
6548 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]1c173852014-06-19 12:51:506549 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:526550 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:506551
6552 // Unstall the resolution begun by the transaction.
6553 session_deps_.host_resolver->set_ondemand_mode(true);
6554 session_deps_.host_resolver->ResolveAllPending();
6555
6556 EXPECT_FALSE(callback1.have_result());
6557 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016558 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:506559
bnc691fda62016-08-12 00:43:166560 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526561 ASSERT_TRUE(response);
6562 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026563 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:506564
6565 std::string response_data;
bnc691fda62016-08-12 00:43:166566 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:506567 EXPECT_EQ(kUploadData, response_data);
6568}
6569
[email protected]dc7bd1c52010-11-12 00:01:136570// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016571TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:276572 HttpRequestInfo request;
6573 request.method = "GET";
bncce36dca22015-04-21 22:11:236574 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106575 request.traffic_annotation =
6576 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276577
[email protected]79cb5c12011-09-12 13:12:046578 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566579 session_deps_.proxy_resolution_service =
6580 ConfiguredProxyResolutionService::CreateFixed(
6581 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146582 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076583 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096584 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:136585
[email protected]dc7bd1c52010-11-12 00:01:136586 // The first request will be a bare GET, the second request will be a
6587 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:456588 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:136589 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:486590 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:386591 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:136592 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466593 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:136594 };
Ryan Hamilton0239aac2018-05-19 00:03:136595 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:246596 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:486597 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:136598 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416599 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:136600 };
6601
6602 // The first response is a 407 proxy authentication challenge, and the second
6603 // response will be a 200 response since the second request includes a valid
6604 // Authorization header.
6605 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:466606 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:136607 };
Ryan Hamilton0239aac2018-05-19 00:03:136608 spdy::SpdySerializedFrame resp_authentication(
6609 spdy_util_.ConstructSpdyReplyError(
6610 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:246611 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136612 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:416613 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:136614 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:356615 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136616 spdy::SpdySerializedFrame body_data(
6617 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:136618 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416619 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:466620 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416621 CreateMockRead(resp_data, 4),
6622 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:136623 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:136624 };
6625
Ryan Sleevib8d7ea02018-05-07 20:01:016626 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076627 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:136628
[email protected]8ddf8322012-02-23 18:08:066629 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366630 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076631 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:136632
[email protected]49639fa2011-12-20 23:22:416633 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:136634
bnc691fda62016-08-12 00:43:166635 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:136636
bnc691fda62016-08-12 00:43:166637 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016638 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136639
6640 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016641 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136642
bnc691fda62016-08-12 00:43:166643 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136644
wezca1070932016-05-26 20:30:526645 ASSERT_TRUE(response);
6646 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:136647 EXPECT_EQ(407, response->headers->response_code());
6648 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:586649 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:136650
[email protected]49639fa2011-12-20 23:22:416651 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:136652
bnc691fda62016-08-12 00:43:166653 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016654 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:136655
6656 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016657 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:136658
bnc691fda62016-08-12 00:43:166659 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:136660
wezca1070932016-05-26 20:30:526661 ASSERT_TRUE(response_restart);
6662 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:136663 EXPECT_EQ(200, response_restart->headers->response_code());
6664 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586665 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:136666}
6667
[email protected]d9da5fe2010-10-13 22:37:166668// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:016669TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:276670 HttpRequestInfo request;
6671 request.method = "GET";
bncce36dca22015-04-21 22:11:236672 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106673 request.traffic_annotation =
6674 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276675
[email protected]d9da5fe2010-10-13 22:37:166676 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566677 session_deps_.proxy_resolution_service =
6678 ConfiguredProxyResolutionService::CreateFixed(
6679 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146680 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076681 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096682 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166683
bnc691fda62016-08-12 00:43:166684 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166685
bncce36dca22015-04-21 22:11:236686 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136687 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046688 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6689 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236690 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:166691
bncce36dca22015-04-21 22:11:236692 const char get[] =
6693 "GET / HTTP/1.1\r\n"
6694 "Host: www.example.org\r\n"
6695 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136696 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:196697 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:136698 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356699 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:166700 const char resp[] = "HTTP/1.1 200 OK\r\n"
6701 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136702 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:196703 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:136704 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:196705 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:136706 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416707 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:046708
6709 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416710 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6711 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:046712 };
6713
[email protected]d9da5fe2010-10-13 22:37:166714 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416715 CreateMockRead(conn_resp, 1, ASYNC),
6716 CreateMockRead(wrapped_get_resp, 3, ASYNC),
6717 CreateMockRead(wrapped_body, 4, ASYNC),
6718 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136719 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:166720 };
6721
Ryan Sleevib8d7ea02018-05-07 20:01:016722 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076723 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166724
[email protected]8ddf8322012-02-23 18:08:066725 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366726 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066728 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076729 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166730
[email protected]49639fa2011-12-20 23:22:416731 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166732
bnc691fda62016-08-12 00:43:166733 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016734 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166735
6736 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016737 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166738
[email protected]58e32bb2013-01-21 18:23:256739 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166740 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256741 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6742
bnc691fda62016-08-12 00:43:166743 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526744 ASSERT_TRUE(response);
6745 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:166746 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6747
6748 std::string response_data;
bnc691fda62016-08-12 00:43:166749 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:166750 EXPECT_EQ("1234567890", response_data);
6751}
6752
6753// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:016754TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
6755 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:386756
[email protected]cb9bf6ca2011-01-28 13:15:276757 HttpRequestInfo request;
6758 request.method = "GET";
bncce36dca22015-04-21 22:11:236759 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106760 request.traffic_annotation =
6761 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276762
[email protected]d9da5fe2010-10-13 22:37:166763 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566764 session_deps_.proxy_resolution_service =
6765 ConfiguredProxyResolutionService::CreateFixed(
6766 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146767 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076768 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096769 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166770
bnc691fda62016-08-12 00:43:166771 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166772
bncce36dca22015-04-21 22:11:236773 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136774 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046775 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6776 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:236777 // fetch https://www.example.org/ via SPDY
6778 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:136779 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:496780 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:136781 spdy::SpdySerializedFrame wrapped_get(
6782 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6783 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356784 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136785 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356786 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136787 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:026788 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136789 spdy::SpdySerializedFrame body(
6790 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
6791 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:026792 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136793 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:416794 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:136795 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:416796 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:046797
6798 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416799 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
6800 CreateMockWrite(window_update_get_resp, 6),
6801 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:046802 };
6803
[email protected]d9da5fe2010-10-13 22:37:166804 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416805 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:096806 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:416807 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6808 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:136809 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:166810 };
6811
Ryan Sleevib8d7ea02018-05-07 20:01:016812 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076813 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166814
[email protected]8ddf8322012-02-23 18:08:066815 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366816 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076817 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066818 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366819 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076820 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166821
[email protected]49639fa2011-12-20 23:22:416822 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166823
bnc691fda62016-08-12 00:43:166824 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016825 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166826
rch32320842015-05-16 15:57:096827 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:556828 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:096829 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:596830 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:166831 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016832 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:166833
[email protected]58e32bb2013-01-21 18:23:256834 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166835 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256836 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6837
bnc691fda62016-08-12 00:43:166838 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526839 ASSERT_TRUE(response);
6840 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026841 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:166842
6843 std::string response_data;
bnc691fda62016-08-12 00:43:166844 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:236845 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:166846}
6847
6848// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:016849TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:276850 HttpRequestInfo request;
6851 request.method = "GET";
bncce36dca22015-04-21 22:11:236852 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106853 request.traffic_annotation =
6854 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276855
[email protected]d9da5fe2010-10-13 22:37:166856 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:566857 session_deps_.proxy_resolution_service =
6858 ConfiguredProxyResolutionService::CreateFixed(
6859 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:146860 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076861 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096862 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:166863
bnc691fda62016-08-12 00:43:166864 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:166865
bncce36dca22015-04-21 22:11:236866 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:136867 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046868 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6869 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136870 spdy::SpdySerializedFrame get(
6871 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:166872
6873 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416874 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:166875 };
6876
Ryan Hamilton0239aac2018-05-19 00:03:136877 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
6878 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:166879 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416880 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:166881 };
6882
Ryan Sleevib8d7ea02018-05-07 20:01:016883 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:076884 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:166885
[email protected]8ddf8322012-02-23 18:08:066886 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366887 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076888 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:066889 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366890 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:076891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:166892
[email protected]49639fa2011-12-20 23:22:416893 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:166894
bnc691fda62016-08-12 00:43:166895 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016896 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:166897
6898 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016899 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:166900
ttuttle960fcbf2016-04-19 13:26:326901 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:166902}
6903
Matt Menkecb2cd0982018-12-19 17:54:046904// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:246905// is observed, but does exist by the time auth credentials are provided. In
6906// this case, auth and SSL are fully negotated on the second request, but then
6907// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:046908TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
6909 ProxyConfig proxy_config;
6910 proxy_config.set_auto_detect(true);
6911 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6912
6913 CapturingProxyResolver capturing_proxy_resolver;
6914 capturing_proxy_resolver.set_proxy_server(
6915 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
6916 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:566917 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menkecb2cd0982018-12-19 17:54:046918 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6919 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6920 std::make_unique<CapturingProxyResolverFactory>(
6921 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:096922 nullptr, /*quick_check_enabled=*/true);
Matt Menkecb2cd0982018-12-19 17:54:046923
6924 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6925
6926 const char kMyUrl[] = "https://www.example.org/";
6927 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6928 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356929 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:046930 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
6931
6932 spdy_util_.UpdateWithStreamDestruction(1);
6933 spdy::SpdySerializedFrame get2(
6934 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
6935 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356936 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:046937 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
6938
6939 MockWrite auth_challenge_writes[] = {
6940 MockWrite(ASYNC, 0,
6941 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6942 "Host: www.example.org:443\r\n"
6943 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:246944 MockWrite(ASYNC, 2,
6945 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6946 "Host: www.example.org:443\r\n"
6947 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:046948 };
6949
6950 MockRead auth_challenge_reads[] = {
6951 MockRead(ASYNC, 1,
6952 "HTTP/1.1 407 Authentication Required\r\n"
6953 "Content-Length: 0\r\n"
6954 "Proxy-Connection: close\r\n"
6955 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
6956 };
6957
6958 MockWrite spdy_writes[] = {
6959 MockWrite(ASYNC, 0,
6960 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6961 "Host: www.example.org:443\r\n"
6962 "Proxy-Connection: keep-alive\r\n"
6963 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6964 CreateMockWrite(get, 2),
6965 CreateMockWrite(get2, 5),
6966 };
6967
6968 MockRead spdy_reads[] = {
6969 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6970 CreateMockRead(get_resp, 3, ASYNC),
6971 CreateMockRead(body, 4, ASYNC),
6972 CreateMockRead(get_resp2, 6, ASYNC),
6973 CreateMockRead(body2, 7, ASYNC),
6974
6975 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
6976 };
6977
Matt Menke5062be22019-05-01 17:50:246978 MockWrite auth_response_writes_discarded_socket[] = {
6979 MockWrite(ASYNC, 0,
6980 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6981 "Host: www.example.org:443\r\n"
6982 "Proxy-Connection: keep-alive\r\n"
6983 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6984 };
6985
6986 MockRead auth_response_reads_discarded_socket[] = {
6987 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
6988 };
6989
Matt Menkecb2cd0982018-12-19 17:54:046990 SequencedSocketData auth_challenge1(auth_challenge_reads,
6991 auth_challenge_writes);
6992 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
6993
6994 SequencedSocketData auth_challenge2(auth_challenge_reads,
6995 auth_challenge_writes);
6996 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
6997
6998 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6999 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7000
Matt Menke5062be22019-05-01 17:50:247001 SequencedSocketData auth_response_discarded_socket(
7002 auth_response_reads_discarded_socket,
7003 auth_response_writes_discarded_socket);
7004 session_deps_.socket_factory->AddSocketDataProvider(
7005 &auth_response_discarded_socket);
7006
Matt Menkecb2cd0982018-12-19 17:54:047007 SSLSocketDataProvider ssl(ASYNC, OK);
7008 ssl.next_proto = kProtoHTTP2;
7009 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7010
Matt Menke5062be22019-05-01 17:50:247011 SSLSocketDataProvider ssl2(ASYNC, OK);
7012 ssl2.next_proto = kProtoHTTP2;
7013 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7014
Matt Menkecb2cd0982018-12-19 17:54:047015 TestCompletionCallback callback;
7016 std::string response_data;
7017
7018 // Run first request until an auth challenge is observed.
7019 HttpRequestInfo request1;
7020 request1.method = "GET";
7021 request1.url = GURL(kMyUrl);
7022 request1.traffic_annotation =
7023 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7024 HttpNetworkTransaction trans1(LOWEST, session.get());
7025 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
7026 EXPECT_THAT(callback.GetResult(rv), IsOk());
7027 const HttpResponseInfo* response = trans1.GetResponseInfo();
7028 ASSERT_TRUE(response);
7029 ASSERT_TRUE(response->headers);
7030 EXPECT_EQ(407, response->headers->response_code());
7031 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587032 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:047033
7034 // Run second request until an auth challenge is observed.
7035 HttpRequestInfo request2;
7036 request2.method = "GET";
7037 request2.url = GURL(kMyUrl);
7038 request2.traffic_annotation =
7039 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7040 HttpNetworkTransaction trans2(LOWEST, session.get());
7041 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
7042 EXPECT_THAT(callback.GetResult(rv), IsOk());
7043 response = trans2.GetResponseInfo();
7044 ASSERT_TRUE(response);
7045 ASSERT_TRUE(response->headers);
7046 EXPECT_EQ(407, response->headers->response_code());
7047 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587048 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:047049
7050 // Now provide credentials for the first request, and wait for it to complete.
7051 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
7052 rv = callback.GetResult(rv);
7053 EXPECT_THAT(rv, IsOk());
7054 response = trans1.GetResponseInfo();
7055 ASSERT_TRUE(response);
7056 ASSERT_TRUE(response->headers);
7057 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7058 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7059 EXPECT_EQ(kUploadData, response_data);
7060
7061 // Now provide credentials for the second request. It should notice the
7062 // existing session, and reuse it.
7063 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
7064 EXPECT_THAT(callback.GetResult(rv), IsOk());
7065 response = trans2.GetResponseInfo();
7066 ASSERT_TRUE(response);
7067 ASSERT_TRUE(response->headers);
7068 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7069 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7070 EXPECT_EQ(kUploadData, response_data);
7071}
7072
[email protected]f6c63db52013-02-02 00:35:227073// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
7074// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:017075TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:227076 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
7077 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567078 session_deps_.proxy_resolution_service =
7079 ConfiguredProxyResolutionService::CreateFixed(
7080 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147081 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077082 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097083 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:507084 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:227085
7086 HttpRequestInfo request1;
7087 request1.method = "GET";
bncce36dca22015-04-21 22:11:237088 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:227089 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:107090 request1.traffic_annotation =
7091 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227092
7093 HttpRequestInfo request2;
7094 request2.method = "GET";
bncce36dca22015-04-21 22:11:237095 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:227096 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:107097 request2.traffic_annotation =
7098 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227099
bncce36dca22015-04-21 22:11:237100 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:137101 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047102 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7103 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:137104 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:357105 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:227106
bncce36dca22015-04-21 22:11:237107 // Fetch https://www.example.org/ via HTTP.
7108 const char get1[] =
7109 "GET / HTTP/1.1\r\n"
7110 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227111 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137112 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:197113 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:227114 const char resp1[] = "HTTP/1.1 200 OK\r\n"
7115 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137116 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:197117 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:137118 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:197119 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:137120 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:417121 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:227122
bncce36dca22015-04-21 22:11:237123 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:137124 spdy::SpdyHeaderBlock connect2_block;
7125 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
7126 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
7127 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:047128 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
7129 false));
[email protected]601e03f12014-04-06 16:26:397130
Ryan Hamilton0239aac2018-05-19 00:03:137131 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:357132 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:227133
bncce36dca22015-04-21 22:11:237134 // Fetch https://mail.example.org/ via HTTP.
7135 const char get2[] =
7136 "GET / HTTP/1.1\r\n"
7137 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227138 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137139 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:197140 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:227141 const char resp2[] = "HTTP/1.1 200 OK\r\n"
7142 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137143 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:197144 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:137145 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:197146 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:227147
7148 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417149 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
7150 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:227151 };
7152
7153 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417154 CreateMockRead(conn_resp1, 1, ASYNC),
7155 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
7156 CreateMockRead(wrapped_body1, 4, ASYNC),
7157 CreateMockRead(conn_resp2, 6, ASYNC),
7158 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
7159 CreateMockRead(wrapped_body2, 9, ASYNC),
7160 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:227161 };
7162
Ryan Sleevib8d7ea02018-05-07 20:01:017163 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507164 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227165
7166 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367167 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507168 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227169 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:507170 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:227171 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:507172 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:227173
7174 TestCompletionCallback callback;
7175
bnc691fda62016-08-12 00:43:167176 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207177 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017178 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227179
7180 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:167181 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:227182 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
7183
bnc691fda62016-08-12 00:43:167184 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527185 ASSERT_TRUE(response);
7186 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:227187 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7188
7189 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447190 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:167191 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507192 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227193
bnc691fda62016-08-12 00:43:167194 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207195 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017196 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227197
7198 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:167199 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:227200 // Even though the SPDY connection is reused, a new tunnelled connection has
7201 // to be created, so the socket's load timing looks like a fresh connection.
7202 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
7203
7204 // The requests should have different IDs, since they each are using their own
7205 // separate stream.
7206 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7207
bnc691fda62016-08-12 00:43:167208 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507209 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227210}
7211
7212// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
7213// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:017214TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:227215 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
7216 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567217 session_deps_.proxy_resolution_service =
7218 ConfiguredProxyResolutionService::CreateFixed(
7219 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147220 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077221 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097222 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:507223 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:227224
7225 HttpRequestInfo request1;
7226 request1.method = "GET";
bncce36dca22015-04-21 22:11:237227 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:227228 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:107229 request1.traffic_annotation =
7230 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227231
7232 HttpRequestInfo request2;
7233 request2.method = "GET";
bncce36dca22015-04-21 22:11:237234 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:227235 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:107236 request2.traffic_annotation =
7237 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227238
bncce36dca22015-04-21 22:11:237239 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:137240 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047241 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7242 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:137243 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:357244 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:227245
bncce36dca22015-04-21 22:11:237246 // Fetch https://www.example.org/ via HTTP.
7247 const char get1[] =
7248 "GET / HTTP/1.1\r\n"
7249 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227250 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137251 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:197252 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:227253 const char resp1[] = "HTTP/1.1 200 OK\r\n"
7254 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137255 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:197256 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:137257 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:197258 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:137259 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:417260 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:227261
bncce36dca22015-04-21 22:11:237262 // Fetch https://www.example.org/2 via HTTP.
7263 const char get2[] =
7264 "GET /2 HTTP/1.1\r\n"
7265 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:227266 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137267 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:197268 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:227269 const char resp2[] = "HTTP/1.1 200 OK\r\n"
7270 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:137271 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:197272 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:137273 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:197274 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:227275
7276 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417277 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
7278 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:227279 };
7280
7281 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417282 CreateMockRead(conn_resp1, 1, ASYNC),
7283 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:467284 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:417285 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:467286 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:417287 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:227288 };
7289
Ryan Sleevib8d7ea02018-05-07 20:01:017290 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507291 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227292
7293 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367294 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507295 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227296 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:507297 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:227298
7299 TestCompletionCallback callback;
7300
bnc87dcefc2017-05-25 12:47:587301 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197302 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207303 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017304 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:227305
7306 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017307 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:227308
7309 LoadTimingInfo load_timing_info;
7310 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7311 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
7312
7313 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527314 ASSERT_TRUE(response);
7315 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:227316 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7317
7318 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447319 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:507320 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:227321 trans.reset();
7322
bnc87dcefc2017-05-25 12:47:587323 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:197324 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207325 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017326 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:227327
[email protected]f6c63db52013-02-02 00:35:227328 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017329 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:227330
7331 LoadTimingInfo load_timing_info2;
7332 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
7333 TestLoadTimingReused(load_timing_info2);
7334
7335 // The requests should have the same ID.
7336 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7337
[email protected]90499482013-06-01 00:39:507338 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:227339}
7340
7341// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
7342// Proxy to different servers.
bncd16676a2016-07-20 16:23:017343TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:227344 // Configure against https proxy server "proxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567345 session_deps_.proxy_resolution_service =
7346 ConfiguredProxyResolutionService::CreateFixed(
7347 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147348 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077349 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097350 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:507351 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:227352
7353 HttpRequestInfo request1;
7354 request1.method = "GET";
bncce36dca22015-04-21 22:11:237355 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:227356 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:107357 request1.traffic_annotation =
7358 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227359
7360 HttpRequestInfo request2;
7361 request2.method = "GET";
bncce36dca22015-04-21 22:11:237362 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:227363 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:107364 request2.traffic_annotation =
7365 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:227366
bncce36dca22015-04-21 22:11:237367 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:137368 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:237369 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137370 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:157371 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137372 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:357373 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:137374 spdy::SpdySerializedFrame body1(
7375 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:387376 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:227377
bncce36dca22015-04-21 22:11:237378 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:137379 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:237380 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:137381 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:157382 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:137383 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:357384 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:137385 spdy::SpdySerializedFrame body2(
7386 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:227387
7388 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417389 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:227390 };
7391
7392 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417393 CreateMockRead(get_resp1, 1, ASYNC),
7394 CreateMockRead(body1, 2, ASYNC),
7395 CreateMockRead(get_resp2, 4, ASYNC),
7396 CreateMockRead(body2, 5, ASYNC),
7397 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:227398 };
7399
Ryan Sleevib8d7ea02018-05-07 20:01:017400 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:507401 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:227402
7403 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367404 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:507405 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:227406
7407 TestCompletionCallback callback;
7408
bnc87dcefc2017-05-25 12:47:587409 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197410 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207411 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017412 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227413
7414 LoadTimingInfo load_timing_info;
7415 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7416 TestLoadTimingNotReused(load_timing_info,
7417 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7418
7419 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527420 ASSERT_TRUE(response);
7421 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:027422 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:227423
7424 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:447425 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:507426 rv = trans->Read(buf.get(), 256, callback.callback());
7427 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227428 // Delete the first request, so the second one can reuse the socket.
7429 trans.reset();
7430
bnc691fda62016-08-12 00:43:167431 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:207432 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017433 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:227434
7435 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:167436 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:227437 TestLoadTimingReused(load_timing_info2);
7438
7439 // The requests should have the same ID.
7440 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
7441
bnc691fda62016-08-12 00:43:167442 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:507443 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:227444}
7445
Matt Menke2436b2f2018-12-11 18:07:117446// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
7447// direct (non-proxied) request to the proxy server are not pooled, as that
7448// would break socket pool isolation.
7449TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
7450 ProxyConfig proxy_config;
7451 proxy_config.set_auto_detect(true);
7452 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7453
7454 CapturingProxyResolver capturing_proxy_resolver;
7455 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:567456 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke2436b2f2018-12-11 18:07:117457 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7458 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7459 std::make_unique<CapturingProxyResolverFactory>(
7460 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:097461 nullptr, /*quick_check_enabled=*/true);
Matt Menke2436b2f2018-12-11 18:07:117462
7463 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7464
7465 SpdyTestUtil spdy_util1;
7466 // CONNECT to www.example.org:443 via HTTP/2.
7467 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047468 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7469 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117470 // fetch https://www.example.org/ via HTTP/2.
7471 const char kMyUrl[] = "https://www.example.org/";
7472 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7473 spdy::SpdySerializedFrame wrapped_get(
7474 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7475 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:357476 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117477 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:357478 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:117479 spdy::SpdySerializedFrame wrapped_get_resp(
7480 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7481 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
7482 spdy::SpdySerializedFrame wrapped_body(
7483 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7484 spdy::SpdySerializedFrame window_update_get_resp(
7485 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7486 spdy::SpdySerializedFrame window_update_body(
7487 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7488
7489 MockWrite spdy_writes1[] = {
7490 CreateMockWrite(connect, 0),
7491 CreateMockWrite(wrapped_get, 2),
7492 CreateMockWrite(window_update_get_resp, 6),
7493 CreateMockWrite(window_update_body, 7),
7494 };
7495
7496 MockRead spdy_reads1[] = {
7497 CreateMockRead(conn_resp, 1, ASYNC),
7498 MockRead(ASYNC, ERR_IO_PENDING, 3),
7499 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7500 CreateMockRead(wrapped_body, 5, ASYNC),
7501 MockRead(ASYNC, 0, 8),
7502 };
7503
7504 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7505 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7506
7507 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
7508 // a new pipe.
7509 SpdyTestUtil spdy_util2;
7510 spdy::SpdySerializedFrame req(
7511 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7512 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
7513
7514 spdy::SpdySerializedFrame resp(
7515 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7516 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
7517 MockRead spdy_reads2[] = {
7518 CreateMockRead(resp, 1),
7519 CreateMockRead(data, 2),
7520 MockRead(ASYNC, 0, 3),
7521 };
7522 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7523 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7524
7525 SSLSocketDataProvider ssl(ASYNC, OK);
7526 ssl.next_proto = kProtoHTTP2;
7527 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7528 SSLSocketDataProvider ssl2(ASYNC, OK);
7529 ssl2.next_proto = kProtoHTTP2;
7530 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7531 SSLSocketDataProvider ssl3(ASYNC, OK);
7532 ssl3.next_proto = kProtoHTTP2;
7533 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7534
7535 TestCompletionCallback callback;
7536 std::string response_data;
7537
7538 // Make a request using proxy:70 as a HTTP/2 proxy.
7539 capturing_proxy_resolver.set_proxy_server(
7540 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7541 HttpRequestInfo request1;
7542 request1.method = "GET";
7543 request1.url = GURL("https://www.example.org/");
7544 request1.traffic_annotation =
7545 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7546
7547 HttpNetworkTransaction trans1(LOWEST, session.get());
7548 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
7549 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7550
7551 // Allow the SpdyProxyClientSocket's write callback to complete.
7552 base::RunLoop().RunUntilIdle();
7553 // Now allow the read of the response to complete.
7554 spdy_data1.Resume();
7555 rv = callback.WaitForResult();
7556 EXPECT_THAT(rv, IsOk());
7557
7558 const HttpResponseInfo* response = trans1.GetResponseInfo();
7559 ASSERT_TRUE(response);
7560 ASSERT_TRUE(response->headers);
7561 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7562
7563 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7564 EXPECT_EQ(kUploadData, response_data);
7565 RunUntilIdle();
7566
7567 // Make a direct HTTP/2 request to proxy:70.
7568 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7569 HttpRequestInfo request2;
7570 request2.method = "GET";
7571 request2.url = GURL("https://proxy:70/");
7572 request2.traffic_annotation =
7573 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7574 HttpNetworkTransaction trans2(LOWEST, session.get());
7575 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
7576 NetLogWithSource())),
7577 IsOk());
7578 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7579}
7580
7581// Same as above, but reverse request order, since the code to check for an
7582// existing session is different for tunnels and direct connections.
7583TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
7584 // Configure against https proxy server "myproxy:80".
7585 ProxyConfig proxy_config;
7586 proxy_config.set_auto_detect(true);
7587 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
7588
7589 CapturingProxyResolver capturing_proxy_resolver;
7590 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:567591 std::make_unique<ConfiguredProxyResolutionService>(
Matt Menke2436b2f2018-12-11 18:07:117592 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
7593 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
7594 std::make_unique<CapturingProxyResolverFactory>(
7595 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:097596 nullptr, /*quick_check_enabled=*/true);
Matt Menke2436b2f2018-12-11 18:07:117597
7598 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7599 // Fetch https://proxy:70/ via HTTP/2.
7600 SpdyTestUtil spdy_util1;
7601 spdy::SpdySerializedFrame req(
7602 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
7603 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
7604
7605 spdy::SpdySerializedFrame resp(
7606 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
7607 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
7608 MockRead spdy_reads1[] = {
7609 CreateMockRead(resp, 1),
7610 CreateMockRead(data, 2),
7611 MockRead(ASYNC, 0, 3),
7612 };
7613 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
7614 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
7615
7616 SpdyTestUtil spdy_util2;
7617 // CONNECT to www.example.org:443 via HTTP/2.
7618 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:047619 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7620 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:117621 // fetch https://www.example.org/ via HTTP/2.
7622 const char kMyUrl[] = "https://www.example.org/";
7623 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
7624 spdy::SpdySerializedFrame wrapped_get(
7625 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
7626 spdy::SpdySerializedFrame conn_resp(
7627 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7628 spdy::SpdySerializedFrame get_resp(
7629 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
7630 spdy::SpdySerializedFrame wrapped_get_resp(
7631 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
7632 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
7633 spdy::SpdySerializedFrame wrapped_body(
7634 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
7635 spdy::SpdySerializedFrame window_update_get_resp(
7636 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
7637 spdy::SpdySerializedFrame window_update_body(
7638 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
7639
7640 MockWrite spdy_writes2[] = {
7641 CreateMockWrite(connect, 0),
7642 CreateMockWrite(wrapped_get, 2),
7643 CreateMockWrite(window_update_get_resp, 6),
7644 CreateMockWrite(window_update_body, 7),
7645 };
7646
7647 MockRead spdy_reads2[] = {
7648 CreateMockRead(conn_resp, 1, ASYNC),
7649 MockRead(ASYNC, ERR_IO_PENDING, 3),
7650 CreateMockRead(wrapped_get_resp, 4, ASYNC),
7651 CreateMockRead(wrapped_body, 5, ASYNC),
7652 MockRead(ASYNC, 0, 8),
7653 };
7654
7655 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
7656 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
7657
7658 SSLSocketDataProvider ssl(ASYNC, OK);
7659 ssl.next_proto = kProtoHTTP2;
7660 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7661 SSLSocketDataProvider ssl2(ASYNC, OK);
7662 ssl2.next_proto = kProtoHTTP2;
7663 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7664 SSLSocketDataProvider ssl3(ASYNC, OK);
7665 ssl3.next_proto = kProtoHTTP2;
7666 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7667
7668 TestCompletionCallback callback;
7669 std::string response_data;
7670
7671 // Make a direct HTTP/2 request to proxy:70.
7672 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
7673 HttpRequestInfo request1;
7674 request1.method = "GET";
7675 request1.url = GURL("https://proxy:70/");
7676 request1.traffic_annotation =
7677 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7678 HttpNetworkTransaction trans1(LOWEST, session.get());
7679 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
7680 NetLogWithSource())),
7681 IsOk());
7682 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
7683 RunUntilIdle();
7684
7685 // Make a request using proxy:70 as a HTTP/2 proxy.
7686 capturing_proxy_resolver.set_proxy_server(
7687 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
7688 HttpRequestInfo request2;
7689 request2.method = "GET";
7690 request2.url = GURL("https://www.example.org/");
7691 request2.traffic_annotation =
7692 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7693
7694 HttpNetworkTransaction trans2(LOWEST, session.get());
7695 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
7696 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7697
7698 // Allow the SpdyProxyClientSocket's write callback to complete.
7699 base::RunLoop().RunUntilIdle();
7700 // Now allow the read of the response to complete.
7701 spdy_data2.Resume();
7702 rv = callback.WaitForResult();
7703 EXPECT_THAT(rv, IsOk());
7704
7705 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
7706 ASSERT_TRUE(response2);
7707 ASSERT_TRUE(response2->headers);
7708 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
7709
7710 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
7711 EXPECT_EQ(kUploadData, response_data);
7712}
7713
[email protected]2df19bb2010-08-25 20:13:467714// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:017715TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:467716 HttpRequestInfo request;
7717 request.method = "GET";
bncce36dca22015-04-21 22:11:237718 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467719 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:007720 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:107721 request.traffic_annotation =
7722 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:467723
[email protected]79cb5c12011-09-12 13:12:047724 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567725 session_deps_.proxy_resolution_service =
7726 ConfiguredProxyResolutionService::CreateFixed(
7727 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:147728 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077729 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097730 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277731
[email protected]2df19bb2010-08-25 20:13:467732 // Since we have proxy, should use full url
7733 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:167734 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7735 "Host: www.example.org\r\n"
7736 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467737
bnc691fda62016-08-12 00:43:167738 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:237739 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:167740 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
7741 "Host: www.example.org\r\n"
7742 "Proxy-Connection: keep-alive\r\n"
7743 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467744 };
7745
7746 // The proxy responds to the GET with a 407, using a persistent
7747 // connection.
7748 MockRead data_reads1[] = {
7749 // No credentials.
7750 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7751 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7752 MockRead("Proxy-Connection: keep-alive\r\n"),
7753 MockRead("Content-Length: 0\r\n\r\n"),
7754
7755 MockRead("HTTP/1.1 200 OK\r\n"),
7756 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7757 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067758 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467759 };
7760
Ryan Sleevib8d7ea02018-05-07 20:01:017761 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077762 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:067763 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077764 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467765
[email protected]49639fa2011-12-20 23:22:417766 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:467767
bnc691fda62016-08-12 00:43:167768 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507769
bnc691fda62016-08-12 00:43:167770 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:017771 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467772
7773 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017774 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467775
[email protected]58e32bb2013-01-21 18:23:257776 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:167777 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257778 TestLoadTimingNotReused(load_timing_info,
7779 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7780
bnc691fda62016-08-12 00:43:167781 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527782 ASSERT_TRUE(response);
7783 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:467784 EXPECT_EQ(407, response->headers->response_code());
7785 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:587786 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:507787 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467788
[email protected]49639fa2011-12-20 23:22:417789 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:467790
bnc691fda62016-08-12 00:43:167791 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017792 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467793
7794 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017795 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467796
[email protected]58e32bb2013-01-21 18:23:257797 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:167798 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:257799 // Retrying with HTTP AUTH is considered to be reusing a socket.
7800 TestLoadTimingReused(load_timing_info);
7801
bnc691fda62016-08-12 00:43:167802 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527803 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:467804
7805 EXPECT_TRUE(response->headers->IsKeepAlive());
7806 EXPECT_EQ(200, response->headers->response_code());
7807 EXPECT_EQ(100, response->headers->GetContentLength());
7808 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:507809 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:467810
7811 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:587812 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:467813}
7814
[email protected]23e482282013-06-14 16:08:027815void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:087816 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:427817 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:087818 request.method = "GET";
bncce36dca22015-04-21 22:11:237819 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107820 request.traffic_annotation =
7821 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:087822
[email protected]cb9bf6ca2011-01-28 13:15:277823 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:567824 session_deps_.proxy_resolution_service =
7825 ConfiguredProxyResolutionService::CreateFixed(
7826 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097827 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277828
[email protected]c744cf22009-02-27 07:28:087829 // Since we have proxy, should try to establish tunnel.
7830 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177831 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7832 "Host: www.example.org:443\r\n"
7833 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:087834 };
7835
7836 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:237837 status, MockRead("Content-Length: 10\r\n\r\n"),
7838 // No response body because the test stops reading here.
7839 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:087840 };
7841
Ryan Sleevib8d7ea02018-05-07 20:01:017842 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:077843 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:087844
[email protected]49639fa2011-12-20 23:22:417845 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:087846
bnc691fda62016-08-12 00:43:167847 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507848
tfarina42834112016-09-22 13:38:207849 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017850 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:087851
7852 rv = callback.WaitForResult();
7853 EXPECT_EQ(expected_status, rv);
7854}
7855
[email protected]23e482282013-06-14 16:08:027856void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:237857 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:087858 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:427859 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:087860}
7861
bncd16676a2016-07-20 16:23:017862TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:087863 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
7864}
7865
bncd16676a2016-07-20 16:23:017866TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:087867 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
7868}
7869
bncd16676a2016-07-20 16:23:017870TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:087871 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
7872}
7873
bncd16676a2016-07-20 16:23:017874TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:087875 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
7876}
7877
bncd16676a2016-07-20 16:23:017878TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:087879 ConnectStatusHelper(
7880 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
7881}
7882
bncd16676a2016-07-20 16:23:017883TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:087884 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
7885}
7886
bncd16676a2016-07-20 16:23:017887TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:087888 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
7889}
7890
bncd16676a2016-07-20 16:23:017891TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:087892 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
7893}
7894
bncd16676a2016-07-20 16:23:017895TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:087896 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
7897}
7898
bncd16676a2016-07-20 16:23:017899TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:087900 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
7901}
7902
bncd16676a2016-07-20 16:23:017903TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:087904 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
7905}
7906
bncd16676a2016-07-20 16:23:017907TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:087908 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
7909}
7910
bncd16676a2016-07-20 16:23:017911TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:087912 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
7913}
7914
bncd16676a2016-07-20 16:23:017915TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:087916 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
7917}
7918
bncd16676a2016-07-20 16:23:017919TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:087920 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
7921}
7922
bncd16676a2016-07-20 16:23:017923TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:087924 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
7925}
7926
bncd16676a2016-07-20 16:23:017927TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:377928 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
7929}
7930
bncd16676a2016-07-20 16:23:017931TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:087932 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
7933}
7934
bncd16676a2016-07-20 16:23:017935TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:087936 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
7937}
7938
bncd16676a2016-07-20 16:23:017939TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:087940 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
7941}
7942
bncd16676a2016-07-20 16:23:017943TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:087944 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
7945}
7946
bncd16676a2016-07-20 16:23:017947TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:087948 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
7949}
7950
bncd16676a2016-07-20 16:23:017951TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:087952 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
7953}
7954
bncd16676a2016-07-20 16:23:017955TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:087956 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
7957}
7958
bncd16676a2016-07-20 16:23:017959TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:087960 ConnectStatusHelperWithExpectedStatus(
7961 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:547962 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:087963}
7964
bncd16676a2016-07-20 16:23:017965TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:087966 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
7967}
7968
bncd16676a2016-07-20 16:23:017969TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:087970 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
7971}
7972
bncd16676a2016-07-20 16:23:017973TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:087974 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
7975}
7976
bncd16676a2016-07-20 16:23:017977TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:087978 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
7979}
7980
bncd16676a2016-07-20 16:23:017981TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:087982 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
7983}
7984
bncd16676a2016-07-20 16:23:017985TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:087986 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
7987}
7988
bncd16676a2016-07-20 16:23:017989TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:087990 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
7991}
7992
bncd16676a2016-07-20 16:23:017993TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:087994 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
7995}
7996
bncd16676a2016-07-20 16:23:017997TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:087998 ConnectStatusHelper(
7999 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
8000}
8001
bncd16676a2016-07-20 16:23:018002TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:088003 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
8004}
8005
bncd16676a2016-07-20 16:23:018006TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:088007 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
8008}
8009
bncd16676a2016-07-20 16:23:018010TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:088011 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
8012}
8013
bncd16676a2016-07-20 16:23:018014TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:088015 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
8016}
8017
bncd16676a2016-07-20 16:23:018018TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:088019 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
8020}
8021
bncd16676a2016-07-20 16:23:018022TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:088023 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
8024}
8025
bncd16676a2016-07-20 16:23:018026TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:088027 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
8028}
8029
[email protected]038e9a32008-10-08 22:40:168030// Test the flow when both the proxy server AND origin server require
8031// authentication. Again, this uses basic auth for both since that is
8032// the simplest to mock.
bncd16676a2016-07-20 16:23:018033TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:278034 HttpRequestInfo request;
8035 request.method = "GET";
bncce36dca22015-04-21 22:11:238036 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108037 request.traffic_annotation =
8038 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278039
[email protected]038e9a32008-10-08 22:40:168040 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:568041 session_deps_.proxy_resolution_service =
8042 ConfiguredProxyResolutionService::CreateFixed(
8043 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:098044 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:078045
bnc691fda62016-08-12 00:43:168046 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:168047
[email protected]f9ee6b52008-11-08 06:46:238048 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238049 MockWrite(
8050 "GET http://www.example.org/ HTTP/1.1\r\n"
8051 "Host: www.example.org\r\n"
8052 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238053 };
8054
[email protected]038e9a32008-10-08 22:40:168055 MockRead data_reads1[] = {
8056 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
8057 // Give a couple authenticate options (only the middle one is actually
8058 // supported).
[email protected]22927ad2009-09-21 19:56:198059 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:168060 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8061 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
8062 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8063 // Large content-length -- won't matter, as connection will be reset.
8064 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068065 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:168066 };
8067
bnc691fda62016-08-12 00:43:168068 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:168069 // request we should be issuing -- the final header line contains the
8070 // proxy's credentials.
8071 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238072 MockWrite(
8073 "GET http://www.example.org/ HTTP/1.1\r\n"
8074 "Host: www.example.org\r\n"
8075 "Proxy-Connection: keep-alive\r\n"
8076 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:168077 };
8078
8079 // Now the proxy server lets the request pass through to origin server.
8080 // The origin server responds with a 401.
8081 MockRead data_reads2[] = {
8082 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8083 // Note: We are using the same realm-name as the proxy server. This is
8084 // completely valid, as realms are unique across hosts.
8085 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8086 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8087 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068088 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:168089 };
8090
bnc691fda62016-08-12 00:43:168091 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:168092 // the credentials for both the proxy and origin server.
8093 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238094 MockWrite(
8095 "GET http://www.example.org/ HTTP/1.1\r\n"
8096 "Host: www.example.org\r\n"
8097 "Proxy-Connection: keep-alive\r\n"
8098 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
8099 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:168100 };
8101
8102 // Lastly we get the desired content.
8103 MockRead data_reads3[] = {
8104 MockRead("HTTP/1.0 200 OK\r\n"),
8105 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8106 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068107 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:168108 };
8109
Ryan Sleevib8d7ea02018-05-07 20:01:018110 StaticSocketDataProvider data1(data_reads1, data_writes1);
8111 StaticSocketDataProvider data2(data_reads2, data_writes2);
8112 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078113 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8114 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8115 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:168116
[email protected]49639fa2011-12-20 23:22:418117 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:168118
tfarina42834112016-09-22 13:38:208119 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018120 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:168121
8122 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018123 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:168124
bnc691fda62016-08-12 00:43:168125 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528126 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588127 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:168128
[email protected]49639fa2011-12-20 23:22:418129 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:168130
bnc691fda62016-08-12 00:43:168131 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:018132 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:168133
8134 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018135 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:168136
bnc691fda62016-08-12 00:43:168137 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528138 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588139 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:168140
[email protected]49639fa2011-12-20 23:22:418141 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:168142
bnc691fda62016-08-12 00:43:168143 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
8144 callback3.callback());
robpercival214763f2016-07-01 23:27:018145 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:168146
8147 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018148 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:168149
bnc691fda62016-08-12 00:43:168150 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:588151 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:168152 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:168153}
[email protected]4ddaf2502008-10-23 18:26:198154
[email protected]ea9dc9a2009-09-05 00:43:328155// For the NTLM implementation using SSPI, we skip the NTLM tests since we
8156// can't hook into its internals to cause it to generate predictable NTLM
8157// authorization headers.
8158#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378159// The NTLM authentication unit tests are based on known test data from the
8160// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
8161// flow rather than the implementation of the NTLM protocol. See net/ntlm
8162// for the implementation and testing of the protocol.
8163//
8164// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:298165
8166// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:558167TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:428168 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:248169 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:558170 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:108171 request.traffic_annotation =
8172 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:548173
8174 // Ensure load is not disrupted by flags which suppress behaviour specific
8175 // to other auth schemes.
8176 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:248177
Asanka Herathbf0b55d2019-12-07 03:27:098178 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098179 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:098180 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278181
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378182 // Generate the NTLM messages based on known test data.
8183 std::string negotiate_msg;
8184 std::string challenge_msg;
8185 std::string authenticate_msg;
8186 base::Base64Encode(
8187 base::StringPiece(
8188 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248189 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378190 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558191 base::Base64Encode(
8192 base::StringPiece(
8193 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248194 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558195 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378196 base::Base64Encode(
8197 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098198 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558199 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248200 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558201 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378202 &authenticate_msg);
8203
[email protected]3f918782009-02-28 01:29:248204 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:558205 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
8206 "Host: server\r\n"
8207 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:248208 };
8209
8210 MockRead data_reads1[] = {
8211 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:048212 // Negotiate and NTLM are often requested together. However, we only want
8213 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
8214 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:248215 MockRead("WWW-Authenticate: NTLM\r\n"),
8216 MockRead("Connection: close\r\n"),
8217 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:368218 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:248219 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:248220 };
8221
8222 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:168223 // After restarting with a null identity, this is the
8224 // request we should be issuing -- the final header line contains a Type
8225 // 1 message.
8226 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558227 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168228 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378229 "Authorization: NTLM "),
8230 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:248231
bnc691fda62016-08-12 00:43:168232 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378233 // (using correct credentials). The second request continues on the
8234 // same connection.
bnc691fda62016-08-12 00:43:168235 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558236 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168237 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378238 "Authorization: NTLM "),
8239 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:248240 };
8241
8242 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:028243 // The origin server responds with a Type 2 message.
8244 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378245 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8246 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028247 MockRead("Content-Type: text/html\r\n\r\n"),
8248 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:248249
Bence Béky1e4ef192017-09-18 19:58:028250 // Lastly we get the desired content.
8251 MockRead("HTTP/1.1 200 OK\r\n"),
8252 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
8253 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:248254 };
8255
Ryan Sleevib8d7ea02018-05-07 20:01:018256 StaticSocketDataProvider data1(data_reads1, data_writes1);
8257 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078258 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8259 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:248260
Bence Béky83eb3512017-09-05 12:56:098261 SSLSocketDataProvider ssl1(ASYNC, OK);
8262 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8263 SSLSocketDataProvider ssl2(ASYNC, OK);
8264 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8265
[email protected]49639fa2011-12-20 23:22:418266 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:248267
bnc691fda62016-08-12 00:43:168268 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508269
tfarina42834112016-09-22 13:38:208270 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018271 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:248272
8273 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018274 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:248275
bnc691fda62016-08-12 00:43:168276 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228277
bnc691fda62016-08-12 00:43:168278 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528279 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588280 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:248281
[email protected]49639fa2011-12-20 23:22:418282 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:258283
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378284 rv = trans.RestartWithAuth(
8285 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8286 callback2.callback());
robpercival214763f2016-07-01 23:27:018287 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258288
8289 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018290 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258291
bnc691fda62016-08-12 00:43:168292 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258293
bnc691fda62016-08-12 00:43:168294 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528295 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588296 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:258297
[email protected]49639fa2011-12-20 23:22:418298 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:248299
bnc691fda62016-08-12 00:43:168300 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018301 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:248302
[email protected]0757e7702009-03-27 04:00:228303 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018304 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:248305
bnc691fda62016-08-12 00:43:168306 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528307 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588308 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028309 EXPECT_EQ(14, response->headers->GetContentLength());
8310
8311 std::string response_data;
8312 rv = ReadTransaction(&trans, &response_data);
8313 EXPECT_THAT(rv, IsOk());
8314 EXPECT_EQ("Please Login\r\n", response_data);
8315
8316 EXPECT_TRUE(data1.AllReadDataConsumed());
8317 EXPECT_TRUE(data1.AllWriteDataConsumed());
8318 EXPECT_TRUE(data2.AllReadDataConsumed());
8319 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:248320}
8321
[email protected]385a4672009-03-11 22:21:298322// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:558323TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:428324 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:298325 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:558326 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:108327 request.traffic_annotation =
8328 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:298329
Asanka Herathbf0b55d2019-12-07 03:27:098330 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098331 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:098332 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278333
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378334 // Generate the NTLM messages based on known test data.
8335 std::string negotiate_msg;
8336 std::string challenge_msg;
8337 std::string authenticate_msg;
8338 base::Base64Encode(
8339 base::StringPiece(
8340 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248341 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378342 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558343 base::Base64Encode(
8344 base::StringPiece(
8345 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248346 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558347 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378348 base::Base64Encode(
8349 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098350 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558351 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248352 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558353 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378354 &authenticate_msg);
8355
8356 // The authenticate message when |kWrongPassword| is sent.
8357 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558358 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
8359 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
8360 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
8361 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
8362 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
8363 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378364
Zentaro Kavanagh1890a3d2018-01-29 19:52:558365 // Sanity check that it's the same length as the correct authenticate message
8366 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378367 ASSERT_EQ(authenticate_msg.length(),
8368 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:558369 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378370
[email protected]385a4672009-03-11 22:21:298371 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:558372 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
8373 "Host: server\r\n"
8374 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298375 };
8376
8377 MockRead data_reads1[] = {
8378 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:048379 // Negotiate and NTLM are often requested together. However, we only want
8380 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
8381 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:298382 MockRead("WWW-Authenticate: NTLM\r\n"),
8383 MockRead("Connection: close\r\n"),
8384 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:368385 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298386 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298387 };
8388
8389 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:168390 // After restarting with a null identity, this is the
8391 // request we should be issuing -- the final header line contains a Type
8392 // 1 message.
8393 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558394 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168395 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378396 "Authorization: NTLM "),
8397 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298398
bnc691fda62016-08-12 00:43:168399 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378400 // (using incorrect credentials). The second request continues on the
8401 // same connection.
bnc691fda62016-08-12 00:43:168402 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558403 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168404 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378405 "Authorization: NTLM "),
8406 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298407 };
8408
8409 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378410 // The origin server responds with a Type 2 message.
8411 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8412 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8413 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
8414 MockRead("Content-Type: text/html\r\n\r\n"),
8415 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298416
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378417 // Wrong password.
8418 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8419 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
8420 MockRead("Content-Length: 42\r\n"),
8421 MockRead("Content-Type: text/html\r\n\r\n"),
8422 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:298423 };
8424
8425 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:168426 // After restarting with a null identity, this is the
8427 // request we should be issuing -- the final header line contains a Type
8428 // 1 message.
8429 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558430 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168431 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378432 "Authorization: NTLM "),
8433 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298434
bnc691fda62016-08-12 00:43:168435 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8436 // (the credentials for the origin server). The second request continues
8437 // on the same connection.
8438 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558439 "Host: server\r\n"
bnc691fda62016-08-12 00:43:168440 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378441 "Authorization: NTLM "),
8442 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:298443 };
8444
8445 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:028446 // The origin server responds with a Type 2 message.
8447 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378448 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8449 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028450 MockRead("Content-Type: text/html\r\n\r\n"),
8451 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:298452
Bence Béky1e4ef192017-09-18 19:58:028453 // Lastly we get the desired content.
8454 MockRead("HTTP/1.1 200 OK\r\n"),
8455 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
8456 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:298457 };
8458
Ryan Sleevib8d7ea02018-05-07 20:01:018459 StaticSocketDataProvider data1(data_reads1, data_writes1);
8460 StaticSocketDataProvider data2(data_reads2, data_writes2);
8461 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078462 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8463 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8464 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:298465
Bence Béky83eb3512017-09-05 12:56:098466 SSLSocketDataProvider ssl1(ASYNC, OK);
8467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8468 SSLSocketDataProvider ssl2(ASYNC, OK);
8469 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8470 SSLSocketDataProvider ssl3(ASYNC, OK);
8471 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8472
[email protected]49639fa2011-12-20 23:22:418473 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:298474
bnc691fda62016-08-12 00:43:168475 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:508476
tfarina42834112016-09-22 13:38:208477 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018478 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298479
8480 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018481 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298482
bnc691fda62016-08-12 00:43:168483 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:298484
bnc691fda62016-08-12 00:43:168485 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528486 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588487 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:298488
[email protected]49639fa2011-12-20 23:22:418489 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:298490
[email protected]0757e7702009-03-27 04:00:228491 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378492 rv = trans.RestartWithAuth(
8493 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
8494 callback2.callback());
robpercival214763f2016-07-01 23:27:018495 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:298496
[email protected]10af5fe72011-01-31 16:17:258497 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018498 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:298499
bnc691fda62016-08-12 00:43:168500 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:418501 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168502 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:018503 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258504 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018505 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168506 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228507
bnc691fda62016-08-12 00:43:168508 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528509 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588510 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:228511
[email protected]49639fa2011-12-20 23:22:418512 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:228513
8514 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378515 rv = trans.RestartWithAuth(
8516 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8517 callback4.callback());
robpercival214763f2016-07-01 23:27:018518 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:258519
8520 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:018521 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:258522
bnc691fda62016-08-12 00:43:168523 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:258524
[email protected]49639fa2011-12-20 23:22:418525 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:258526
8527 // One more roundtrip
bnc691fda62016-08-12 00:43:168528 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:018529 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:228530
8531 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:018532 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:228533
bnc691fda62016-08-12 00:43:168534 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:588535 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028536 EXPECT_EQ(14, response->headers->GetContentLength());
8537
8538 std::string response_data;
8539 rv = ReadTransaction(&trans, &response_data);
8540 EXPECT_THAT(rv, IsOk());
8541 EXPECT_EQ("Please Login\r\n", response_data);
8542
8543 EXPECT_TRUE(data1.AllReadDataConsumed());
8544 EXPECT_TRUE(data1.AllWriteDataConsumed());
8545 EXPECT_TRUE(data2.AllReadDataConsumed());
8546 EXPECT_TRUE(data2.AllWriteDataConsumed());
8547 EXPECT_TRUE(data3.AllReadDataConsumed());
8548 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:298549}
Bence Béky83eb3512017-09-05 12:56:098550
Bence Béky3238f2e12017-09-22 22:44:498551// Server requests NTLM authentication, which is not supported over HTTP/2.
8552// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:098553TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Asanka Herathbf0b55d2019-12-07 03:27:098554 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Zentaro Kavanagh6ccee512017-09-28 18:34:098555 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:098556
Zentaro Kavanagh1890a3d2018-01-29 19:52:558557 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:098558
8559 HttpRequestInfo request;
8560 request.method = "GET";
8561 request.url = GURL(kUrl);
Ramin Halavatib5e433e62018-02-07 07:41:108562 request.traffic_annotation =
8563 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:098564
8565 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:138566 spdy::SpdyHeaderBlock request_headers0(
8567 spdy_util_.ConstructGetHeaderBlock(kUrl));
8568 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:098569 1, std::move(request_headers0), LOWEST, true));
8570
Ryan Hamilton0239aac2018-05-19 00:03:138571 spdy::SpdyHeaderBlock response_headers0;
8572 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:098573 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:138574 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:098575 1, std::move(response_headers0), true));
8576
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378577 // Stream 1 is closed.
8578 spdy_util_.UpdateWithStreamDestruction(1);
8579
8580 // Generate the NTLM messages based on known test data.
8581 std::string negotiate_msg;
8582 std::string challenge_msg;
8583 std::string authenticate_msg;
8584 base::Base64Encode(
8585 base::StringPiece(
8586 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248587 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378588 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:558589 base::Base64Encode(
8590 base::StringPiece(
8591 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248592 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:558593 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378594 base::Base64Encode(
8595 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:098596 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558597 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248598 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:558599 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378600 &authenticate_msg);
8601
Bence Béky3238f2e12017-09-22 22:44:498602 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:168603 MockRead reads0[] = {CreateMockRead(resp, 1),
8604 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:098605
8606 // Retry yet again using HTTP/1.1.
8607 MockWrite writes1[] = {
8608 // After restarting with a null identity, this is the
8609 // request we should be issuing -- the final header line contains a Type
8610 // 1 message.
8611 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558612 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098613 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378614 "Authorization: NTLM "),
8615 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098616
8617 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8618 // (the credentials for the origin server). The second request continues
8619 // on the same connection.
8620 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:558621 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:098622 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378623 "Authorization: NTLM "),
8624 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:098625 };
8626
8627 MockRead reads1[] = {
8628 // The origin server responds with a Type 2 message.
8629 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378630 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
8631 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:098632 MockRead("Content-Type: text/html\r\n\r\n"),
8633 MockRead("You are not authorized to view this page\r\n"),
8634
8635 // Lastly we get the desired content.
8636 MockRead("HTTP/1.1 200 OK\r\n"),
8637 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:028638 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:098639 };
Ryan Sleevib8d7ea02018-05-07 20:01:018640 SequencedSocketData data0(reads0, writes0);
8641 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:098642 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8643 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8644
8645 SSLSocketDataProvider ssl0(ASYNC, OK);
8646 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:168647 ssl0.next_protos_expected_in_ssl_config =
8648 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098649 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:168650 // When creating the second connection, only HTTP/1.1 should be allowed.
8651 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:098652 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8653 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8654
8655 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8656 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8657
8658 TestCompletionCallback callback1;
8659 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
8660 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8661
8662 rv = callback1.WaitForResult();
8663 EXPECT_THAT(rv, IsOk());
8664
8665 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
8666
8667 const HttpResponseInfo* response = trans.GetResponseInfo();
8668 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588669 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:098670
8671 TestCompletionCallback callback2;
8672
Zentaro Kavanagh5b27a6e22017-09-25 23:00:378673 rv = trans.RestartWithAuth(
8674 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8675 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:098676 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8677
8678 rv = callback2.WaitForResult();
8679 EXPECT_THAT(rv, IsOk());
8680
8681 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
8682
8683 response = trans.GetResponseInfo();
8684 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588685 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:098686
8687 TestCompletionCallback callback3;
8688
8689 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
8690 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8691
8692 rv = callback3.WaitForResult();
8693 EXPECT_THAT(rv, IsOk());
8694
8695 response = trans.GetResponseInfo();
8696 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588697 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:028698 EXPECT_EQ(14, response->headers->GetContentLength());
8699
8700 std::string response_data;
8701 rv = ReadTransaction(&trans, &response_data);
8702 EXPECT_THAT(rv, IsOk());
8703 EXPECT_EQ("Please Login\r\n", response_data);
8704
8705 EXPECT_TRUE(data0.AllReadDataConsumed());
8706 EXPECT_TRUE(data0.AllWriteDataConsumed());
8707 EXPECT_TRUE(data1.AllReadDataConsumed());
8708 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:098709}
David Benjamin5cb91132018-04-06 05:54:498710
Matt Menkef2ee07c2019-08-29 02:10:368711#if BUILDFLAG(ENABLE_WEBSOCKETS)
8712
8713// Variant of above test using WebSockets.
8714TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
8715 const GURL kInitialUrl("https://server/");
8716 const GURL kWebSocketUrl("wss://server/");
Asanka Herathbf0b55d2019-12-07 03:27:098717 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
Matt Menkef2ee07c2019-08-29 02:10:368718 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8719
8720 // Initial request establishes an H2 connection, which will then be reused for
8721 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
8722 // it won't create a new one.
8723 spdy::SpdyHeaderBlock initial_request_headers(
8724 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
8725 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
8726 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
8727 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
8728
8729 // Settings frame, indicating WebSockets is supported.
8730 spdy::SettingsMap settings;
8731 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
8732 spdy::SpdySerializedFrame settings_frame(
8733 spdy_util_.ConstructSpdySettings(settings));
8734
8735 // Response headers for first request. Body is never received, but that
8736 // shouldn't matter for the purposes of this test.
8737 spdy::SpdySerializedFrame initial_response(
8738 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8739
8740 // First WebSocket request, which has no credentials.
8741 spdy::SpdyHeaderBlock websocket_request_headers;
8742 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
8743 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
8744 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
8745 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
8746 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
8747 websocket_request_headers["origin"] = "http://server";
8748 websocket_request_headers["sec-websocket-version"] = "13";
8749 websocket_request_headers["sec-websocket-extensions"] =
8750 "permessage-deflate; client_max_window_bits";
8751 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
8752 3, std::move(websocket_request_headers), MEDIUM, false));
8753
8754 // Auth challenge to WebSocket request.
8755 spdy::SpdyHeaderBlock auth_challenge_headers;
8756 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
8757 auth_challenge_headers["www-authenticate"] = "NTLM";
8758 spdy::SpdySerializedFrame websocket_auth_challenge(
8759 spdy_util_.ConstructSpdyResponseHeaders(
8760 3, std::move(auth_challenge_headers), true));
8761
8762 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
8763 CreateMockWrite(settings_ack, 2),
8764 CreateMockWrite(websocket_request, 4),
8765 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
8766 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
8767 CreateMockRead(initial_response, 3),
8768 CreateMockRead(websocket_auth_challenge, 5),
8769 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
8770
8771 // Generate the NTLM messages based on known test data.
8772 std::string negotiate_msg;
8773 std::string challenge_msg;
8774 std::string authenticate_msg;
8775 base::Base64Encode(
8776 base::StringPiece(
8777 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
8778 base::size(ntlm::test::kExpectedNegotiateMsg)),
8779 &negotiate_msg);
8780 base::Base64Encode(
8781 base::StringPiece(
8782 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
8783 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
8784 &challenge_msg);
8785 base::Base64Encode(
8786 base::StringPiece(
8787 reinterpret_cast<const char*>(
8788 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
8789 base::size(
8790 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8791 &authenticate_msg);
8792
8793 // Retry yet again using HTTP/1.1.
8794 MockWrite writes1[] = {
8795 // After restarting with a null identity, this is the
8796 // request we should be issuing -- the final header line contains a Type
8797 // 1 message.
8798 MockWrite("GET / HTTP/1.1\r\n"
8799 "Host: server\r\n"
8800 "Connection: Upgrade\r\n"
8801 "Authorization: NTLM "),
8802 MockWrite(negotiate_msg.c_str()),
8803 MockWrite("\r\n"),
8804 MockWrite("Origin: http://server\r\n"
8805 "Sec-WebSocket-Version: 13\r\n"
8806 "Upgrade: websocket\r\n"
8807 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8808 "Sec-WebSocket-Extensions: permessage-deflate; "
8809 "client_max_window_bits\r\n\r\n"),
8810
8811 // After calling trans.RestartWithAuth(), we should send a Type 3 message
8812 // (the credentials for the origin server). The second request continues
8813 // on the same connection.
8814 MockWrite("GET / HTTP/1.1\r\n"
8815 "Host: server\r\n"
8816 "Connection: Upgrade\r\n"
8817 "Authorization: NTLM "),
8818 MockWrite(authenticate_msg.c_str()),
8819 MockWrite("\r\n"),
8820 MockWrite("Origin: http://server\r\n"
8821 "Sec-WebSocket-Version: 13\r\n"
8822 "Upgrade: websocket\r\n"
8823 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
8824 "Sec-WebSocket-Extensions: permessage-deflate; "
8825 "client_max_window_bits\r\n\r\n"),
8826 };
8827
8828 MockRead reads1[] = {
8829 // The origin server responds with a Type 2 message.
8830 MockRead("HTTP/1.1 401 Access Denied\r\n"),
8831 MockRead("WWW-Authenticate: NTLM "),
8832 MockRead(challenge_msg.c_str()),
8833 MockRead("\r\n"),
8834 MockRead("Content-Length: 42\r\n"),
8835 MockRead("Content-Type: text/html\r\n\r\n"),
8836 MockRead("You are not authorized to view this page\r\n"),
8837
8838 // Lastly we get the desired content.
8839 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
8840 "Upgrade: websocket\r\n"
8841 "Connection: Upgrade\r\n"
8842 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
8843 };
8844 SequencedSocketData data0(reads0, writes0);
8845 session_deps_.socket_factory->AddSocketDataProvider(&data0);
8846 SSLSocketDataProvider ssl0(ASYNC, OK);
8847 ssl0.next_proto = kProtoHTTP2;
8848 ssl0.next_protos_expected_in_ssl_config =
8849 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
8850 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
8851
8852 StaticSocketDataProvider data1(reads1, writes1);
8853 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8854 SSLSocketDataProvider ssl1(ASYNC, OK);
8855 // When creating the second connection, only HTTP/1.1 should be allowed.
8856 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
8857 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
8858
8859 session_deps_.enable_websocket_over_http2 = true;
8860 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8861
8862 HttpRequestInfo initial_request_info;
8863 initial_request_info.method = "GET";
8864 initial_request_info.url = kInitialUrl;
8865 initial_request_info.traffic_annotation =
8866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8867 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
8868 TestCompletionCallback initial_callback;
8869 int rv = initial_trans.Start(&initial_request_info,
8870 initial_callback.callback(), NetLogWithSource());
8871 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
8872
8873 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
8874 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8875
8876 HttpRequestInfo websocket_request_info;
8877 websocket_request_info.method = "GET";
8878 websocket_request_info.url = kWebSocketUrl;
8879 websocket_request_info.traffic_annotation =
8880 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8881 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
8882 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
8883 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
8884 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
8885 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
8886 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
8887 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
8888
8889 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
8890
8891 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
8892 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
8893 &websocket_stream_create_helper);
8894
8895 TestCompletionCallback websocket_callback;
8896 rv = websocket_trans.Start(&websocket_request_info,
8897 websocket_callback.callback(), NetLogWithSource());
8898 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8899
8900 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
8901
8902 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
8903 ASSERT_TRUE(response);
8904 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
8905
8906 rv = websocket_trans.RestartWithAuth(
8907 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
8908 websocket_callback.callback());
8909 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8910
8911 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
8912
8913 response = websocket_trans.GetResponseInfo();
8914 ASSERT_TRUE(response);
8915 EXPECT_FALSE(response->auth_challenge.has_value());
8916
8917 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
8918 websocket_callback.callback());
8919 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
8920
8921 // The server should have been marked as requiring HTTP/1.1. The important
8922 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
8923 // WSS.
8924 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
8925 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
8926}
8927
8928#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
8929
David Benjamin5cb91132018-04-06 05:54:498930// Test that, if we have an NTLM proxy and the origin resets the connection, we
David Benjamin07a07d652020-02-26 22:26:598931// do no retry forever as a result of TLS retries. This is a regression test for
8932// https://crbug.com/823387. The version interference probe has since been
8933// removed, but we now have a legacy crypto fallback. (If that fallback is
8934// removed, this test should be kept but with the expectations tweaked, in case
8935// future fallbacks are added.)
David Benjamin5cb91132018-04-06 05:54:498936TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
8937 // The NTLM test data expects the proxy to be named 'server'. The origin is
8938 // https://origin/.
8939 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:568940 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
David Benjamin5cb91132018-04-06 05:54:498941 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
8942
David Benjamin151ec6b2019-08-02 19:38:528943 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:498944 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:078945 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:498946
8947 HttpRequestInfo request;
8948 request.method = "GET";
8949 request.url = GURL("https://origin/");
8950 request.traffic_annotation =
8951 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8952
8953 // Ensure load is not disrupted by flags which suppress behaviour specific
8954 // to other auth schemes.
8955 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
8956
Asanka Herathbf0b55d2019-12-07 03:27:098957 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
David Benjamin5cb91132018-04-06 05:54:498958 MockGetMSTime, MockGenerateRandom, MockGetHostName);
8959 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8960
8961 // Generate the NTLM messages based on known test data.
8962 std::string negotiate_msg;
8963 std::string challenge_msg;
8964 std::string authenticate_msg;
8965 base::Base64Encode(
8966 base::StringPiece(
8967 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:248968 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:498969 &negotiate_msg);
8970 base::Base64Encode(
8971 base::StringPiece(
8972 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:248973 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:498974 &challenge_msg);
8975 base::Base64Encode(
8976 base::StringPiece(
8977 reinterpret_cast<const char*>(
8978 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:248979 base::size(
David Benjamin5cb91132018-04-06 05:54:498980 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
8981 &authenticate_msg);
8982
8983 MockWrite data_writes[] = {
8984 // The initial CONNECT request.
8985 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8986 "Host: origin:443\r\n"
8987 "Proxy-Connection: keep-alive\r\n\r\n"),
8988
8989 // After restarting with an identity.
8990 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
8991 "Host: origin:443\r\n"
8992 "Proxy-Connection: keep-alive\r\n"
8993 "Proxy-Authorization: NTLM "),
8994 MockWrite(negotiate_msg.c_str()),
8995 // End headers.
8996 MockWrite("\r\n\r\n"),
8997
8998 // The second restart.
8999 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
9000 "Host: origin:443\r\n"
9001 "Proxy-Connection: keep-alive\r\n"
9002 "Proxy-Authorization: NTLM "),
9003 MockWrite(authenticate_msg.c_str()),
9004 // End headers.
9005 MockWrite("\r\n\r\n"),
9006 };
9007
9008 MockRead data_reads[] = {
9009 // The initial NTLM response.
9010 MockRead("HTTP/1.1 407 Access Denied\r\n"
9011 "Content-Length: 0\r\n"
9012 "Proxy-Authenticate: NTLM\r\n\r\n"),
9013
9014 // The NTLM challenge message.
9015 MockRead("HTTP/1.1 407 Access Denied\r\n"
9016 "Content-Length: 0\r\n"
9017 "Proxy-Authenticate: NTLM "),
9018 MockRead(challenge_msg.c_str()),
9019 // End headers.
9020 MockRead("\r\n\r\n"),
9021
9022 // Finally the tunnel is established.
9023 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
9024 };
9025
Ryan Sleevib8d7ea02018-05-07 20:01:019026 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:499027 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:499028 session_deps_.socket_factory->AddSocketDataProvider(&data);
9029 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:499030
David Benjamin07a07d652020-02-26 22:26:599031 StaticSocketDataProvider data2(data_reads, data_writes);
9032 SSLSocketDataProvider data2_ssl(ASYNC, ERR_CONNECTION_RESET);
9033 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9034 session_deps_.socket_factory->AddSSLSocketDataProvider(&data2_ssl);
9035
David Benjamin5cb91132018-04-06 05:54:499036 // Start the transaction. The proxy responds with an NTLM authentication
9037 // request.
9038 TestCompletionCallback callback;
9039 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9040 int rv = callback.GetResult(
9041 trans.Start(&request, callback.callback(), NetLogWithSource()));
9042
9043 EXPECT_THAT(rv, IsOk());
9044 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
9045 const HttpResponseInfo* response = trans.GetResponseInfo();
9046 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589047 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:499048
David Benjamind61bd532019-04-23 21:11:379049 // Configure credentials and restart. The proxy responds with the challenge
9050 // message.
David Benjamin5cb91132018-04-06 05:54:499051 rv = callback.GetResult(trans.RestartWithAuth(
9052 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
9053 callback.callback()));
9054 EXPECT_THAT(rv, IsOk());
9055 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
9056 response = trans.GetResponseInfo();
9057 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589058 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:499059
David Benjamin07a07d652020-02-26 22:26:599060 // Restart once more. The tunnel will be established and the the SSL handshake
9061 // will reset. The fallback will then kick in and restart the process. The
9062 // proxy responds with another NTLM authentiation request, but we don't need
9063 // to provide credentials as the cached ones work.
9064 rv = callback.GetResult(
9065 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
9066 EXPECT_THAT(rv, IsOk());
9067 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
9068 response = trans.GetResponseInfo();
9069 ASSERT_TRUE(response);
9070 EXPECT_FALSE(response->auth_challenge.has_value());
9071
9072 // The proxy responds with the NTLM challenge message.
9073 rv = callback.GetResult(
9074 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
9075 EXPECT_THAT(rv, IsOk());
9076 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
9077 response = trans.GetResponseInfo();
9078 ASSERT_TRUE(response);
9079 EXPECT_FALSE(response->auth_challenge.has_value());
9080
9081 // Send the NTLM authenticate message. The tunnel is established and the
9082 // handshake resets again. We should not retry again.
David Benjamin5cb91132018-04-06 05:54:499083 rv = callback.GetResult(
9084 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
9085 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
9086}
9087
[email protected]ea9dc9a2009-09-05 00:43:329088#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:299089
[email protected]4ddaf2502008-10-23 18:26:199090// Test reading a server response which has only headers, and no body.
9091// After some maximum number of bytes is consumed, the transaction should
9092// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:019093TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:429094 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:199095 request.method = "GET";
bncce36dca22015-04-21 22:11:239096 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109097 request.traffic_annotation =
9098 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:199099
danakj1fd259a02016-04-16 03:17:099100 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169101 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279102
[email protected]b75b7b2f2009-10-06 00:54:539103 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:439104 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:539105 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:199106
9107 MockRead data_reads[] = {
9108 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:069109 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:199110 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:069111 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:199112 };
Ryan Sleevib8d7ea02018-05-07 20:01:019113 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079114 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:199115
[email protected]49639fa2011-12-20 23:22:419116 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:199117
tfarina42834112016-09-22 13:38:209118 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019119 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:199120
9121 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019122 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:199123}
[email protected]f4e426b2008-11-05 00:24:499124
9125// Make sure that we don't try to reuse a TCPClientSocket when failing to
9126// establish tunnel.
9127// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:019128TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:279129 HttpRequestInfo request;
9130 request.method = "GET";
bncce36dca22015-04-21 22:11:239131 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109132 request.traffic_annotation =
9133 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:279134
[email protected]f4e426b2008-11-05 00:24:499135 // Configure against proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:569136 session_deps_.proxy_resolution_service =
9137 ConfiguredProxyResolutionService::CreateFixed(
9138 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:019139
danakj1fd259a02016-04-16 03:17:099140 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:499141
bnc87dcefc2017-05-25 12:47:589142 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199143 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:499144
[email protected]f4e426b2008-11-05 00:24:499145 // Since we have proxy, should try to establish tunnel.
9146 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:179147 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9148 "Host: www.example.org:443\r\n"
9149 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:499150 };
9151
[email protected]77848d12008-11-14 00:00:229152 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:499153 // connection. Usually a proxy would return 501 (not implemented),
9154 // or 200 (tunnel established).
9155 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:239156 MockRead("HTTP/1.1 404 Not Found\r\n"),
9157 MockRead("Content-Length: 10\r\n\r\n"),
9158 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:499159 };
9160
Ryan Sleevib8d7ea02018-05-07 20:01:019161 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079162 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:499163
[email protected]49639fa2011-12-20 23:22:419164 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:499165
tfarina42834112016-09-22 13:38:209166 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019167 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:499168
9169 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019170 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:499171
[email protected]b4404c02009-04-10 16:38:529172 // Empty the current queue. This is necessary because idle sockets are
9173 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559174 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529175
[email protected]f4e426b2008-11-05 00:24:499176 // We now check to make sure the TCPClientSocket was not added back to
9177 // the pool.
[email protected]90499482013-06-01 00:39:509178 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:499179 trans.reset();
fdoray92e35a72016-06-10 15:54:559180 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:499181 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:509182 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:499183}
[email protected]372d34a2008-11-05 21:30:519184
[email protected]1b157c02009-04-21 01:55:409185// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:019186TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:429187 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:409188 request.method = "GET";
bncce36dca22015-04-21 22:11:239189 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109190 request.traffic_annotation =
9191 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:409192
danakj1fd259a02016-04-16 03:17:099193 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279194
bnc691fda62016-08-12 00:43:169195 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279196
[email protected]1b157c02009-04-21 01:55:409197 MockRead data_reads[] = {
9198 // A part of the response body is received with the response headers.
9199 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9200 // The rest of the response body is received in two parts.
9201 MockRead("lo"),
9202 MockRead(" world"),
9203 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069204 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:409205 };
9206
Ryan Sleevib8d7ea02018-05-07 20:01:019207 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079208 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:409209
[email protected]49639fa2011-12-20 23:22:419210 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:409211
tfarina42834112016-09-22 13:38:209212 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019213 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:409214
9215 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019216 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:409217
bnc691fda62016-08-12 00:43:169218 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529219 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:409220
wezca1070932016-05-26 20:30:529221 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:409222 std::string status_line = response->headers->GetStatusLine();
9223 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9224
[email protected]90499482013-06-01 00:39:509225 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:409226
9227 std::string response_data;
bnc691fda62016-08-12 00:43:169228 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019229 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:409230 EXPECT_EQ("hello world", response_data);
9231
9232 // Empty the current queue. This is necessary because idle sockets are
9233 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559234 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:409235
9236 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509237 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:409238}
9239
[email protected]76a505b2010-08-25 06:23:009240// Make sure that we recycle a SSL socket after reading all of the response
9241// body.
bncd16676a2016-07-20 16:23:019242TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:009243 HttpRequestInfo request;
9244 request.method = "GET";
bncce36dca22015-04-21 22:11:239245 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109246 request.traffic_annotation =
9247 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:009248
9249 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239250 MockWrite(
9251 "GET / HTTP/1.1\r\n"
9252 "Host: www.example.org\r\n"
9253 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:009254 };
9255
9256 MockRead data_reads[] = {
9257 MockRead("HTTP/1.1 200 OK\r\n"),
9258 MockRead("Content-Length: 11\r\n\r\n"),
9259 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069260 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:009261 };
9262
[email protected]8ddf8322012-02-23 18:08:069263 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079264 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:009265
Ryan Sleevib8d7ea02018-05-07 20:01:019266 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:079267 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:009268
[email protected]49639fa2011-12-20 23:22:419269 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:009270
danakj1fd259a02016-04-16 03:17:099271 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169272 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009273
tfarina42834112016-09-22 13:38:209274 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009275
robpercival214763f2016-07-01 23:27:019276 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9277 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009278
bnc691fda62016-08-12 00:43:169279 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529280 ASSERT_TRUE(response);
9281 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009282 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9283
[email protected]90499482013-06-01 00:39:509284 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009285
9286 std::string response_data;
bnc691fda62016-08-12 00:43:169287 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019288 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009289 EXPECT_EQ("hello world", response_data);
9290
9291 // Empty the current queue. This is necessary because idle sockets are
9292 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559293 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009294
9295 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239296 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009297}
9298
9299// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
9300// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:019301TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:009302 HttpRequestInfo request;
9303 request.method = "GET";
bncce36dca22015-04-21 22:11:239304 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109305 request.traffic_annotation =
9306 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:009307
9308 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239309 MockWrite(
9310 "GET / HTTP/1.1\r\n"
9311 "Host: www.example.org\r\n"
9312 "Connection: keep-alive\r\n\r\n"),
9313 MockWrite(
9314 "GET / HTTP/1.1\r\n"
9315 "Host: www.example.org\r\n"
9316 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:009317 };
9318
9319 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:429320 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9321 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:009322
[email protected]8ddf8322012-02-23 18:08:069323 SSLSocketDataProvider ssl(ASYNC, OK);
9324 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079325 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9326 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:009327
Ryan Sleevib8d7ea02018-05-07 20:01:019328 StaticSocketDataProvider data(data_reads, data_writes);
9329 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:079330 session_deps_.socket_factory->AddSocketDataProvider(&data);
9331 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:009332
[email protected]49639fa2011-12-20 23:22:419333 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:009334
danakj1fd259a02016-04-16 03:17:099335 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:589336 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199337 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009338
tfarina42834112016-09-22 13:38:209339 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009340
robpercival214763f2016-07-01 23:27:019341 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9342 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009343
9344 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529345 ASSERT_TRUE(response);
9346 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009347 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9348
[email protected]90499482013-06-01 00:39:509349 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009350
9351 std::string response_data;
9352 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019353 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009354 EXPECT_EQ("hello world", response_data);
9355
9356 // Empty the current queue. This is necessary because idle sockets are
9357 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559358 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009359
9360 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239361 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009362
9363 // Now start the second transaction, which should reuse the previous socket.
9364
bnc87dcefc2017-05-25 12:47:589365 trans =
Jeremy Roman0579ed62017-08-29 15:56:199366 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:009367
tfarina42834112016-09-22 13:38:209368 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:009369
robpercival214763f2016-07-01 23:27:019370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9371 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:009372
9373 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529374 ASSERT_TRUE(response);
9375 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:009376 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9377
[email protected]90499482013-06-01 00:39:509378 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009379
9380 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019381 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:009382 EXPECT_EQ("hello world", response_data);
9383
9384 // Empty the current queue. This is necessary because idle sockets are
9385 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559386 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:009387
9388 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239389 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:009390}
9391
maksim.sisov0adf8592016-07-15 06:25:569392// Grab a socket, use it, and put it back into the pool. Then, make
9393// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019394TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569395 HttpRequestInfo request;
9396 request.method = "GET";
9397 request.url = GURL("http://www.example.org/");
9398 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109399 request.traffic_annotation =
9400 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569401
9402 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9403
bnc691fda62016-08-12 00:43:169404 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569405
9406 MockRead data_reads[] = {
9407 // A part of the response body is received with the response headers.
9408 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9409 // The rest of the response body is received in two parts.
9410 MockRead("lo"), MockRead(" world"),
9411 MockRead("junk"), // Should not be read!!
9412 MockRead(SYNCHRONOUS, OK),
9413 };
9414
Ryan Sleevib8d7ea02018-05-07 20:01:019415 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:569416 session_deps_.socket_factory->AddSocketDataProvider(&data);
9417
9418 TestCompletionCallback callback;
9419
tfarina42834112016-09-22 13:38:209420 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569421 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9422
9423 EXPECT_THAT(callback.GetResult(rv), IsOk());
9424
bnc691fda62016-08-12 00:43:169425 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569426 ASSERT_TRUE(response);
9427 EXPECT_TRUE(response->headers);
9428 std::string status_line = response->headers->GetStatusLine();
9429 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9430
9431 // Make memory critical notification and ensure the transaction still has been
9432 // operating right.
9433 base::MemoryPressureListener::NotifyMemoryPressure(
9434 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9435 base::RunLoop().RunUntilIdle();
9436
9437 // Socket should not be flushed as long as it is not idle.
9438 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9439
9440 std::string response_data;
bnc691fda62016-08-12 00:43:169441 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569442 EXPECT_THAT(rv, IsOk());
9443 EXPECT_EQ("hello world", response_data);
9444
9445 // Empty the current queue. This is necessary because idle sockets are
9446 // added to the connection pool asynchronously with a PostTask.
9447 base::RunLoop().RunUntilIdle();
9448
9449 // We now check to make sure the socket was added back to the pool.
9450 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9451
9452 // Idle sockets should be flushed now.
9453 base::MemoryPressureListener::NotifyMemoryPressure(
9454 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9455 base::RunLoop().RunUntilIdle();
9456
9457 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9458}
9459
yucliu48f235d2018-01-11 00:59:559460// Disable idle socket closing on memory pressure.
9461// Grab a socket, use it, and put it back into the pool. Then, make
9462// low memory notification and ensure the socket pool is NOT flushed.
9463TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
9464 HttpRequestInfo request;
9465 request.method = "GET";
9466 request.url = GURL("http://www.example.org/");
9467 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109468 request.traffic_annotation =
9469 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:559470
9471 // Disable idle socket closing on memory pressure.
9472 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
9473 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9474
9475 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9476
9477 MockRead data_reads[] = {
9478 // A part of the response body is received with the response headers.
9479 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
9480 // The rest of the response body is received in two parts.
9481 MockRead("lo"), MockRead(" world"),
9482 MockRead("junk"), // Should not be read!!
9483 MockRead(SYNCHRONOUS, OK),
9484 };
9485
Ryan Sleevib8d7ea02018-05-07 20:01:019486 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:559487 session_deps_.socket_factory->AddSocketDataProvider(&data);
9488
9489 TestCompletionCallback callback;
9490
9491 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9492 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9493
9494 EXPECT_THAT(callback.GetResult(rv), IsOk());
9495
9496 const HttpResponseInfo* response = trans.GetResponseInfo();
9497 ASSERT_TRUE(response);
9498 EXPECT_TRUE(response->headers);
9499 std::string status_line = response->headers->GetStatusLine();
9500 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
9501
9502 // Make memory critical notification and ensure the transaction still has been
9503 // operating right.
9504 base::MemoryPressureListener::NotifyMemoryPressure(
9505 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9506 base::RunLoop().RunUntilIdle();
9507
9508 // Socket should not be flushed as long as it is not idle.
9509 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
9510
9511 std::string response_data;
9512 rv = ReadTransaction(&trans, &response_data);
9513 EXPECT_THAT(rv, IsOk());
9514 EXPECT_EQ("hello world", response_data);
9515
9516 // Empty the current queue. This is necessary because idle sockets are
9517 // added to the connection pool asynchronously with a PostTask.
9518 base::RunLoop().RunUntilIdle();
9519
9520 // We now check to make sure the socket was added back to the pool.
9521 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9522
9523 // Idle sockets should NOT be flushed on moderate memory pressure.
9524 base::MemoryPressureListener::NotifyMemoryPressure(
9525 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
9526 base::RunLoop().RunUntilIdle();
9527
9528 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9529
9530 // Idle sockets should NOT be flushed on critical memory pressure.
9531 base::MemoryPressureListener::NotifyMemoryPressure(
9532 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9533 base::RunLoop().RunUntilIdle();
9534
9535 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
9536}
9537
maksim.sisov0adf8592016-07-15 06:25:569538// Grab an SSL socket, use it, and put it back into the pool. Then, make
9539// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:019540TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:569541 HttpRequestInfo request;
9542 request.method = "GET";
9543 request.url = GURL("https://www.example.org/");
9544 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109545 request.traffic_annotation =
9546 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:569547
9548 MockWrite data_writes[] = {
9549 MockWrite("GET / HTTP/1.1\r\n"
9550 "Host: www.example.org\r\n"
9551 "Connection: keep-alive\r\n\r\n"),
9552 };
9553
9554 MockRead data_reads[] = {
9555 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
9556 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
9557
9558 SSLSocketDataProvider ssl(ASYNC, OK);
9559 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9560
Ryan Sleevib8d7ea02018-05-07 20:01:019561 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:569562 session_deps_.socket_factory->AddSocketDataProvider(&data);
9563
9564 TestCompletionCallback callback;
9565
9566 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169567 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:569568
Matt Menke9d5e2c92019-02-05 01:42:239569 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:209570 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:569571
9572 EXPECT_THAT(callback.GetResult(rv), IsOk());
9573
bnc691fda62016-08-12 00:43:169574 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:569575 ASSERT_TRUE(response);
9576 ASSERT_TRUE(response->headers);
9577 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9578
9579 // Make memory critical notification and ensure the transaction still has been
9580 // operating right.
9581 base::MemoryPressureListener::NotifyMemoryPressure(
9582 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9583 base::RunLoop().RunUntilIdle();
9584
Matt Menke9d5e2c92019-02-05 01:42:239585 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569586
9587 std::string response_data;
bnc691fda62016-08-12 00:43:169588 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:569589 EXPECT_THAT(rv, IsOk());
9590 EXPECT_EQ("hello world", response_data);
9591
9592 // Empty the current queue. This is necessary because idle sockets are
9593 // added to the connection pool asynchronously with a PostTask.
9594 base::RunLoop().RunUntilIdle();
9595
9596 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:239597 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569598
9599 // Make memory notification once again and ensure idle socket is closed.
9600 base::MemoryPressureListener::NotifyMemoryPressure(
9601 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
9602 base::RunLoop().RunUntilIdle();
9603
Matt Menke9d5e2c92019-02-05 01:42:239604 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:569605}
9606
[email protected]b4404c02009-04-10 16:38:529607// Make sure that we recycle a socket after a zero-length response.
9608// http://crbug.com/9880
bncd16676a2016-07-20 16:23:019609TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:429610 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:529611 request.method = "GET";
bncce36dca22015-04-21 22:11:239612 request.url = GURL(
9613 "http://www.example.org/csi?v=3&s=web&action=&"
9614 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
9615 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
9616 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e62018-02-07 07:41:109617 request.traffic_annotation =
9618 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:529619
danakj1fd259a02016-04-16 03:17:099620 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279621
[email protected]b4404c02009-04-10 16:38:529622 MockRead data_reads[] = {
9623 MockRead("HTTP/1.1 204 No Content\r\n"
9624 "Content-Length: 0\r\n"
9625 "Content-Type: text/html\r\n\r\n"),
9626 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:069627 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:529628 };
9629
Ryan Sleevib8d7ea02018-05-07 20:01:019630 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:079631 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:529632
mmenkecc2298e2015-12-07 18:20:189633 // Transaction must be created after the MockReads, so it's destroyed before
9634 // them.
bnc691fda62016-08-12 00:43:169635 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:189636
[email protected]49639fa2011-12-20 23:22:419637 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:529638
tfarina42834112016-09-22 13:38:209639 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019640 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:529641
9642 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019643 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529644
bnc691fda62016-08-12 00:43:169645 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529646 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:529647
wezca1070932016-05-26 20:30:529648 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:529649 std::string status_line = response->headers->GetStatusLine();
9650 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
9651
[email protected]90499482013-06-01 00:39:509652 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529653
9654 std::string response_data;
bnc691fda62016-08-12 00:43:169655 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019656 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:529657 EXPECT_EQ("", response_data);
9658
9659 // Empty the current queue. This is necessary because idle sockets are
9660 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:559661 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:529662
9663 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:509664 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:529665}
9666
bncd16676a2016-07-20 16:23:019667TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:099668 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:229669 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:199670 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:229671 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279672
[email protected]1c773ea12009-04-28 19:58:429673 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:519674 // Transaction 1: a GET request that succeeds. The socket is recycled
9675 // after use.
9676 request[0].method = "GET";
9677 request[0].url = GURL("http://www.google.com/");
9678 request[0].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109679 request[0].traffic_annotation =
9680 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519681 // Transaction 2: a POST request. Reuses the socket kept alive from
9682 // transaction 1. The first attempts fails when writing the POST data.
9683 // This causes the transaction to retry with a new socket. The second
9684 // attempt succeeds.
9685 request[1].method = "POST";
9686 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:279687 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:519688 request[1].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:109689 request[1].traffic_annotation =
9690 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:519691
danakj1fd259a02016-04-16 03:17:099692 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:519693
9694 // The first socket is used for transaction 1 and the first attempt of
9695 // transaction 2.
9696
9697 // The response of transaction 1.
9698 MockRead data_reads1[] = {
9699 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
9700 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069701 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519702 };
9703 // The mock write results of transaction 1 and the first attempt of
9704 // transaction 2.
9705 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:069706 MockWrite(SYNCHRONOUS, 64), // GET
9707 MockWrite(SYNCHRONOUS, 93), // POST
9708 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:519709 };
Ryan Sleevib8d7ea02018-05-07 20:01:019710 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:519711
9712 // The second socket is used for the second attempt of transaction 2.
9713
9714 // The response of transaction 2.
9715 MockRead data_reads2[] = {
9716 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
9717 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:069718 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:519719 };
9720 // The mock write results of the second attempt of transaction 2.
9721 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:069722 MockWrite(SYNCHRONOUS, 93), // POST
9723 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:519724 };
Ryan Sleevib8d7ea02018-05-07 20:01:019725 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:519726
[email protected]bb88e1d32013-05-03 23:11:079727 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9728 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:519729
thestig9d3bb0c2015-01-24 00:49:519730 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:519731 "hello world", "welcome"
9732 };
9733
9734 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:169735 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:519736
[email protected]49639fa2011-12-20 23:22:419737 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:519738
tfarina42834112016-09-22 13:38:209739 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019740 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:519741
9742 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019743 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519744
bnc691fda62016-08-12 00:43:169745 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529746 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:519747
wezca1070932016-05-26 20:30:529748 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:519749 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9750
9751 std::string response_data;
bnc691fda62016-08-12 00:43:169752 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:019753 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:519754 EXPECT_EQ(kExpectedResponseData[i], response_data);
9755 }
9756}
[email protected]f9ee6b52008-11-08 06:46:239757
9758// Test the request-challenge-retry sequence for basic auth when there is
9759// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:169760// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:019761TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:429762 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239763 request.method = "GET";
bncce36dca22015-04-21 22:11:239764 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:419765 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:109766 request.traffic_annotation =
9767 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:299768
danakj1fd259a02016-04-16 03:17:099769 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169770 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279771
[email protected]a97cca42009-08-14 01:00:299772 // The password contains an escaped character -- for this test to pass it
9773 // will need to be unescaped by HttpNetworkTransaction.
9774 EXPECT_EQ("b%40r", request.url.password());
9775
[email protected]f9ee6b52008-11-08 06:46:239776 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239777 MockWrite(
9778 "GET / HTTP/1.1\r\n"
9779 "Host: www.example.org\r\n"
9780 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239781 };
9782
9783 MockRead data_reads1[] = {
9784 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9785 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9786 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069787 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239788 };
9789
[email protected]2262e3a2012-05-22 16:08:169790 // After the challenge above, the transaction will be restarted using the
9791 // identity from the url (foo, b@r) to answer the challenge.
9792 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239793 MockWrite(
9794 "GET / HTTP/1.1\r\n"
9795 "Host: www.example.org\r\n"
9796 "Connection: keep-alive\r\n"
9797 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169798 };
9799
9800 MockRead data_reads2[] = {
9801 MockRead("HTTP/1.0 200 OK\r\n"),
9802 MockRead("Content-Length: 100\r\n\r\n"),
9803 MockRead(SYNCHRONOUS, OK),
9804 };
9805
Ryan Sleevib8d7ea02018-05-07 20:01:019806 StaticSocketDataProvider data1(data_reads1, data_writes1);
9807 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079808 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9809 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239810
[email protected]49639fa2011-12-20 23:22:419811 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209812 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019813 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239814 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019815 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169816 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169817
9818 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169819 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019820 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169821 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019822 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169823 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229824
bnc691fda62016-08-12 00:43:169825 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529826 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169827
9828 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:589829 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169830
9831 EXPECT_EQ(100, response->headers->GetContentLength());
9832
9833 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559834 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:169835}
9836
9837// Test the request-challenge-retry sequence for basic auth when there is an
9838// incorrect identity in the URL. The identity from the URL should be used only
9839// once.
bncd16676a2016-07-20 16:23:019840TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:169841 HttpRequestInfo request;
9842 request.method = "GET";
9843 // Note: the URL has a username:password in it. The password "baz" is
9844 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:239845 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:169846
9847 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:109848 request.traffic_annotation =
9849 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:169850
danakj1fd259a02016-04-16 03:17:099851 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169852 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:169853
9854 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239855 MockWrite(
9856 "GET / HTTP/1.1\r\n"
9857 "Host: www.example.org\r\n"
9858 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169859 };
9860
9861 MockRead data_reads1[] = {
9862 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9863 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9864 MockRead("Content-Length: 10\r\n\r\n"),
9865 MockRead(SYNCHRONOUS, ERR_FAILED),
9866 };
9867
9868 // After the challenge above, the transaction will be restarted using the
9869 // identity from the url (foo, baz) to answer the challenge.
9870 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239871 MockWrite(
9872 "GET / HTTP/1.1\r\n"
9873 "Host: www.example.org\r\n"
9874 "Connection: keep-alive\r\n"
9875 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169876 };
9877
9878 MockRead data_reads2[] = {
9879 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9880 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9881 MockRead("Content-Length: 10\r\n\r\n"),
9882 MockRead(SYNCHRONOUS, ERR_FAILED),
9883 };
9884
9885 // After the challenge above, the transaction will be restarted using the
9886 // identity supplied by the user (foo, bar) to answer the challenge.
9887 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239888 MockWrite(
9889 "GET / HTTP/1.1\r\n"
9890 "Host: www.example.org\r\n"
9891 "Connection: keep-alive\r\n"
9892 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:169893 };
9894
9895 MockRead data_reads3[] = {
9896 MockRead("HTTP/1.0 200 OK\r\n"),
9897 MockRead("Content-Length: 100\r\n\r\n"),
9898 MockRead(SYNCHRONOUS, OK),
9899 };
9900
Ryan Sleevib8d7ea02018-05-07 20:01:019901 StaticSocketDataProvider data1(data_reads1, data_writes1);
9902 StaticSocketDataProvider data2(data_reads2, data_writes2);
9903 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079904 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9905 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9906 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:169907
9908 TestCompletionCallback callback1;
9909
tfarina42834112016-09-22 13:38:209910 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019911 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169912
9913 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019914 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:169915
bnc691fda62016-08-12 00:43:169916 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169917 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169918 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169920 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019921 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169922 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169923
bnc691fda62016-08-12 00:43:169924 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529925 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589926 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:169927
9928 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:169929 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:019930 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:169931 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019932 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169933 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:169934
bnc691fda62016-08-12 00:43:169935 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529936 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:169937
9938 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:589939 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:169940
9941 EXPECT_EQ(100, response->headers->GetContentLength());
9942
[email protected]ea9dc9a2009-09-05 00:43:329943 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:559944 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:329945}
9946
[email protected]2217aa22013-10-11 03:03:549947
9948// Test the request-challenge-retry sequence for basic auth when there is a
9949// correct identity in the URL, but its use is being suppressed. The identity
9950// from the URL should never be used.
bncd16676a2016-07-20 16:23:019951TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:549952 HttpRequestInfo request;
9953 request.method = "GET";
bncce36dca22015-04-21 22:11:239954 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:549955 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e62018-02-07 07:41:109956 request.traffic_annotation =
9957 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:549958
danakj1fd259a02016-04-16 03:17:099959 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169960 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:549961
9962 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239963 MockWrite(
9964 "GET / HTTP/1.1\r\n"
9965 "Host: www.example.org\r\n"
9966 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549967 };
9968
9969 MockRead data_reads1[] = {
9970 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9971 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9972 MockRead("Content-Length: 10\r\n\r\n"),
9973 MockRead(SYNCHRONOUS, ERR_FAILED),
9974 };
9975
9976 // After the challenge above, the transaction will be restarted using the
9977 // identity supplied by the user, not the one in the URL, to answer the
9978 // challenge.
9979 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239980 MockWrite(
9981 "GET / HTTP/1.1\r\n"
9982 "Host: www.example.org\r\n"
9983 "Connection: keep-alive\r\n"
9984 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:549985 };
9986
9987 MockRead data_reads3[] = {
9988 MockRead("HTTP/1.0 200 OK\r\n"),
9989 MockRead("Content-Length: 100\r\n\r\n"),
9990 MockRead(SYNCHRONOUS, OK),
9991 };
9992
Ryan Sleevib8d7ea02018-05-07 20:01:019993 StaticSocketDataProvider data1(data_reads1, data_writes1);
9994 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:549995 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9996 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9997
9998 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:209999 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110000 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:5410001 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110002 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610003 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:5410004
bnc691fda62016-08-12 00:43:1610005 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210006 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810007 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:5410008
10009 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1610010 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:0110011 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:5410012 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110013 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610014 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:5410015
bnc691fda62016-08-12 00:43:1610016 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210017 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:5410018
10019 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:5810020 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:5410021 EXPECT_EQ(100, response->headers->GetContentLength());
10022
10023 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:5510024 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:5410025}
10026
[email protected]f9ee6b52008-11-08 06:46:2310027// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:0110028TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:0910029 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:2310030
10031 // Transaction 1: authenticate (foo, bar) on MyRealm1
10032 {
[email protected]1c773ea12009-04-28 19:58:4210033 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310034 request.method = "GET";
bncce36dca22015-04-21 22:11:2310035 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:1010036 request.traffic_annotation =
10037 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310038
bnc691fda62016-08-12 00:43:1610039 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710040
[email protected]f9ee6b52008-11-08 06:46:2310041 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310042 MockWrite(
10043 "GET /x/y/z HTTP/1.1\r\n"
10044 "Host: www.example.org\r\n"
10045 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310046 };
10047
10048 MockRead data_reads1[] = {
10049 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10050 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10051 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610052 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310053 };
10054
10055 // Resend with authorization (username=foo, password=bar)
10056 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310057 MockWrite(
10058 "GET /x/y/z HTTP/1.1\r\n"
10059 "Host: www.example.org\r\n"
10060 "Connection: keep-alive\r\n"
10061 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310062 };
10063
10064 // Sever accepts the authorization.
10065 MockRead data_reads2[] = {
10066 MockRead("HTTP/1.0 200 OK\r\n"),
10067 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610068 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310069 };
10070
Ryan Sleevib8d7ea02018-05-07 20:01:0110071 StaticSocketDataProvider data1(data_reads1, data_writes1);
10072 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710073 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10074 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310075
[email protected]49639fa2011-12-20 23:22:4110076 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310077
tfarina42834112016-09-22 13:38:2010078 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110079 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310080
10081 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110082 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310083
bnc691fda62016-08-12 00:43:1610084 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210085 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810086 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:2310087
[email protected]49639fa2011-12-20 23:22:4110088 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:2310089
bnc691fda62016-08-12 00:43:1610090 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10091 callback2.callback());
robpercival214763f2016-07-01 23:27:0110092 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310093
10094 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110095 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310096
bnc691fda62016-08-12 00:43:1610097 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210098 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810099 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310100 EXPECT_EQ(100, response->headers->GetContentLength());
10101 }
10102
10103 // ------------------------------------------------------------------------
10104
10105 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
10106 {
[email protected]1c773ea12009-04-28 19:58:4210107 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310108 request.method = "GET";
10109 // Note that Transaction 1 was at /x/y/z, so this is in the same
10110 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:2310111 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:1010112 request.traffic_annotation =
10113 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310114
bnc691fda62016-08-12 00:43:1610115 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710116
[email protected]f9ee6b52008-11-08 06:46:2310117 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310118 MockWrite(
10119 "GET /x/y/a/b HTTP/1.1\r\n"
10120 "Host: www.example.org\r\n"
10121 "Connection: keep-alive\r\n"
10122 // Send preemptive authorization for MyRealm1
10123 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310124 };
10125
10126 // The server didn't like the preemptive authorization, and
10127 // challenges us for a different realm (MyRealm2).
10128 MockRead data_reads1[] = {
10129 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10130 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
10131 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610132 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310133 };
10134
10135 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
10136 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310137 MockWrite(
10138 "GET /x/y/a/b HTTP/1.1\r\n"
10139 "Host: www.example.org\r\n"
10140 "Connection: keep-alive\r\n"
10141 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310142 };
10143
10144 // Sever accepts the authorization.
10145 MockRead data_reads2[] = {
10146 MockRead("HTTP/1.0 200 OK\r\n"),
10147 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610148 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310149 };
10150
Ryan Sleevib8d7ea02018-05-07 20:01:0110151 StaticSocketDataProvider data1(data_reads1, data_writes1);
10152 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710153 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10154 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310155
[email protected]49639fa2011-12-20 23:22:4110156 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310157
tfarina42834112016-09-22 13:38:2010158 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110159 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310160
10161 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110162 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310163
bnc691fda62016-08-12 00:43:1610164 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210165 ASSERT_TRUE(response);
10166 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:0410167 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:4310168 EXPECT_EQ("http://www.example.org",
10169 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0410170 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:1910171 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:2310172
[email protected]49639fa2011-12-20 23:22:4110173 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:2310174
bnc691fda62016-08-12 00:43:1610175 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
10176 callback2.callback());
robpercival214763f2016-07-01 23:27:0110177 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310178
10179 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110180 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310181
bnc691fda62016-08-12 00:43:1610182 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210183 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810184 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310185 EXPECT_EQ(100, response->headers->GetContentLength());
10186 }
10187
10188 // ------------------------------------------------------------------------
10189
10190 // Transaction 3: Resend a request in MyRealm's protection space --
10191 // succeed with preemptive authorization.
10192 {
[email protected]1c773ea12009-04-28 19:58:4210193 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310194 request.method = "GET";
bncce36dca22015-04-21 22:11:2310195 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e62018-02-07 07:41:1010196 request.traffic_annotation =
10197 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310198
bnc691fda62016-08-12 00:43:1610199 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710200
[email protected]f9ee6b52008-11-08 06:46:2310201 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310202 MockWrite(
10203 "GET /x/y/z2 HTTP/1.1\r\n"
10204 "Host: www.example.org\r\n"
10205 "Connection: keep-alive\r\n"
10206 // The authorization for MyRealm1 gets sent preemptively
10207 // (since the url is in the same protection space)
10208 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310209 };
10210
10211 // Sever accepts the preemptive authorization
10212 MockRead data_reads1[] = {
10213 MockRead("HTTP/1.0 200 OK\r\n"),
10214 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610215 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310216 };
10217
Ryan Sleevib8d7ea02018-05-07 20:01:0110218 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710219 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:2310220
[email protected]49639fa2011-12-20 23:22:4110221 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310222
tfarina42834112016-09-22 13:38:2010223 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110224 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310225
10226 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110227 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310228
bnc691fda62016-08-12 00:43:1610229 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210230 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:2310231
Emily Starkf2c9bbd2019-04-09 17:08:5810232 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310233 EXPECT_EQ(100, response->headers->GetContentLength());
10234 }
10235
10236 // ------------------------------------------------------------------------
10237
10238 // Transaction 4: request another URL in MyRealm (however the
10239 // url is not known to belong to the protection space, so no pre-auth).
10240 {
[email protected]1c773ea12009-04-28 19:58:4210241 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310242 request.method = "GET";
bncce36dca22015-04-21 22:11:2310243 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e62018-02-07 07:41:1010244 request.traffic_annotation =
10245 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310246
bnc691fda62016-08-12 00:43:1610247 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710248
[email protected]f9ee6b52008-11-08 06:46:2310249 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310250 MockWrite(
10251 "GET /x/1 HTTP/1.1\r\n"
10252 "Host: www.example.org\r\n"
10253 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310254 };
10255
10256 MockRead data_reads1[] = {
10257 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10258 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10259 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610260 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310261 };
10262
10263 // Resend with authorization from MyRealm's cache.
10264 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310265 MockWrite(
10266 "GET /x/1 HTTP/1.1\r\n"
10267 "Host: www.example.org\r\n"
10268 "Connection: keep-alive\r\n"
10269 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310270 };
10271
10272 // Sever accepts the authorization.
10273 MockRead data_reads2[] = {
10274 MockRead("HTTP/1.0 200 OK\r\n"),
10275 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610276 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310277 };
10278
Ryan Sleevib8d7ea02018-05-07 20:01:0110279 StaticSocketDataProvider data1(data_reads1, data_writes1);
10280 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710281 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10282 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:2310283
[email protected]49639fa2011-12-20 23:22:4110284 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310285
tfarina42834112016-09-22 13:38:2010286 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110287 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310288
10289 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110290 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310291
bnc691fda62016-08-12 00:43:1610292 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110293 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610294 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110295 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210296 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110297 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610298 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210299
bnc691fda62016-08-12 00:43:1610300 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210301 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810302 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310303 EXPECT_EQ(100, response->headers->GetContentLength());
10304 }
10305
10306 // ------------------------------------------------------------------------
10307
10308 // Transaction 5: request a URL in MyRealm, but the server rejects the
10309 // cached identity. Should invalidate and re-prompt.
10310 {
[email protected]1c773ea12009-04-28 19:58:4210311 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:2310312 request.method = "GET";
bncce36dca22015-04-21 22:11:2310313 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e62018-02-07 07:41:1010314 request.traffic_annotation =
10315 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:2310316
bnc691fda62016-08-12 00:43:1610317 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710318
[email protected]f9ee6b52008-11-08 06:46:2310319 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310320 MockWrite(
10321 "GET /p/q/t HTTP/1.1\r\n"
10322 "Host: www.example.org\r\n"
10323 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310324 };
10325
10326 MockRead data_reads1[] = {
10327 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10328 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10329 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610330 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310331 };
10332
10333 // Resend with authorization from cache for MyRealm.
10334 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310335 MockWrite(
10336 "GET /p/q/t HTTP/1.1\r\n"
10337 "Host: www.example.org\r\n"
10338 "Connection: keep-alive\r\n"
10339 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310340 };
10341
10342 // Sever rejects the authorization.
10343 MockRead data_reads2[] = {
10344 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10345 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10346 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610347 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:2310348 };
10349
10350 // At this point we should prompt for new credentials for MyRealm.
10351 // Restart with username=foo3, password=foo4.
10352 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2310353 MockWrite(
10354 "GET /p/q/t HTTP/1.1\r\n"
10355 "Host: www.example.org\r\n"
10356 "Connection: keep-alive\r\n"
10357 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:2310358 };
10359
10360 // Sever accepts the authorization.
10361 MockRead data_reads3[] = {
10362 MockRead("HTTP/1.0 200 OK\r\n"),
10363 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610364 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:2310365 };
10366
Ryan Sleevib8d7ea02018-05-07 20:01:0110367 StaticSocketDataProvider data1(data_reads1, data_writes1);
10368 StaticSocketDataProvider data2(data_reads2, data_writes2);
10369 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:0710370 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10371 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10372 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:2310373
[email protected]49639fa2011-12-20 23:22:4110374 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:2310375
tfarina42834112016-09-22 13:38:2010376 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110377 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310378
10379 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110380 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310381
bnc691fda62016-08-12 00:43:1610382 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:4110383 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1610384 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:0110385 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:2210386 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110387 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610388 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:2210389
bnc691fda62016-08-12 00:43:1610390 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210391 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810392 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:2310393
[email protected]49639fa2011-12-20 23:22:4110394 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:2310395
bnc691fda62016-08-12 00:43:1610396 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
10397 callback3.callback());
robpercival214763f2016-07-01 23:27:0110398 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:2310399
[email protected]0757e7702009-03-27 04:00:2210400 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0110401 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:2310402
bnc691fda62016-08-12 00:43:1610403 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210404 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810405 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:2310406 EXPECT_EQ(100, response->headers->GetContentLength());
10407 }
10408}
[email protected]89ceba9a2009-03-21 03:46:0610409
[email protected]3c32c5f2010-05-18 15:18:1210410// Tests that nonce count increments when multiple auth attempts
10411// are started with the same nonce.
bncd16676a2016-07-20 16:23:0110412TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:4410413 HttpAuthHandlerDigest::Factory* digest_factory =
10414 new HttpAuthHandlerDigest::Factory();
10415 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
10416 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
10417 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:0710418 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:0910419 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:1210420
10421 // Transaction 1: authenticate (foo, bar) on MyRealm1
10422 {
[email protected]3c32c5f2010-05-18 15:18:1210423 HttpRequestInfo request;
10424 request.method = "GET";
bncce36dca22015-04-21 22:11:2310425 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:1010426 request.traffic_annotation =
10427 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210428
bnc691fda62016-08-12 00:43:1610429 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710430
[email protected]3c32c5f2010-05-18 15:18:1210431 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310432 MockWrite(
10433 "GET /x/y/z HTTP/1.1\r\n"
10434 "Host: www.example.org\r\n"
10435 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210436 };
10437
10438 MockRead data_reads1[] = {
10439 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
10440 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
10441 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610442 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210443 };
10444
10445 // Resend with authorization (username=foo, password=bar)
10446 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2310447 MockWrite(
10448 "GET /x/y/z HTTP/1.1\r\n"
10449 "Host: www.example.org\r\n"
10450 "Connection: keep-alive\r\n"
10451 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10452 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
10453 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
10454 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210455 };
10456
10457 // Sever accepts the authorization.
10458 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:0810459 MockRead("HTTP/1.0 200 OK\r\n"),
10460 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210461 };
10462
Ryan Sleevib8d7ea02018-05-07 20:01:0110463 StaticSocketDataProvider data1(data_reads1, data_writes1);
10464 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0710465 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10466 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:1210467
[email protected]49639fa2011-12-20 23:22:4110468 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210469
tfarina42834112016-09-22 13:38:2010470 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110471 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210472
10473 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110474 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210475
bnc691fda62016-08-12 00:43:1610476 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210477 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810478 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:1210479
[email protected]49639fa2011-12-20 23:22:4110480 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:1210481
bnc691fda62016-08-12 00:43:1610482 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
10483 callback2.callback());
robpercival214763f2016-07-01 23:27:0110484 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210485
10486 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110487 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210488
bnc691fda62016-08-12 00:43:1610489 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210490 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810491 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210492 }
10493
10494 // ------------------------------------------------------------------------
10495
10496 // Transaction 2: Request another resource in digestive's protection space.
10497 // This will preemptively add an Authorization header which should have an
10498 // "nc" value of 2 (as compared to 1 in the first use.
10499 {
[email protected]3c32c5f2010-05-18 15:18:1210500 HttpRequestInfo request;
10501 request.method = "GET";
10502 // Note that Transaction 1 was at /x/y/z, so this is in the same
10503 // protection space as digest.
bncce36dca22015-04-21 22:11:2310504 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:1010505 request.traffic_annotation =
10506 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:1210507
bnc691fda62016-08-12 00:43:1610508 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710509
[email protected]3c32c5f2010-05-18 15:18:1210510 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2310511 MockWrite(
10512 "GET /x/y/a/b HTTP/1.1\r\n"
10513 "Host: www.example.org\r\n"
10514 "Connection: keep-alive\r\n"
10515 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
10516 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
10517 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
10518 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:1210519 };
10520
10521 // Sever accepts the authorization.
10522 MockRead data_reads1[] = {
10523 MockRead("HTTP/1.0 200 OK\r\n"),
10524 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610525 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:1210526 };
10527
Ryan Sleevib8d7ea02018-05-07 20:01:0110528 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0710529 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:1210530
[email protected]49639fa2011-12-20 23:22:4110531 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:1210532
tfarina42834112016-09-22 13:38:2010533 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110534 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:1210535
10536 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110537 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:1210538
bnc691fda62016-08-12 00:43:1610539 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210540 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5810541 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:1210542 }
10543}
10544
[email protected]89ceba9a2009-03-21 03:46:0610545// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:0110546TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:0610547 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:0910548 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610549 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:0610550
10551 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:4410552 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:1610553 trans.read_buf_len_ = 15;
10554 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:0610555
10556 // Setup state in response_
bnc691fda62016-08-12 00:43:1610557 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:5810558 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:0810559 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:5710560 response->response_time = base::Time::Now();
10561 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:0610562
10563 { // Setup state for response_.vary_data
10564 HttpRequestInfo request;
10565 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
10566 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:2710567 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:4310568 request.extra_headers.SetHeader("Foo", "1");
10569 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:5010570 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:0610571 }
10572
10573 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:1610574 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:0610575
10576 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:1610577 EXPECT_FALSE(trans.read_buf_);
10578 EXPECT_EQ(0, trans.read_buf_len_);
10579 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:5810580 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:5210581 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:0410582 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:0810583 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:5710584 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:0610585}
10586
[email protected]bacff652009-03-31 17:50:3310587// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:0110588TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:3310589 HttpRequestInfo request;
10590 request.method = "GET";
bncce36dca22015-04-21 22:11:2310591 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010592 request.traffic_annotation =
10593 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310594
danakj1fd259a02016-04-16 03:17:0910595 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610596 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710597
[email protected]bacff652009-03-31 17:50:3310598 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310599 MockWrite(
10600 "GET / HTTP/1.1\r\n"
10601 "Host: www.example.org\r\n"
10602 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310603 };
10604
10605 MockRead data_reads[] = {
10606 MockRead("HTTP/1.0 200 OK\r\n"),
10607 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10608 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610609 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310610 };
10611
[email protected]5ecc992a42009-11-11 01:41:5910612 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:0110613 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610614 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10615 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310616
[email protected]bb88e1d32013-05-03 23:11:0710617 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10618 session_deps_.socket_factory->AddSocketDataProvider(&data);
10619 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10620 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310621
[email protected]49639fa2011-12-20 23:22:4110622 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310623
tfarina42834112016-09-22 13:38:2010624 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110625 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310626
10627 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110628 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310629
bnc691fda62016-08-12 00:43:1610630 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110631 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310632
10633 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110634 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310635
bnc691fda62016-08-12 00:43:1610636 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310637
wezca1070932016-05-26 20:30:5210638 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310639 EXPECT_EQ(100, response->headers->GetContentLength());
10640}
10641
10642// Test HTTPS connections to a site with a bad certificate, going through a
10643// proxy
bncd16676a2016-07-20 16:23:0110644TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5610645 session_deps_.proxy_resolution_service =
10646 ConfiguredProxyResolutionService::CreateFixed(
10647 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310648
10649 HttpRequestInfo request;
10650 request.method = "GET";
bncce36dca22015-04-21 22:11:2310651 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010652 request.traffic_annotation =
10653 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:3310654
10655 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710656 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10657 "Host: www.example.org:443\r\n"
10658 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310659 };
10660
10661 MockRead proxy_reads[] = {
10662 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610663 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:3310664 };
10665
10666 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710667 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10668 "Host: www.example.org:443\r\n"
10669 "Proxy-Connection: keep-alive\r\n\r\n"),
10670 MockWrite("GET / HTTP/1.1\r\n"
10671 "Host: www.example.org\r\n"
10672 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:3310673 };
10674
10675 MockRead data_reads[] = {
10676 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10677 MockRead("HTTP/1.0 200 OK\r\n"),
10678 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10679 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610680 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:3310681 };
10682
Ryan Sleevib8d7ea02018-05-07 20:01:0110683 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
10684 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610685 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10686 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:3310687
[email protected]bb88e1d32013-05-03 23:11:0710688 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10689 session_deps_.socket_factory->AddSocketDataProvider(&data);
10690 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
10691 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:3310692
[email protected]49639fa2011-12-20 23:22:4110693 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:3310694
10695 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:0710696 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:3310697
danakj1fd259a02016-04-16 03:17:0910698 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610699 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:3310700
tfarina42834112016-09-22 13:38:2010701 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110702 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310703
10704 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110705 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:3310706
bnc691fda62016-08-12 00:43:1610707 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110708 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:3310709
10710 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110711 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:3310712
bnc691fda62016-08-12 00:43:1610713 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:3310714
wezca1070932016-05-26 20:30:5210715 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:3310716 EXPECT_EQ(100, response->headers->GetContentLength());
10717 }
10718}
10719
[email protected]2df19bb2010-08-25 20:13:4610720
10721// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:0110722TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910723 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610724 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910725 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410726 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710727 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:4610728
10729 HttpRequestInfo request;
10730 request.method = "GET";
bncce36dca22015-04-21 22:11:2310731 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010732 request.traffic_annotation =
10733 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610734
10735 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710736 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10737 "Host: www.example.org:443\r\n"
10738 "Proxy-Connection: keep-alive\r\n\r\n"),
10739 MockWrite("GET / HTTP/1.1\r\n"
10740 "Host: www.example.org\r\n"
10741 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610742 };
10743
10744 MockRead data_reads[] = {
10745 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10746 MockRead("HTTP/1.1 200 OK\r\n"),
10747 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10748 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610749 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610750 };
10751
Ryan Sleevib8d7ea02018-05-07 20:01:0110752 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610753 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10754 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:4610755
[email protected]bb88e1d32013-05-03 23:11:0710756 session_deps_.socket_factory->AddSocketDataProvider(&data);
10757 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10758 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:4610759
[email protected]49639fa2011-12-20 23:22:4110760 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610761
danakj1fd259a02016-04-16 03:17:0910762 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610763 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610764
tfarina42834112016-09-22 13:38:2010765 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110766 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610767
10768 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110769 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1610770 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610771
wezca1070932016-05-26 20:30:5210772 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610773
tbansal2ecbbc72016-10-06 17:15:4710774 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:4610775 EXPECT_TRUE(response->headers->IsKeepAlive());
10776 EXPECT_EQ(200, response->headers->response_code());
10777 EXPECT_EQ(100, response->headers->GetContentLength());
10778 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2010779
10780 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610781 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010782 TestLoadTimingNotReusedWithPac(load_timing_info,
10783 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:4610784}
10785
Eric Roman695a7872019-04-16 21:53:2910786// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:0110787TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:5910788 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610789 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4910790 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410791 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710792 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:2910793
Matt Menkeecfecfc72019-02-05 19:15:2810794 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10795 session_deps_.host_resolver->set_ondemand_mode(true);
10796
[email protected]511f6f52010-12-17 03:58:2910797 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:1210798 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:2910799 request.method = "GET";
bncce36dca22015-04-21 22:11:2310800 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010801 request.traffic_annotation =
10802 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910803
10804 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810805 MockWrite(ASYNC, 0,
10806 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710807 "Host: www.example.org:443\r\n"
10808 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910809 };
10810
10811 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810812 // Pause on first read.
10813 MockRead(ASYNC, ERR_IO_PENDING, 1),
10814 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
10815 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
10816 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2910817 };
10818
Matt Menkeecfecfc72019-02-05 19:15:2810819 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610820 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2910821
[email protected]bb88e1d32013-05-03 23:11:0710822 session_deps_.socket_factory->AddSocketDataProvider(&data);
10823 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910824
[email protected]49639fa2011-12-20 23:22:4110825 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910826
danakj1fd259a02016-04-16 03:17:0910827 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610828 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910829
tfarina42834112016-09-22 13:38:2010830 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110831 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:2810832 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
10833
10834 // Host resolution takes |kTimeIncrement|.
10835 FastForwardBy(kTimeIncrement);
10836 // Resolving the current request with |ResolveNow| will cause the pending
10837 // request to instantly complete, and the async connect will start as well.
10838 session_deps_.host_resolver->ResolveOnlyRequestNow();
10839
10840 // Connecting takes |kTimeIncrement|.
10841 FastForwardBy(kTimeIncrement);
10842 data.RunUntilPaused();
10843
10844 // The server takes |kTimeIncrement| to respond.
10845 FastForwardBy(kTimeIncrement);
10846 data.Resume();
[email protected]511f6f52010-12-17 03:58:2910847
10848 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910849 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910850}
10851
Eric Roman74103c72019-02-21 00:23:1210852// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
10853TEST_F(HttpNetworkTransactionTest,
10854 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
10855 base::HistogramTester histograms;
10856 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610857 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Eric Roman74103c72019-02-21 00:23:1210858 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410859 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210860 session_deps_.net_log = &net_log;
10861
10862 HttpRequestInfo request;
10863 request.method = "GET";
10864 request.url = GURL("https://www.example.org/");
10865 request.traffic_annotation =
10866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10867
10868 MockWrite data_writes[] = {
10869 MockWrite(ASYNC, 0,
10870 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10871 "Host: www.example.org:443\r\n"
10872 "Proxy-Connection: keep-alive\r\n\r\n"),
10873 };
10874
10875 MockRead data_reads[] = {
10876 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10877 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10878 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10879 };
10880
10881 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10882 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10883
10884 session_deps_.socket_factory->AddSocketDataProvider(&data);
10885 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10886
10887 TestCompletionCallback callback;
10888
10889 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10890 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10891
10892 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10893 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10894
10895 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910896 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210897}
10898
10899// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
10900// request for main frames.
10901TEST_F(HttpNetworkTransactionTest,
10902 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
10903 base::HistogramTester histograms;
10904 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5610905 ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
Eric Roman74103c72019-02-21 00:23:1210906 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410907 RecordingTestNetLog net_log;
Eric Roman74103c72019-02-21 00:23:1210908 session_deps_.net_log = &net_log;
10909
10910 HttpRequestInfo request;
10911 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
10912 request.method = "GET";
10913 request.url = GURL("https://www.example.org/");
10914 request.traffic_annotation =
10915 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10916
10917 MockWrite data_writes[] = {
10918 MockWrite(ASYNC, 0,
10919 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10920 "Host: www.example.org:443\r\n"
10921 "Proxy-Connection: keep-alive\r\n\r\n"),
10922 };
10923
10924 MockRead data_reads[] = {
10925 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
10926 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
10927 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
10928 };
10929
10930 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
10931 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
10932
10933 session_deps_.socket_factory->AddSocketDataProvider(&data);
10934 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
10935
10936 TestCompletionCallback callback;
10937
10938 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10939 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10940
10941 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10942 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10943
10944 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5910945 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:1210946}
10947
Eric Roman695a7872019-04-16 21:53:2910948// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:1210949// frames.
bncd16676a2016-07-20 16:23:0110950TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:1210951 base::HistogramTester histograms;
Nicolas Arciniegad2013f92020-02-07 23:00:5610952 session_deps_.proxy_resolution_service =
10953 ConfiguredProxyResolutionService::CreateFixed(
10954 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1410955 RecordingTestNetLog net_log;
Matt Menkeecfecfc72019-02-05 19:15:2810956 session_deps_.net_log = &net_log;
10957
Matt Menkeecfecfc72019-02-05 19:15:2810958 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
10959 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:2910960
10961 HttpRequestInfo request;
10962 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:1210963 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:2310964 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010965 request.traffic_annotation =
10966 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2910967
Ryan Hamilton0239aac2018-05-19 00:03:1310968 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410969 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10970 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310971 spdy::SpdySerializedFrame goaway(
10972 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2910973 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110974 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:2810975 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:2910976 };
10977
10978 static const char* const kExtraHeaders[] = {
10979 "location",
10980 "http://login.example.com/",
10981 };
Ryan Hamilton0239aac2018-05-19 00:03:1310982 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410983 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:2910984 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:2810985 // Pause on first read.
10986 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
10987 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910988 };
10989
Matt Menkeecfecfc72019-02-05 19:15:2810990 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610991 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610992 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910993
[email protected]bb88e1d32013-05-03 23:11:0710994 session_deps_.socket_factory->AddSocketDataProvider(&data);
10995 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910996
[email protected]49639fa2011-12-20 23:22:4110997 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910998
danakj1fd259a02016-04-16 03:17:0910999 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611000 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911001
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));
Matt Menkeecfecfc72019-02-05 19:15:2811004 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:2911005
Matt Menkeecfecfc72019-02-05 19:15:2811006 // Host resolution takes |kTimeIncrement|.
11007 FastForwardBy(kTimeIncrement);
11008 // Resolving the current request with |ResolveNow| will cause the pending
11009 // request to instantly complete, and the async connect will start as well.
11010 session_deps_.host_resolver->ResolveOnlyRequestNow();
11011
11012 // Connecting takes |kTimeIncrement|.
11013 FastForwardBy(kTimeIncrement);
11014 data.RunUntilPaused();
11015
11016 FastForwardBy(kTimeIncrement);
11017 data.Resume();
[email protected]511f6f52010-12-17 03:58:2911018 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:5911019 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911020}
11021
[email protected]4eddbc732012-08-09 05:40:1711022// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0111023TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611024 session_deps_.proxy_resolution_service =
11025 ConfiguredProxyResolutionService::CreateFixed(
11026 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911027
11028 HttpRequestInfo request;
11029 request.method = "GET";
bncce36dca22015-04-21 22:11:2311030 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011031 request.traffic_annotation =
11032 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911033
11034 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711035 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11036 "Host: www.example.org:443\r\n"
11037 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:2911038 };
11039
11040 MockRead data_reads[] = {
11041 MockRead("HTTP/1.1 404 Not Found\r\n"),
11042 MockRead("Content-Length: 23\r\n\r\n"),
11043 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:0611044 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:2911045 };
11046
Ryan Sleevib8d7ea02018-05-07 20:01:0111047 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0611048 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:2911049
[email protected]bb88e1d32013-05-03 23:11:0711050 session_deps_.socket_factory->AddSocketDataProvider(&data);
11051 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2911052
[email protected]49639fa2011-12-20 23:22:4111053 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2911054
danakj1fd259a02016-04-16 03:17:0911055 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611056 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911057
tfarina42834112016-09-22 13:38:2011058 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111059 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2911060
11061 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111062 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911063
ttuttle960fcbf2016-04-19 13:26:3211064 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2911065}
11066
[email protected]4eddbc732012-08-09 05:40:1711067// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:0111068TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611069 session_deps_.proxy_resolution_service =
11070 ConfiguredProxyResolutionService::CreateFixed(
11071 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911072
11073 HttpRequestInfo request;
11074 request.method = "GET";
bncce36dca22015-04-21 22:11:2311075 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011076 request.traffic_annotation =
11077 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:2911078
Ryan Hamilton0239aac2018-05-19 00:03:1311079 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411080 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
11081 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1311082 spdy::SpdySerializedFrame rst(
11083 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:2911084 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111085 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:2911086 };
11087
11088 static const char* const kExtraHeaders[] = {
11089 "location",
11090 "http://login.example.com/",
11091 };
Ryan Hamilton0239aac2018-05-19 00:03:1311092 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2411093 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1311094 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:1911095 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:2911096 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111097 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:1311098 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2911099 };
11100
Ryan Sleevib8d7ea02018-05-07 20:01:0111101 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0611102 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3611103 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2911104
[email protected]bb88e1d32013-05-03 23:11:0711105 session_deps_.socket_factory->AddSocketDataProvider(&data);
11106 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2911107
[email protected]49639fa2011-12-20 23:22:4111108 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2911109
danakj1fd259a02016-04-16 03:17:0911110 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611111 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2911112
tfarina42834112016-09-22 13:38:2011113 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111114 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2911115
11116 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111117 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2911118
ttuttle960fcbf2016-04-19 13:26:3211119 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2911120}
11121
[email protected]0c5fb722012-02-28 11:50:3511122// Test the request-challenge-retry sequence for basic auth, through
11123// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0111124TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3511125 HttpRequestInfo request;
11126 request.method = "GET";
bncce36dca22015-04-21 22:11:2311127 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3511128 // when the no authentication data flag is set.
Matt Menke25eaa432020-08-25 00:10:0011129 request.privacy_mode = PRIVACY_MODE_ENABLED;
Ramin Halavatib5e433e62018-02-07 07:41:1011130 request.traffic_annotation =
11131 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3511132
11133 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5911134 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611135 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911136 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411137 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711138 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0911139 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3511140
11141 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1311142 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411143 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
11144 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1311145 spdy::SpdySerializedFrame rst(
11146 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3811147 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3511148
bnc691fda62016-08-12 00:43:1611149 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3511150 // be issuing -- the final header line contains the credentials.
11151 const char* const kAuthCredentials[] = {
11152 "proxy-authorization", "Basic Zm9vOmJhcg==",
11153 };
Ryan Hamilton0239aac2018-05-19 00:03:1311154 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0411155 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
11156 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2311157 HostPortPair("www.example.org", 443)));
11158 // fetch https://www.example.org/ via HTTP
11159 const char get[] =
11160 "GET / HTTP/1.1\r\n"
11161 "Host: www.example.org\r\n"
11162 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1311163 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1911164 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3511165
11166 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111167 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
11168 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3511169 };
11170
11171 // The proxy responds to the connect with a 407, using a persistent
11172 // connection.
thestig9d3bb0c2015-01-24 00:49:5111173 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3511174 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3511175 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
11176 };
Ryan Hamilton0239aac2018-05-19 00:03:1311177 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2411178 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3511179
Ryan Hamilton0239aac2018-05-19 00:03:1311180 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3511181 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3511182 const char resp[] = "HTTP/1.1 200 OK\r\n"
11183 "Content-Length: 5\r\n\r\n";
11184
Ryan Hamilton0239aac2018-05-19 00:03:1311185 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1911186 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1311187 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1911188 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3511189 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111190 CreateMockRead(conn_auth_resp, 1, ASYNC),
11191 CreateMockRead(conn_resp, 4, ASYNC),
11192 CreateMockRead(wrapped_get_resp, 6, ASYNC),
11193 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1311194 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3511195 };
11196
Ryan Sleevib8d7ea02018-05-07 20:01:0111197 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711198 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3511199 // Negotiate SPDY to the proxy
11200 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611201 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711202 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3511203 // Vanilla SSL to the server
11204 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711205 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3511206
11207 TestCompletionCallback callback1;
11208
bnc87dcefc2017-05-25 12:47:5811209 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911210 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3511211
11212 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111213 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3511214
11215 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111216 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5411217 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3511218 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0011219 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11220 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3511221 ExpectLogContainsSomewhere(
11222 entries, pos,
mikecirone8b85c432016-09-08 19:11:0011223 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11224 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3511225
11226 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211227 ASSERT_TRUE(response);
11228 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3511229 EXPECT_EQ(407, response->headers->response_code());
11230 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5811231 EXPECT_TRUE(response->auth_challenge.has_value());
11232 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3511233
11234 TestCompletionCallback callback2;
11235
11236 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
11237 callback2.callback());
robpercival214763f2016-07-01 23:27:0111238 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3511239
11240 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111241 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3511242
11243 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211244 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3511245
11246 EXPECT_TRUE(response->headers->IsKeepAlive());
11247 EXPECT_EQ(200, response->headers->response_code());
11248 EXPECT_EQ(5, response->headers->GetContentLength());
11249 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11250
11251 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5811252 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3511253
[email protected]029c83b62013-01-24 05:28:2011254 LoadTimingInfo load_timing_info;
11255 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11256 TestLoadTimingNotReusedWithPac(load_timing_info,
11257 CONNECT_TIMING_HAS_SSL_TIMES);
11258
[email protected]0c5fb722012-02-28 11:50:3511259 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111260 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]0c5fb722012-02-28 11:50:3511261}
11262
[email protected]7c6f7ba2012-04-03 04:09:2911263// Test that an explicitly trusted SPDY proxy can push a resource from an
11264// origin that is different from that of its associated resource.
Matt Menkedf93ff72020-07-16 02:23:0311265TEST_F(HttpNetworkTransactionTest, CrossOriginSpdyProxyPush) {
tbansal28e68f82016-02-04 02:56:1511266 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911267 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511268 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11269 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2911270 HttpRequestInfo request;
11271 HttpRequestInfo push_request;
Ramin Halavatib5e433e62018-02-07 07:41:1011272 request.traffic_annotation =
11273 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2911274
[email protected]7c6f7ba2012-04-03 04:09:2911275 request.method = "GET";
bncce36dca22015-04-21 22:11:2311276 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2911277 push_request.method = "GET";
11278 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e62018-02-07 07:41:1011279 push_request.traffic_annotation =
11280 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2911281
tbansal28e68f82016-02-04 02:56:1511282 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5911283 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611284 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4911285 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411286 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711287 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5011288
Eric Roman3d8546a2018-09-10 17:00:5211289 session_deps_.proxy_resolution_service->SetProxyDelegate(
11290 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011291
danakj1fd259a02016-04-16 03:17:0911292 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2911293
Ryan Hamilton0239aac2018-05-19 00:03:1311294 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511295 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311296 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511297 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2911298
11299 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111300 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511301 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2911302 };
11303
Ryan Hamilton0239aac2018-05-19 00:03:1311304 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511305 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3611306
Ryan Hamilton0239aac2018-05-19 00:03:1311307 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511308 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2911309
Ryan Hamilton0239aac2018-05-19 00:03:1311310 spdy::SpdySerializedFrame stream1_body(
11311 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2911312
Ryan Hamilton0239aac2018-05-19 00:03:1311313 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1911314 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2911315
11316 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3611317 CreateMockRead(stream2_syn, 1, ASYNC),
11318 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511319 CreateMockRead(stream1_body, 4, ASYNC),
11320 CreateMockRead(stream2_body, 5, ASYNC),
11321 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2911322 };
11323
Ryan Sleevib8d7ea02018-05-07 20:01:0111324 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711325 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2911326 // Negotiate SPDY to the proxy
11327 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611328 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711329 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2911330
bnc87dcefc2017-05-25 12:47:5811331 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911332 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2911333 TestCompletionCallback callback;
11334 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111335 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911336
11337 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111338 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911339 const HttpResponseInfo* response = trans->GetResponseInfo();
11340
bnc87dcefc2017-05-25 12:47:5811341 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1911342 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5011343 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111344 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2911345
11346 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111347 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911348 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
11349
wezca1070932016-05-26 20:30:5211350 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2911351 EXPECT_TRUE(response->headers->IsKeepAlive());
11352
11353 EXPECT_EQ(200, response->headers->response_code());
11354 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11355
11356 std::string response_data;
11357 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111358 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911359 EXPECT_EQ("hello!", response_data);
11360
[email protected]029c83b62013-01-24 05:28:2011361 LoadTimingInfo load_timing_info;
11362 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11363 TestLoadTimingNotReusedWithPac(load_timing_info,
11364 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11365
[email protected]7c6f7ba2012-04-03 04:09:2911366 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5211367 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2911368 EXPECT_EQ(200, push_response->headers->response_code());
11369
11370 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111371 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2911372 EXPECT_EQ("pushed", response_data);
11373
[email protected]029c83b62013-01-24 05:28:2011374 LoadTimingInfo push_load_timing_info;
11375 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
11376 TestLoadTimingReusedWithPac(push_load_timing_info);
11377 // The transactions should share a socket ID, despite being for different
11378 // origins.
11379 EXPECT_EQ(load_timing_info.socket_log_id,
11380 push_load_timing_info.socket_log_id);
11381
[email protected]7c6f7ba2012-04-03 04:09:2911382 trans.reset();
11383 push_trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111384 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]7c6f7ba2012-04-03 04:09:2911385}
11386
[email protected]8c843192012-04-05 07:15:0011387// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0111388TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511389 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911390 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511391 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
11392 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0011393 HttpRequestInfo request;
11394
11395 request.method = "GET";
bncce36dca22015-04-21 22:11:2311396 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011397 request.traffic_annotation =
11398 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0011399
Nicolas Arciniegad2013f92020-02-07 23:00:5611400 session_deps_.proxy_resolution_service =
11401 ConfiguredProxyResolutionService::CreateFixed(
11402 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411403 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711404 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5011405
11406 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211407 session_deps_.proxy_resolution_service->SetProxyDelegate(
11408 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5011409
danakj1fd259a02016-04-16 03:17:0911410 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0011411
Ryan Hamilton0239aac2018-05-19 00:03:1311412 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511413 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0011414
Ryan Hamilton0239aac2018-05-19 00:03:1311415 spdy::SpdySerializedFrame push_rst(
11416 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0011417
11418 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111419 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0011420 };
11421
Ryan Hamilton0239aac2018-05-19 00:03:1311422 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3511423 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0011424
Ryan Hamilton0239aac2018-05-19 00:03:1311425 spdy::SpdySerializedFrame stream1_body(
11426 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0011427
Ryan Hamilton0239aac2018-05-19 00:03:1311428 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3511429 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0011430
11431 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111432 CreateMockRead(stream1_reply, 1, ASYNC),
11433 CreateMockRead(stream2_syn, 2, ASYNC),
11434 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5911435 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0011436 };
11437
Ryan Sleevib8d7ea02018-05-07 20:01:0111438 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0711439 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0011440 // Negotiate SPDY to the proxy
11441 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611442 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0711443 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0011444
bnc87dcefc2017-05-25 12:47:5811445 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911446 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0011447 TestCompletionCallback callback;
11448 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111449 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0011450
11451 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111452 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011453 const HttpResponseInfo* response = trans->GetResponseInfo();
11454
wezca1070932016-05-26 20:30:5211455 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0011456 EXPECT_TRUE(response->headers->IsKeepAlive());
11457
11458 EXPECT_EQ(200, response->headers->response_code());
11459 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11460
11461 std::string response_data;
11462 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111463 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0011464 EXPECT_EQ("hello!", response_data);
11465
11466 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111467 session->CloseAllConnections(ERR_FAILED, "Very good reason");
[email protected]8c843192012-04-05 07:15:0011468}
11469
tbansal8ef1d3e2016-02-03 04:05:4211470// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
11471// resources.
bncd16676a2016-07-20 16:23:0111472TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1511473 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1911474 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1511475 proxy_delegate->set_trusted_spdy_proxy(
11476 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
11477
tbansal8ef1d3e2016-02-03 04:05:4211478 HttpRequestInfo request;
11479
11480 request.method = "GET";
11481 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011482 request.traffic_annotation =
11483 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4211484
11485 // Configure against https proxy server "myproxy:70".
Nicolas Arciniegad2013f92020-02-07 23:00:5611486 session_deps_.proxy_resolution_service =
11487 ConfiguredProxyResolutionService::CreateFixed(
11488 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1411489 RecordingBoundTestNetLog log;
tbansal8ef1d3e2016-02-03 04:05:4211490 session_deps_.net_log = log.bound().net_log();
11491
11492 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5211493 session_deps_.proxy_resolution_service->SetProxyDelegate(
11494 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4211495
danakj1fd259a02016-04-16 03:17:0911496 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4211497
Ryan Hamilton0239aac2018-05-19 00:03:1311498 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4511499 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1311500 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3511501 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4211502
11503 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4111504 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3511505 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4211506 };
11507
Ryan Hamilton0239aac2018-05-19 00:03:1311508 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1511509 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211510
Ryan Hamilton0239aac2018-05-19 00:03:1311511 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3311512 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4911513
Ryan Hamilton0239aac2018-05-19 00:03:1311514 spdy::SpdySerializedFrame stream1_body(
11515 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211516
Ryan Hamilton0239aac2018-05-19 00:03:1311517 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1511518 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4211519
Ryan Hamilton0239aac2018-05-19 00:03:1311520 spdy::SpdySerializedFrame stream2_body(
11521 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4211522
11523 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111524 CreateMockRead(stream1_reply, 1, ASYNC),
11525 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3511526 CreateMockRead(stream1_body, 4, ASYNC),
11527 CreateMockRead(stream2_body, 5, ASYNC),
11528 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4211529 };
11530
Ryan Sleevib8d7ea02018-05-07 20:01:0111531 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4211532 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11533 // Negotiate SPDY to the proxy
11534 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611535 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4211536 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
11537
bnc87dcefc2017-05-25 12:47:5811538 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911539 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4211540 TestCompletionCallback callback;
11541 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0111542 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4211543
11544 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111545 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211546 const HttpResponseInfo* response = trans->GetResponseInfo();
11547
wezca1070932016-05-26 20:30:5211548 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4211549 EXPECT_TRUE(response->headers->IsKeepAlive());
11550
11551 EXPECT_EQ(200, response->headers->response_code());
11552 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11553
11554 std::string response_data;
11555 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0111556 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4211557 EXPECT_EQ("hello!", response_data);
11558
11559 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1111560 session->CloseAllConnections(ERR_FAILED, "Very good reason");
tbansal8ef1d3e2016-02-03 04:05:4211561}
11562
[email protected]2df19bb2010-08-25 20:13:4611563// Test HTTPS connections to a site with a bad certificate, going through an
11564// HTTPS proxy
bncd16676a2016-07-20 16:23:0111565TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Nicolas Arciniegad2013f92020-02-07 23:00:5611566 session_deps_.proxy_resolution_service =
11567 ConfiguredProxyResolutionService::CreateFixed(
11568 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611569
11570 HttpRequestInfo request;
11571 request.method = "GET";
bncce36dca22015-04-21 22:11:2311572 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011573 request.traffic_annotation =
11574 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4611575
11576 // Attempt to fetch the URL from a server with a bad cert
11577 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711578 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11579 "Host: www.example.org:443\r\n"
11580 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611581 };
11582
11583 MockRead bad_cert_reads[] = {
11584 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611585 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4611586 };
11587
11588 // Attempt to fetch the URL with a good cert
11589 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1711590 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11591 "Host: www.example.org:443\r\n"
11592 "Proxy-Connection: keep-alive\r\n\r\n"),
11593 MockWrite("GET / HTTP/1.1\r\n"
11594 "Host: www.example.org\r\n"
11595 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4611596 };
11597
11598 MockRead good_cert_reads[] = {
11599 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
11600 MockRead("HTTP/1.0 200 OK\r\n"),
11601 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11602 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611603 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4611604 };
11605
Ryan Sleevib8d7ea02018-05-07 20:01:0111606 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
11607 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0611608 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
11609 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4611610
11611 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0711612 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11613 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
11614 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4611615
11616 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0711617 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11618 session_deps_.socket_factory->AddSocketDataProvider(&data);
11619 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4611620
[email protected]49639fa2011-12-20 23:22:4111621 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4611622
danakj1fd259a02016-04-16 03:17:0911623 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611624 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4611625
tfarina42834112016-09-22 13:38:2011626 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111627 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611628
11629 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111630 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4611631
bnc691fda62016-08-12 00:43:1611632 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0111633 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4611634
11635 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111636 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4611637
bnc691fda62016-08-12 00:43:1611638 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4611639
wezca1070932016-05-26 20:30:5211640 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4611641 EXPECT_EQ(100, response->headers->GetContentLength());
11642}
11643
bncd16676a2016-07-20 16:23:0111644TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4211645 HttpRequestInfo request;
11646 request.method = "GET";
bncce36dca22015-04-21 22:11:2311647 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311648 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11649 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e62018-02-07 07:41:1011650 request.traffic_annotation =
11651 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211652
danakj1fd259a02016-04-16 03:17:0911653 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611654 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711655
[email protected]1c773ea12009-04-28 19:58:4211656 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311657 MockWrite(
11658 "GET / HTTP/1.1\r\n"
11659 "Host: www.example.org\r\n"
11660 "Connection: keep-alive\r\n"
11661 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211662 };
11663
11664 // Lastly, the server responds with the actual content.
11665 MockRead data_reads[] = {
11666 MockRead("HTTP/1.0 200 OK\r\n"),
11667 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11668 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611669 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211670 };
11671
Ryan Sleevib8d7ea02018-05-07 20:01:0111672 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711673 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211674
[email protected]49639fa2011-12-20 23:22:4111675 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211676
tfarina42834112016-09-22 13:38:2011677 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111678 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211679
11680 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111681 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211682}
11683
bncd16676a2016-07-20 16:23:0111684TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0011685 // Test user agent values, used both for the request header of the original
11686 // request, and the value returned by the HttpUserAgentSettings. nullptr means
11687 // no request header / no HttpUserAgentSettings object.
11688 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2911689
Matt Menked732ea42019-03-08 12:05:0011690 for (const char* setting_user_agent : kTestUserAgents) {
11691 if (!setting_user_agent) {
11692 session_deps_.http_user_agent_settings.reset();
11693 } else {
11694 session_deps_.http_user_agent_settings =
11695 std::make_unique<StaticHttpUserAgentSettings>(
11696 std::string() /* accept-language */, setting_user_agent);
11697 }
11698 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5611699 ConfiguredProxyResolutionService::CreateFixed(
11700 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked732ea42019-03-08 12:05:0011701 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11702 for (const char* request_user_agent : kTestUserAgents) {
11703 HttpRequestInfo request;
11704 request.method = "GET";
11705 request.url = GURL("https://www.example.org/");
11706 if (request_user_agent) {
11707 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
11708 request_user_agent);
11709 }
11710 request.traffic_annotation =
11711 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711712
Matt Menked732ea42019-03-08 12:05:0011713 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2911714
Matt Menked732ea42019-03-08 12:05:0011715 std::string expected_request;
11716 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
11717 expected_request =
11718 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11719 "Host: www.example.org:443\r\n"
11720 "Proxy-Connection: keep-alive\r\n\r\n";
11721 } else {
11722 expected_request = base::StringPrintf(
11723 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11724 "Host: www.example.org:443\r\n"
11725 "Proxy-Connection: keep-alive\r\n"
11726 "User-Agent: %s\r\n\r\n",
11727 setting_user_agent);
11728 }
11729 MockWrite data_writes[] = {
11730 MockWrite(expected_request.c_str()),
11731 };
11732 MockRead data_reads[] = {
11733 // Return an error, so the transaction stops here (this test isn't
11734 // interested in the rest).
11735 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
11736 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11737 MockRead("Proxy-Connection: close\r\n\r\n"),
11738 };
[email protected]da81f132010-08-18 23:39:2911739
Matt Menked732ea42019-03-08 12:05:0011740 StaticSocketDataProvider data(data_reads, data_writes);
11741 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2911742
Matt Menked732ea42019-03-08 12:05:0011743 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2911744
Matt Menked732ea42019-03-08 12:05:0011745 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11746 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11747
11748 rv = callback.WaitForResult();
11749 EXPECT_THAT(rv, IsOk());
11750 }
11751 }
[email protected]da81f132010-08-18 23:39:2911752}
11753
bncd16676a2016-07-20 16:23:0111754TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4211755 HttpRequestInfo request;
11756 request.method = "GET";
bncce36dca22015-04-21 22:11:2311757 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1611758 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
11759 "http://the.previous.site.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011760 request.traffic_annotation =
11761 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211762
danakj1fd259a02016-04-16 03:17:0911763 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611764 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711765
[email protected]1c773ea12009-04-28 19:58:4211766 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311767 MockWrite(
11768 "GET / HTTP/1.1\r\n"
11769 "Host: www.example.org\r\n"
11770 "Connection: keep-alive\r\n"
11771 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211772 };
11773
11774 // Lastly, the server responds with the actual content.
11775 MockRead data_reads[] = {
11776 MockRead("HTTP/1.0 200 OK\r\n"),
11777 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11778 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611779 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211780 };
11781
Ryan Sleevib8d7ea02018-05-07 20:01:0111782 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711783 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211784
[email protected]49639fa2011-12-20 23:22:4111785 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211786
tfarina42834112016-09-22 13:38:2011787 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111788 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211789
11790 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111791 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211792}
11793
bncd16676a2016-07-20 16:23:0111794TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211795 HttpRequestInfo request;
11796 request.method = "POST";
bncce36dca22015-04-21 22:11:2311797 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011798 request.traffic_annotation =
11799 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211800
danakj1fd259a02016-04-16 03:17:0911801 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611802 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711803
[email protected]1c773ea12009-04-28 19:58:4211804 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311805 MockWrite(
11806 "POST / HTTP/1.1\r\n"
11807 "Host: www.example.org\r\n"
11808 "Connection: keep-alive\r\n"
11809 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211810 };
11811
11812 // Lastly, the server responds with the actual content.
11813 MockRead data_reads[] = {
11814 MockRead("HTTP/1.0 200 OK\r\n"),
11815 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11816 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611817 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211818 };
11819
Ryan Sleevib8d7ea02018-05-07 20:01:0111820 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711821 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211822
[email protected]49639fa2011-12-20 23:22:4111823 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211824
tfarina42834112016-09-22 13:38:2011825 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111826 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211827
11828 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111829 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211830}
11831
bncd16676a2016-07-20 16:23:0111832TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211833 HttpRequestInfo request;
11834 request.method = "PUT";
bncce36dca22015-04-21 22:11:2311835 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011836 request.traffic_annotation =
11837 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211838
danakj1fd259a02016-04-16 03:17:0911839 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611840 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711841
[email protected]1c773ea12009-04-28 19:58:4211842 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311843 MockWrite(
11844 "PUT / HTTP/1.1\r\n"
11845 "Host: www.example.org\r\n"
11846 "Connection: keep-alive\r\n"
11847 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211848 };
11849
11850 // Lastly, the server responds with the actual content.
11851 MockRead data_reads[] = {
11852 MockRead("HTTP/1.0 200 OK\r\n"),
11853 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11854 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611855 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211856 };
11857
Ryan Sleevib8d7ea02018-05-07 20:01:0111858 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711859 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211860
[email protected]49639fa2011-12-20 23:22:4111861 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211862
tfarina42834112016-09-22 13:38:2011863 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111864 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211865
11866 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111867 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211868}
11869
bncd16676a2016-07-20 16:23:0111870TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4211871 HttpRequestInfo request;
11872 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2311873 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011874 request.traffic_annotation =
11875 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211876
danakj1fd259a02016-04-16 03:17:0911877 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611878 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711879
[email protected]1c773ea12009-04-28 19:58:4211880 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1311881 MockWrite("HEAD / HTTP/1.1\r\n"
11882 "Host: www.example.org\r\n"
11883 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211884 };
11885
11886 // Lastly, the server responds with the actual content.
11887 MockRead data_reads[] = {
11888 MockRead("HTTP/1.0 200 OK\r\n"),
11889 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11890 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611891 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211892 };
11893
Ryan Sleevib8d7ea02018-05-07 20:01:0111894 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711895 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211896
[email protected]49639fa2011-12-20 23:22:4111897 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211898
tfarina42834112016-09-22 13:38:2011899 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111900 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211901
11902 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111903 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211904}
11905
bncd16676a2016-07-20 16:23:0111906TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4211907 HttpRequestInfo request;
11908 request.method = "GET";
bncce36dca22015-04-21 22:11:2311909 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211910 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1011911 request.traffic_annotation =
11912 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211913
danakj1fd259a02016-04-16 03:17:0911914 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611915 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711916
[email protected]1c773ea12009-04-28 19:58:4211917 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311918 MockWrite(
11919 "GET / HTTP/1.1\r\n"
11920 "Host: www.example.org\r\n"
11921 "Connection: keep-alive\r\n"
11922 "Pragma: no-cache\r\n"
11923 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211924 };
11925
11926 // Lastly, the server responds with the actual content.
11927 MockRead data_reads[] = {
11928 MockRead("HTTP/1.0 200 OK\r\n"),
11929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11930 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611931 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211932 };
11933
Ryan Sleevib8d7ea02018-05-07 20:01:0111934 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711935 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211936
[email protected]49639fa2011-12-20 23:22:4111937 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211938
tfarina42834112016-09-22 13:38:2011939 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111940 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211941
11942 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111943 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211944}
11945
bncd16676a2016-07-20 16:23:0111946TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4211947 HttpRequestInfo request;
11948 request.method = "GET";
bncce36dca22015-04-21 22:11:2311949 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4211950 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1011951 request.traffic_annotation =
11952 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211953
danakj1fd259a02016-04-16 03:17:0911954 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611955 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711956
[email protected]1c773ea12009-04-28 19:58:4211957 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311958 MockWrite(
11959 "GET / HTTP/1.1\r\n"
11960 "Host: www.example.org\r\n"
11961 "Connection: keep-alive\r\n"
11962 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4211963 };
11964
11965 // Lastly, the server responds with the actual content.
11966 MockRead data_reads[] = {
11967 MockRead("HTTP/1.0 200 OK\r\n"),
11968 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11969 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611970 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4211971 };
11972
Ryan Sleevib8d7ea02018-05-07 20:01:0111973 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711974 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4211975
[email protected]49639fa2011-12-20 23:22:4111976 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4211977
tfarina42834112016-09-22 13:38:2011978 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4211980
11981 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111982 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4211983}
11984
bncd16676a2016-07-20 16:23:0111985TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4211986 HttpRequestInfo request;
11987 request.method = "GET";
bncce36dca22015-04-21 22:11:2311988 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4311989 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e62018-02-07 07:41:1011990 request.traffic_annotation =
11991 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4211992
danakj1fd259a02016-04-16 03:17:0911993 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611994 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711995
[email protected]1c773ea12009-04-28 19:58:4211996 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311997 MockWrite(
11998 "GET / HTTP/1.1\r\n"
11999 "Host: www.example.org\r\n"
12000 "Connection: keep-alive\r\n"
12001 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4212002 };
12003
12004 // Lastly, the server responds with the actual content.
12005 MockRead data_reads[] = {
12006 MockRead("HTTP/1.0 200 OK\r\n"),
12007 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12008 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612009 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4212010 };
12011
Ryan Sleevib8d7ea02018-05-07 20:01:0112012 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712013 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4212014
[email protected]49639fa2011-12-20 23:22:4112015 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4212016
tfarina42834112016-09-22 13:38:2012017 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112018 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4212019
12020 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112021 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4212022}
12023
bncd16676a2016-07-20 16:23:0112024TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4712025 HttpRequestInfo request;
12026 request.method = "GET";
bncce36dca22015-04-21 22:11:2312027 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4312028 request.extra_headers.SetHeader("referer", "www.foo.com");
12029 request.extra_headers.SetHeader("hEllo", "Kitty");
12030 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1012031 request.traffic_annotation =
12032 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4712033
danakj1fd259a02016-04-16 03:17:0912034 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612035 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712036
[email protected]270c6412010-03-29 22:02:4712037 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312038 MockWrite(
12039 "GET / HTTP/1.1\r\n"
12040 "Host: www.example.org\r\n"
12041 "Connection: keep-alive\r\n"
12042 "referer: www.foo.com\r\n"
12043 "hEllo: Kitty\r\n"
12044 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4712045 };
12046
12047 // Lastly, the server responds with the actual content.
12048 MockRead data_reads[] = {
12049 MockRead("HTTP/1.0 200 OK\r\n"),
12050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12051 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612052 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4712053 };
12054
Ryan Sleevib8d7ea02018-05-07 20:01:0112055 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712056 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4712057
[email protected]49639fa2011-12-20 23:22:4112058 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4712059
tfarina42834112016-09-22 13:38:2012060 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112061 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4712062
12063 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112064 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4712065}
12066
bncd16676a2016-07-20 16:23:0112067TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712068 HttpRequestInfo request;
12069 request.method = "GET";
bncce36dca22015-04-21 22:11:2312070 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012071 request.traffic_annotation =
12072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712073
Lily Houghton8c2f97d2018-01-22 05:06:5912074 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612075 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912076 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412077 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712078 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0212079
danakj1fd259a02016-04-16 03:17:0912080 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612081 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0212082
[email protected]3cd17242009-06-23 02:59:0212083 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
12084 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12085
12086 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412087 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
12088 MockWrite("GET / HTTP/1.1\r\n"
12089 "Host: www.example.org\r\n"
12090 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0212091
12092 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412093 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
12094 MockRead("HTTP/1.0 200 OK\r\n"),
12095 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12096 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0212097
Ryan Sleevib8d7ea02018-05-07 20:01:0112098 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712099 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0212100
[email protected]49639fa2011-12-20 23:22:4112101 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0212102
tfarina42834112016-09-22 13:38:2012103 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112104 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0212105
12106 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112107 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212108
bnc691fda62016-08-12 00:43:1612109 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212110 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0212111
tbansal2ecbbc72016-10-06 17:15:4712112 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2012113 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612114 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012115 TestLoadTimingNotReusedWithPac(load_timing_info,
12116 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12117
[email protected]3cd17242009-06-23 02:59:0212118 std::string response_text;
bnc691fda62016-08-12 00:43:1612119 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112120 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212121 EXPECT_EQ("Payload", response_text);
12122}
12123
bncd16676a2016-07-20 16:23:0112124TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712125 HttpRequestInfo request;
12126 request.method = "GET";
bncce36dca22015-04-21 22:11:2312127 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012128 request.traffic_annotation =
12129 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712130
Lily Houghton8c2f97d2018-01-22 05:06:5912131 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612132 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912133 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412134 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712135 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0212136
danakj1fd259a02016-04-16 03:17:0912137 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612138 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0212139
[email protected]3cd17242009-06-23 02:59:0212140 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
12141 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12142
12143 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2312144 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2412145 base::size(write_buffer)),
12146 MockWrite("GET / HTTP/1.1\r\n"
12147 "Host: www.example.org\r\n"
12148 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0212149
12150 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412151 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
12152 base::size(read_buffer)),
12153 MockRead("HTTP/1.0 200 OK\r\n"),
12154 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12155 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3512156
Ryan Sleevib8d7ea02018-05-07 20:01:0112157 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712158 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3512159
[email protected]8ddf8322012-02-23 18:08:0612160 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712161 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3512162
[email protected]49639fa2011-12-20 23:22:4112163 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3512164
tfarina42834112016-09-22 13:38:2012165 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112166 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3512167
12168 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112169 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512170
[email protected]029c83b62013-01-24 05:28:2012171 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612172 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012173 TestLoadTimingNotReusedWithPac(load_timing_info,
12174 CONNECT_TIMING_HAS_SSL_TIMES);
12175
bnc691fda62016-08-12 00:43:1612176 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212177 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712178 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3512179
12180 std::string response_text;
bnc691fda62016-08-12 00:43:1612181 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112182 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512183 EXPECT_EQ("Payload", response_text);
12184}
12185
bncd16676a2016-07-20 16:23:0112186TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2012187 HttpRequestInfo request;
12188 request.method = "GET";
bncce36dca22015-04-21 22:11:2312189 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012190 request.traffic_annotation =
12191 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2012192
Nicolas Arciniegad2013f92020-02-07 23:00:5612193 session_deps_.proxy_resolution_service =
12194 ConfiguredProxyResolutionService::CreateFixed(
12195 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412196 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712197 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2012198
danakj1fd259a02016-04-16 03:17:0912199 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612200 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2012201
12202 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
12203 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
12204
12205 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412206 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
12207 MockWrite("GET / HTTP/1.1\r\n"
12208 "Host: www.example.org\r\n"
12209 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2012210
12211 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412212 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
12213 MockRead("HTTP/1.0 200 OK\r\n"),
12214 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12215 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2012216
Ryan Sleevib8d7ea02018-05-07 20:01:0112217 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712218 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2012219
12220 TestCompletionCallback callback;
12221
tfarina42834112016-09-22 13:38:2012222 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112223 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2012224
12225 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112226 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2012227
bnc691fda62016-08-12 00:43:1612228 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212229 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2012230
12231 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612232 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012233 TestLoadTimingNotReused(load_timing_info,
12234 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12235
12236 std::string response_text;
bnc691fda62016-08-12 00:43:1612237 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112238 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2012239 EXPECT_EQ("Payload", response_text);
12240}
12241
bncd16676a2016-07-20 16:23:0112242TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712243 HttpRequestInfo request;
12244 request.method = "GET";
bncce36dca22015-04-21 22:11:2312245 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012246 request.traffic_annotation =
12247 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712248
Lily Houghton8c2f97d2018-01-22 05:06:5912249 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612250 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912251 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412252 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712253 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3512254
danakj1fd259a02016-04-16 03:17:0912255 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612256 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3512257
[email protected]e0c27be2009-07-15 13:09:3512258 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
12259 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3712260 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2312261 0x05, // Version
12262 0x01, // Command (CONNECT)
12263 0x00, // Reserved.
12264 0x03, // Address type (DOMAINNAME).
12265 0x0F, // Length of domain (15)
12266 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12267 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3712268 };
[email protected]e0c27be2009-07-15 13:09:3512269 const char kSOCKS5OkResponse[] =
12270 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
12271
12272 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412273 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
12274 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
12275 MockWrite("GET / HTTP/1.1\r\n"
12276 "Host: www.example.org\r\n"
12277 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512278
12279 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412280 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12281 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12282 MockRead("HTTP/1.0 200 OK\r\n"),
12283 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12284 MockRead("Payload"),
12285 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3512286
Ryan Sleevib8d7ea02018-05-07 20:01:0112287 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712288 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3512289
[email protected]49639fa2011-12-20 23:22:4112290 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3512291
tfarina42834112016-09-22 13:38:2012292 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112293 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3512294
12295 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112296 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512297
bnc691fda62016-08-12 00:43:1612298 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212299 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712300 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3512301
[email protected]029c83b62013-01-24 05:28:2012302 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612303 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012304 TestLoadTimingNotReusedWithPac(load_timing_info,
12305 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
12306
[email protected]e0c27be2009-07-15 13:09:3512307 std::string response_text;
bnc691fda62016-08-12 00:43:1612308 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112309 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3512310 EXPECT_EQ("Payload", response_text);
12311}
12312
bncd16676a2016-07-20 16:23:0112313TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2712314 HttpRequestInfo request;
12315 request.method = "GET";
bncce36dca22015-04-21 22:11:2312316 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012317 request.traffic_annotation =
12318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712319
Lily Houghton8c2f97d2018-01-22 05:06:5912320 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612321 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4912322 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1412323 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0712324 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3512325
danakj1fd259a02016-04-16 03:17:0912326 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612327 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3512328
[email protected]e0c27be2009-07-15 13:09:3512329 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
12330 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3712331 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2312332 0x05, // Version
12333 0x01, // Command (CONNECT)
12334 0x00, // Reserved.
12335 0x03, // Address type (DOMAINNAME).
12336 0x0F, // Length of domain (15)
12337 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
12338 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3712339 };
12340
[email protected]e0c27be2009-07-15 13:09:3512341 const char kSOCKS5OkResponse[] =
12342 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
12343
12344 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2412345 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2312346 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2412347 base::size(kSOCKS5OkRequest)),
12348 MockWrite("GET / HTTP/1.1\r\n"
12349 "Host: www.example.org\r\n"
12350 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3512351
12352 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2412353 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
12354 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
12355 MockRead("HTTP/1.0 200 OK\r\n"),
12356 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
12357 MockRead("Payload"),
12358 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0212359
Ryan Sleevib8d7ea02018-05-07 20:01:0112360 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0712361 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0212362
[email protected]8ddf8322012-02-23 18:08:0612363 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712364 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0212365
[email protected]49639fa2011-12-20 23:22:4112366 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0212367
tfarina42834112016-09-22 13:38:2012368 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112369 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0212370
12371 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112372 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212373
bnc691fda62016-08-12 00:43:1612374 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212375 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4712376 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0212377
[email protected]029c83b62013-01-24 05:28:2012378 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1612379 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2012380 TestLoadTimingNotReusedWithPac(load_timing_info,
12381 CONNECT_TIMING_HAS_SSL_TIMES);
12382
[email protected]3cd17242009-06-23 02:59:0212383 std::string response_text;
bnc691fda62016-08-12 00:43:1612384 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0112385 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0212386 EXPECT_EQ("Payload", response_text);
12387}
12388
[email protected]448d4ca52012-03-04 04:12:2312389namespace {
12390
Matt Menkef6edce752019-03-19 17:21:5612391// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0612392
Matt Menkef6edce752019-03-19 17:21:5612393struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0612394 std::string proxy_server;
12395 std::string url;
Matt Menkef6edce752019-03-19 17:21:5612396 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1812397 bool ssl;
[email protected]2d731a32010-04-29 01:04:0612398};
12399
Matt Menkef6edce752019-03-19 17:21:5612400std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0712401 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0912402 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0612403
bnc525e175a2016-06-20 12:36:4012404 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312405 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112406 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1212407 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112408 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4212409 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0712410 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0612411
12412 return session;
12413}
12414
Matt Menkef6edce752019-03-19 17:21:5612415int GroupIdTransactionHelper(const std::string& url,
12416 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0612417 HttpRequestInfo request;
12418 request.method = "GET";
12419 request.url = GURL(url);
Ramin Halavatib5e433e62018-02-07 07:41:1012420 request.traffic_annotation =
12421 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0612422
bnc691fda62016-08-12 00:43:1612423 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2712424
[email protected]49639fa2011-12-20 23:22:4112425 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0612426
12427 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2012428 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0612429}
12430
[email protected]448d4ca52012-03-04 04:12:2312431} // namespace
12432
Matt Menkef6edce752019-03-19 17:21:5612433TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
12434 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312435 {
Matt Menkef6edce752019-03-19 17:21:5612436 "", // unused
12437 "http://www.example.org/direct",
12438 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12439 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412440 PrivacyMode::PRIVACY_MODE_DISABLED,
12441 NetworkIsolationKey(),
12442 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612443 false,
bncce36dca22015-04-21 22:11:2312444 },
12445 {
Matt Menkef6edce752019-03-19 17:21:5612446 "", // unused
12447 "http://[2001:1418:13:1::25]/direct",
12448 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
12449 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412450 PrivacyMode::PRIVACY_MODE_DISABLED,
12451 NetworkIsolationKey(),
12452 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612453 false,
bncce36dca22015-04-21 22:11:2312454 },
[email protected]04e5be32009-06-26 20:00:3112455
bncce36dca22015-04-21 22:11:2312456 // SSL Tests
12457 {
Matt Menkef6edce752019-03-19 17:21:5612458 "", // unused
12459 "https://www.example.org/direct_ssl",
12460 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12461 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412462 PrivacyMode::PRIVACY_MODE_DISABLED,
12463 NetworkIsolationKey(),
12464 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612465 true,
bncce36dca22015-04-21 22:11:2312466 },
12467 {
Matt Menkef6edce752019-03-19 17:21:5612468 "", // unused
12469 "https://[2001:1418:13:1::25]/direct",
12470 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
12471 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412472 PrivacyMode::PRIVACY_MODE_DISABLED,
12473 NetworkIsolationKey(),
12474 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612475 true,
bncce36dca22015-04-21 22:11:2312476 },
12477 {
Matt Menkef6edce752019-03-19 17:21:5612478 "", // unused
12479 "https://host.with.alternate/direct",
12480 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12481 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412482 PrivacyMode::PRIVACY_MODE_DISABLED,
12483 NetworkIsolationKey(),
12484 false /* disable_secure_dns */),
Matt Menkef6edce752019-03-19 17:21:5612485 true,
bncce36dca22015-04-21 22:11:2312486 },
[email protected]2d731a32010-04-29 01:04:0612487 };
[email protected]2ff8b312010-04-26 22:20:5412488
Avi Drissman4365a4782018-12-28 19:26:2412489 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912490 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612491 ConfiguredProxyResolutionService::CreateFixed(
12492 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912493 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612494 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612495
mmenkee65e7af2015-10-13 17:16:4212496 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5612497 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612498 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912499 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012500 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
12501 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4812502 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612503
12504 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612505 GroupIdTransactionHelper(tests[i].url, session.get()));
12506 EXPECT_EQ(tests[i].expected_group_id,
12507 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2312508 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0612509 }
[email protected]2d731a32010-04-29 01:04:0612510}
12511
Matt Menkef6edce752019-03-19 17:21:5612512TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
12513 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312514 {
Matt Menke4802de62019-03-08 22:47:5012515 "http_proxy",
12516 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5612517 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12518 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412519 PrivacyMode::PRIVACY_MODE_DISABLED,
12520 NetworkIsolationKey(),
12521 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012522 false,
bncce36dca22015-04-21 22:11:2312523 },
[email protected]2d731a32010-04-29 01:04:0612524
bncce36dca22015-04-21 22:11:2312525 // SSL Tests
12526 {
Matt Menke4802de62019-03-08 22:47:5012527 "http_proxy",
12528 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5612529 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12530 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412531 PrivacyMode::PRIVACY_MODE_DISABLED,
12532 NetworkIsolationKey(),
12533 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012534 true,
bncce36dca22015-04-21 22:11:2312535 },
[email protected]af3490e2010-10-16 21:02:2912536
bncce36dca22015-04-21 22:11:2312537 {
Matt Menke4802de62019-03-08 22:47:5012538 "http_proxy",
12539 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612540 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12541 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412542 PrivacyMode::PRIVACY_MODE_DISABLED,
12543 NetworkIsolationKey(),
12544 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012545 true,
bncce36dca22015-04-21 22:11:2312546 },
[email protected]2d731a32010-04-29 01:04:0612547 };
12548
Avi Drissman4365a4782018-12-28 19:26:2412549 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912550 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612551 ConfiguredProxyResolutionService::CreateFixed(
12552 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912553 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612554 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0612555
mmenkee65e7af2015-10-13 17:16:4212556 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0612557
Matt Menkee8648fa2019-01-17 16:47:0712558 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
12559 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5612560 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3612561 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912562 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012563 mock_pool_manager->SetSocketPool(proxy_server,
12564 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4812565 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0612566
12567 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612568 GroupIdTransactionHelper(tests[i].url, session.get()));
12569 EXPECT_EQ(tests[i].expected_group_id,
12570 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0612571 }
[email protected]2d731a32010-04-29 01:04:0612572}
12573
Matt Menkef6edce752019-03-19 17:21:5612574TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
12575 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2312576 {
Matt Menke4802de62019-03-08 22:47:5012577 "socks4://socks_proxy:1080",
12578 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5612579 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12580 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412581 PrivacyMode::PRIVACY_MODE_DISABLED,
12582 NetworkIsolationKey(),
12583 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012584 false,
bncce36dca22015-04-21 22:11:2312585 },
12586 {
Matt Menke4802de62019-03-08 22:47:5012587 "socks5://socks_proxy:1080",
12588 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5612589 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
12590 ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3412591 PrivacyMode::PRIVACY_MODE_DISABLED,
12592 NetworkIsolationKey(),
12593 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012594 false,
bncce36dca22015-04-21 22:11:2312595 },
[email protected]2d731a32010-04-29 01:04:0612596
bncce36dca22015-04-21 22:11:2312597 // SSL Tests
12598 {
Matt Menke4802de62019-03-08 22:47:5012599 "socks4://socks_proxy:1080",
12600 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5612601 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12602 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412603 PrivacyMode::PRIVACY_MODE_DISABLED,
12604 NetworkIsolationKey(),
12605 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012606 true,
bncce36dca22015-04-21 22:11:2312607 },
12608 {
Matt Menke4802de62019-03-08 22:47:5012609 "socks5://socks_proxy:1080",
12610 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5612611 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
12612 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412613 PrivacyMode::PRIVACY_MODE_DISABLED,
12614 NetworkIsolationKey(),
12615 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012616 true,
bncce36dca22015-04-21 22:11:2312617 },
[email protected]af3490e2010-10-16 21:02:2912618
bncce36dca22015-04-21 22:11:2312619 {
Matt Menke4802de62019-03-08 22:47:5012620 "socks4://socks_proxy:1080",
12621 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5612622 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
12623 ClientSocketPool::SocketType::kSsl,
dalyk51ab46b2019-10-15 15:14:3412624 PrivacyMode::PRIVACY_MODE_DISABLED,
12625 NetworkIsolationKey(),
12626 false /* disable_secure_dns */),
Matt Menke4802de62019-03-08 22:47:5012627 true,
bncce36dca22015-04-21 22:11:2312628 },
[email protected]04e5be32009-06-26 20:00:3112629 };
12630
Avi Drissman4365a4782018-12-28 19:26:2412631 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5912632 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5612633 ConfiguredProxyResolutionService::CreateFixed(
12634 tests[i].proxy_server, TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0912635 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5612636 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0212637
mmenkee65e7af2015-10-13 17:16:4212638 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3112639
Matt Menkee8648fa2019-01-17 16:47:0712640 ProxyServer proxy_server(
12641 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
12642 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5612643 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3612644 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1912645 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4012646 mock_pool_manager->SetSocketPool(proxy_server,
12647 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4812648 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3112649
bnc691fda62016-08-12 00:43:1612650 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3112651
[email protected]2d731a32010-04-29 01:04:0612652 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5612653 GroupIdTransactionHelper(tests[i].url, session.get()));
12654 EXPECT_EQ(tests[i].expected_group_id,
12655 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3112656 }
12657}
12658
bncd16676a2016-07-20 16:23:0112659TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2712660 HttpRequestInfo request;
12661 request.method = "GET";
bncce36dca22015-04-21 22:11:2312662 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012663 request.traffic_annotation =
12664 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2712665
Nicolas Arciniegad2013f92020-02-07 23:00:5612666 session_deps_.proxy_resolution_service =
12667 ConfiguredProxyResolutionService::CreateFixed(
12668 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3212669
[email protected]69719062010-01-05 20:09:2112670 // This simulates failure resolving all hostnames; that means we will fail
12671 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0712672 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3212673
danakj1fd259a02016-04-16 03:17:0912674 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612675 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2512676
[email protected]49639fa2011-12-20 23:22:4112677 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2512678
tfarina42834112016-09-22 13:38:2012679 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112680 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2512681
[email protected]9172a982009-06-06 00:30:2512682 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112683 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2512684}
12685
[email protected]0877e3d2009-10-17 22:29:5712686// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0112687TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5712688 HttpRequestInfo request;
12689 request.method = "GET";
12690 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1012691 request.traffic_annotation =
12692 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712693
12694 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0612695 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712696 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112697 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0712698 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912699 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712700
[email protected]49639fa2011-12-20 23:22:4112701 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712702
bnc691fda62016-08-12 00:43:1612703 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712704
tfarina42834112016-09-22 13:38:2012705 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112706 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712707
12708 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112709 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5912710
12711 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612712 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912713 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712714}
12715
zmo9528c9f42015-08-04 22:12:0812716// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0112717TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5712718 HttpRequestInfo request;
12719 request.method = "GET";
12720 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1012721 request.traffic_annotation =
12722 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712723
12724 MockRead data_reads[] = {
12725 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0612726 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712727 };
12728
Ryan Sleevib8d7ea02018-05-07 20:01:0112729 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712730 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0912731 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712732
[email protected]49639fa2011-12-20 23:22:4112733 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712734
bnc691fda62016-08-12 00:43:1612735 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712736
tfarina42834112016-09-22 13:38:2012737 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112738 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712739
12740 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112741 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812742
bnc691fda62016-08-12 00:43:1612743 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212744 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0812745
wezca1070932016-05-26 20:30:5212746 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0812747 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12748
12749 std::string response_data;
bnc691fda62016-08-12 00:43:1612750 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112751 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0812752 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5912753
12754 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1612755 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5912756 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5712757}
12758
12759// Make sure that a dropped connection while draining the body for auth
12760// restart does the right thing.
bncd16676a2016-07-20 16:23:0112761TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5712762 HttpRequestInfo request;
12763 request.method = "GET";
bncce36dca22015-04-21 22:11:2312764 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012765 request.traffic_annotation =
12766 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712767
12768 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312769 MockWrite(
12770 "GET / HTTP/1.1\r\n"
12771 "Host: www.example.org\r\n"
12772 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712773 };
12774
12775 MockRead data_reads1[] = {
12776 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
12777 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
12778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12779 MockRead("Content-Length: 14\r\n\r\n"),
12780 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0612781 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5712782 };
12783
Ryan Sleevib8d7ea02018-05-07 20:01:0112784 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0712785 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5712786
bnc691fda62016-08-12 00:43:1612787 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5712788 // be issuing -- the final header line contains the credentials.
12789 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2312790 MockWrite(
12791 "GET / HTTP/1.1\r\n"
12792 "Host: www.example.org\r\n"
12793 "Connection: keep-alive\r\n"
12794 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5712795 };
12796
12797 // Lastly, the server responds with the actual content.
12798 MockRead data_reads2[] = {
12799 MockRead("HTTP/1.1 200 OK\r\n"),
12800 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12801 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612802 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5712803 };
12804
Ryan Sleevib8d7ea02018-05-07 20:01:0112805 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0712806 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0912807 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5712808
[email protected]49639fa2011-12-20 23:22:4112809 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5712810
bnc691fda62016-08-12 00:43:1612811 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012812
tfarina42834112016-09-22 13:38:2012813 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112814 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712815
12816 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112817 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712818
bnc691fda62016-08-12 00:43:1612819 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212820 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812821 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5712822
[email protected]49639fa2011-12-20 23:22:4112823 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5712824
bnc691fda62016-08-12 00:43:1612825 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0112826 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712827
12828 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112829 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5712830
bnc691fda62016-08-12 00:43:1612831 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212832 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812833 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5712834 EXPECT_EQ(100, response->headers->GetContentLength());
12835}
12836
12837// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0112838TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Nicolas Arciniegad2013f92020-02-07 23:00:5612839 session_deps_.proxy_resolution_service =
12840 ConfiguredProxyResolutionService::CreateFixed(
12841 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712842
12843 HttpRequestInfo request;
12844 request.method = "GET";
bncce36dca22015-04-21 22:11:2312845 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012846 request.traffic_annotation =
12847 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5712848
12849 MockRead proxy_reads[] = {
12850 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0612851 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5712852 };
12853
Ryan Sleevib8d7ea02018-05-07 20:01:0112854 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0612855 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5712856
[email protected]bb88e1d32013-05-03 23:11:0712857 session_deps_.socket_factory->AddSocketDataProvider(&data);
12858 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5712859
[email protected]49639fa2011-12-20 23:22:4112860 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5712861
[email protected]bb88e1d32013-05-03 23:11:0712862 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5712863
danakj1fd259a02016-04-16 03:17:0912864 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612865 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5712866
tfarina42834112016-09-22 13:38:2012867 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112868 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5712869
12870 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112871 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5712872}
12873
bncd16676a2016-07-20 16:23:0112874TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4612875 HttpRequestInfo request;
12876 request.method = "GET";
bncce36dca22015-04-21 22:11:2312877 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012878 request.traffic_annotation =
12879 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4612880
danakj1fd259a02016-04-16 03:17:0912881 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612882 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2712883
[email protected]e22e1362009-11-23 21:31:1212884 MockRead data_reads[] = {
12885 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612886 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1212887 };
[email protected]9492e4a2010-02-24 00:58:4612888
Ryan Sleevib8d7ea02018-05-07 20:01:0112889 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712890 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4612891
[email protected]49639fa2011-12-20 23:22:4112892 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4612893
tfarina42834112016-09-22 13:38:2012894 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112895 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4612896
robpercival214763f2016-07-01 23:27:0112897 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4612898
bnc691fda62016-08-12 00:43:1612899 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212900 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4612901
wezca1070932016-05-26 20:30:5212902 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4612903 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
12904
12905 std::string response_data;
bnc691fda62016-08-12 00:43:1612906 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0112907 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1212908}
12909
bncd16676a2016-07-20 16:23:0112910TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1512911 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5212912 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1412913 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2112914 UploadFileElementReader::ScopedOverridingContentLengthForTests
12915 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3312916
danakj1fd259a02016-04-16 03:17:0912917 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912918 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412919 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0712920 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212921 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712922
12923 HttpRequestInfo request;
12924 request.method = "POST";
bncce36dca22015-04-21 22:11:2312925 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712926 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012927 request.traffic_annotation =
12928 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712929
danakj1fd259a02016-04-16 03:17:0912930 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612931 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3312932
12933 MockRead data_reads[] = {
12934 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
12935 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612936 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3312937 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112938 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712939 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3312940
[email protected]49639fa2011-12-20 23:22:4112941 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3312942
tfarina42834112016-09-22 13:38:2012943 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112944 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3312945
12946 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112947 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3312948
bnc691fda62016-08-12 00:43:1612949 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212950 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3312951
maksim.sisove869bf52016-06-23 17:11:5212952 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3312953
Lei Zhang6dfdc9b12020-06-29 22:15:3112954 base::DeleteFile(temp_file_path);
[email protected]95d88ffe2010-02-04 21:25:3312955}
12956
bncd16676a2016-07-20 16:23:0112957TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1512958 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5212959 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3612960 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4812961 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
12962 base::WriteFile(temp_file, temp_file_content.c_str(),
12963 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1112964 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3612965
danakj1fd259a02016-04-16 03:17:0912966 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1912967 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1412968 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0712969 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2212970 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2712971
12972 HttpRequestInfo request;
12973 request.method = "POST";
bncce36dca22015-04-21 22:11:2312974 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2712975 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1012976 request.traffic_annotation =
12977 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2712978
[email protected]999dd8c2013-11-12 06:45:5412979 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0912980 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612981 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3612982
Ryan Sleevib8d7ea02018-05-07 20:01:0112983 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0712984 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3612985
[email protected]49639fa2011-12-20 23:22:4112986 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3612987
tfarina42834112016-09-22 13:38:2012988 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112989 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3612990
12991 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112992 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3612993
Lei Zhang6dfdc9b12020-06-29 22:15:3112994 base::DeleteFile(temp_file);
[email protected]6624b4622010-03-29 19:58:3612995}
12996
bncd16676a2016-07-20 16:23:0112997TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0312998 class FakeUploadElementReader : public UploadElementReader {
12999 public:
Chris Watkins7a41d3552017-12-01 02:13:2713000 FakeUploadElementReader() = default;
13001 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0313002
Matt Menkecc1d3a902018-02-05 18:27:3313003 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0313004
13005 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3313006 int Init(CompletionOnceCallback callback) override {
13007 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0313008 return ERR_IO_PENDING;
13009 }
avibf0746c2015-12-09 19:53:1413010 uint64_t GetContentLength() const override { return 0; }
13011 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2013012 int Read(IOBuffer* buf,
13013 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3313014 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0313015 return ERR_FAILED;
13016 }
13017
13018 private:
Matt Menkecc1d3a902018-02-05 18:27:3313019 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0313020 };
13021
13022 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0913023 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
13024 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2213025 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0313026
13027 HttpRequestInfo request;
13028 request.method = "POST";
bncce36dca22015-04-21 22:11:2313029 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0313030 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1013031 request.traffic_annotation =
13032 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0313033
danakj1fd259a02016-04-16 03:17:0913034 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813035 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913036 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0313037
13038 StaticSocketDataProvider data;
13039 session_deps_.socket_factory->AddSocketDataProvider(&data);
13040
13041 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2013042 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113043 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5513044 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0313045
13046 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3313047 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
13048 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0313049
13050 // Return Init()'s result after the transaction gets destroyed.
13051 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3313052 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0313053}
13054
[email protected]aeefc9e82010-02-19 16:18:2713055// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0113056TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2713057 HttpRequestInfo request;
13058 request.method = "GET";
bncce36dca22015-04-21 22:11:2313059 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013060 request.traffic_annotation =
13061 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2713062
13063 // First transaction will request a resource and receive a Basic challenge
13064 // with realm="first_realm".
13065 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2313066 MockWrite(
13067 "GET / HTTP/1.1\r\n"
13068 "Host: www.example.org\r\n"
13069 "Connection: keep-alive\r\n"
13070 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713071 };
13072 MockRead data_reads1[] = {
13073 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13074 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
13075 "\r\n"),
13076 };
13077
bnc691fda62016-08-12 00:43:1613078 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2713079 // for first_realm. The server will reject and provide a challenge with
13080 // second_realm.
13081 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2313082 MockWrite(
13083 "GET / HTTP/1.1\r\n"
13084 "Host: www.example.org\r\n"
13085 "Connection: keep-alive\r\n"
13086 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
13087 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713088 };
13089 MockRead data_reads2[] = {
13090 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13091 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
13092 "\r\n"),
13093 };
13094
13095 // This again fails, and goes back to first_realm. Make sure that the
13096 // entry is removed from cache.
13097 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2313098 MockWrite(
13099 "GET / HTTP/1.1\r\n"
13100 "Host: www.example.org\r\n"
13101 "Connection: keep-alive\r\n"
13102 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
13103 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713104 };
13105 MockRead data_reads3[] = {
13106 MockRead("HTTP/1.1 401 Unauthorized\r\n"
13107 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
13108 "\r\n"),
13109 };
13110
13111 // Try one last time (with the correct password) and get the resource.
13112 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2313113 MockWrite(
13114 "GET / HTTP/1.1\r\n"
13115 "Host: www.example.org\r\n"
13116 "Connection: keep-alive\r\n"
13117 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
13118 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2713119 };
13120 MockRead data_reads4[] = {
13121 MockRead("HTTP/1.1 200 OK\r\n"
13122 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5013123 "Content-Length: 5\r\n"
13124 "\r\n"
13125 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2713126 };
13127
Ryan Sleevib8d7ea02018-05-07 20:01:0113128 StaticSocketDataProvider data1(data_reads1, data_writes1);
13129 StaticSocketDataProvider data2(data_reads2, data_writes2);
13130 StaticSocketDataProvider data3(data_reads3, data_writes3);
13131 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0713132 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13133 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13134 session_deps_.socket_factory->AddSocketDataProvider(&data3);
13135 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2713136
[email protected]49639fa2011-12-20 23:22:4113137 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2713138
danakj1fd259a02016-04-16 03:17:0913139 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613140 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5013141
[email protected]aeefc9e82010-02-19 16:18:2713142 // Issue the first request with Authorize headers. There should be a
13143 // password prompt for first_realm waiting to be filled in after the
13144 // transaction completes.
tfarina42834112016-09-22 13:38:2013145 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113146 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713147 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0113148 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613149 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213150 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813151 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213152 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413153 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313154 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413155 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913156 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713157
13158 // Issue the second request with an incorrect password. There should be a
13159 // password prompt for second_realm waiting to be filled in after the
13160 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4113161 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1613162 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
13163 callback2.callback());
robpercival214763f2016-07-01 23:27:0113164 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713165 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0113166 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613167 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213168 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813169 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213170 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413171 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313172 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413173 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913174 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713175
13176 // Issue the third request with another incorrect password. There should be
13177 // a password prompt for first_realm waiting to be filled in. If the password
13178 // prompt is not present, it indicates that the HttpAuthCacheEntry for
13179 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4113180 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1613181 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
13182 callback3.callback());
robpercival214763f2016-07-01 23:27:0113183 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713184 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0113185 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613186 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213187 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813188 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5213189 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0413190 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4313191 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0413192 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1913193 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2713194
13195 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4113196 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1613197 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
13198 callback4.callback());
robpercival214763f2016-07-01 23:27:0113199 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2713200 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0113201 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1613202 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213203 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5813204 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2713205}
13206
Bence Béky230ac612017-08-30 19:17:0813207// Regression test for https://crbug.com/754395.
13208TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
13209 MockRead data_reads[] = {
13210 MockRead("HTTP/1.1 200 OK\r\n"),
13211 MockRead(kAlternativeServiceHttpHeader),
13212 MockRead("\r\n"),
13213 MockRead("hello world"),
13214 MockRead(SYNCHRONOUS, OK),
13215 };
13216
13217 HttpRequestInfo request;
13218 request.method = "GET";
13219 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013220 request.traffic_annotation =
13221 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0813222
Ryan Sleevib8d7ea02018-05-07 20:01:0113223 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0813224 session_deps_.socket_factory->AddSocketDataProvider(&data);
13225
13226 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913227 ssl.ssl_info.cert =
13228 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13229 ASSERT_TRUE(ssl.ssl_info.cert);
13230 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0813231 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13232
13233 TestCompletionCallback callback;
13234
13235 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13236 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13237
13238 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13239 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13240
13241 url::SchemeHostPort test_server(request.url);
13242 HttpServerProperties* http_server_properties =
13243 session->http_server_properties();
13244 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913245 http_server_properties
13246 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13247 .empty());
Bence Béky230ac612017-08-30 19:17:0813248
13249 EXPECT_THAT(callback.WaitForResult(), IsOk());
13250
13251 const HttpResponseInfo* response = trans.GetResponseInfo();
13252 ASSERT_TRUE(response);
13253 ASSERT_TRUE(response->headers);
13254 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13255 EXPECT_FALSE(response->was_fetched_via_spdy);
13256 EXPECT_FALSE(response->was_alpn_negotiated);
13257
13258 std::string response_data;
13259 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13260 EXPECT_EQ("hello world", response_data);
13261
13262 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913263 http_server_properties
13264 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13265 .empty());
Bence Béky230ac612017-08-30 19:17:0813266}
13267
bncd16676a2016-07-20 16:23:0113268TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5213269 MockRead data_reads[] = {
13270 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313271 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213272 MockRead("\r\n"),
13273 MockRead("hello world"),
13274 MockRead(SYNCHRONOUS, OK),
13275 };
13276
13277 HttpRequestInfo request;
13278 request.method = "GET";
bncb26024382016-06-29 02:39:4513279 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013280 request.traffic_annotation =
13281 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213282
Ryan Sleevib8d7ea02018-05-07 20:01:0113283 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213284 session_deps_.socket_factory->AddSocketDataProvider(&data);
13285
bncb26024382016-06-29 02:39:4513286 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913287 ssl.ssl_info.cert =
13288 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13289 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513290 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13291
bncc958faa2015-07-31 18:14:5213292 TestCompletionCallback callback;
13293
danakj1fd259a02016-04-16 03:17:0913294 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613295 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213296
tfarina42834112016-09-22 13:38:2013297 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213299
bncb26024382016-06-29 02:39:4513300 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013301 HttpServerProperties* http_server_properties =
13302 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413303 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913304 http_server_properties
13305 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13306 .empty());
bncc958faa2015-07-31 18:14:5213307
robpercival214763f2016-07-01 23:27:0113308 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213309
bnc691fda62016-08-12 00:43:1613310 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213311 ASSERT_TRUE(response);
13312 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213313 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13314 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213315 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213316
13317 std::string response_data;
bnc691fda62016-08-12 00:43:1613318 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213319 EXPECT_EQ("hello world", response_data);
13320
zhongyic4de03032017-05-19 04:07:3413321 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913322 http_server_properties->GetAlternativeServiceInfos(test_server,
13323 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413324 ASSERT_EQ(1u, alternative_service_info_vector.size());
13325 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13326 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413327 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5213328}
13329
Matt Menke3233d8f22019-08-20 21:01:4913330TEST_F(HttpNetworkTransactionTest,
13331 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
13332 base::test::ScopedFeatureList feature_list;
13333 feature_list.InitWithFeatures(
13334 // enabled_features
13335 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
13336 // Need to partition connections by NetworkIsolationKey for
13337 // SpdySessionKeys to include NetworkIsolationKeys.
13338 features::kPartitionConnectionsByNetworkIsolationKey},
13339 // disabled_features
13340 {});
13341 // Since HttpServerProperties caches the feature value, have to create a new
13342 // one.
13343 session_deps_.http_server_properties =
13344 std::make_unique<HttpServerProperties>();
13345
13346 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
13347 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
13348 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
13349 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
13350
13351 MockRead data_reads[] = {
13352 MockRead("HTTP/1.1 200 OK\r\n"),
13353 MockRead(kAlternativeServiceHttpHeader),
13354 MockRead("\r\n"),
13355 MockRead("hello world"),
13356 MockRead(SYNCHRONOUS, OK),
13357 };
13358
13359 HttpRequestInfo request;
13360 request.method = "GET";
13361 request.url = GURL("https://www.example.org/");
13362 request.traffic_annotation =
13363 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13364 request.network_isolation_key = kNetworkIsolationKey1;
13365
13366 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
13367 session_deps_.socket_factory->AddSocketDataProvider(&data);
13368
13369 SSLSocketDataProvider ssl(ASYNC, OK);
13370 ssl.ssl_info.cert =
13371 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13372 ASSERT_TRUE(ssl.ssl_info.cert);
13373 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13374
13375 TestCompletionCallback callback;
13376
13377 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13378 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13379
13380 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13381 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13382
13383 url::SchemeHostPort test_server(request.url);
13384 HttpServerProperties* http_server_properties =
13385 session->http_server_properties();
13386 EXPECT_TRUE(
13387 http_server_properties
13388 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
13389 .empty());
13390
13391 EXPECT_THAT(callback.WaitForResult(), IsOk());
13392
13393 const HttpResponseInfo* response = trans.GetResponseInfo();
13394 ASSERT_TRUE(response);
13395 ASSERT_TRUE(response->headers);
13396 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13397 EXPECT_FALSE(response->was_fetched_via_spdy);
13398 EXPECT_FALSE(response->was_alpn_negotiated);
13399
13400 std::string response_data;
13401 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13402 EXPECT_EQ("hello world", response_data);
13403
13404 AlternativeServiceInfoVector alternative_service_info_vector =
13405 http_server_properties->GetAlternativeServiceInfos(test_server,
13406 kNetworkIsolationKey1);
13407 ASSERT_EQ(1u, alternative_service_info_vector.size());
13408 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
13409 EXPECT_EQ(alternative_service,
13410 alternative_service_info_vector[0].alternative_service());
13411
13412 // Make sure the alternative service information is only associated with
13413 // kNetworkIsolationKey1.
13414 EXPECT_TRUE(
13415 http_server_properties
13416 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13417 .empty());
13418 EXPECT_TRUE(
13419 http_server_properties
13420 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
13421 .empty());
13422}
13423
bnce3dd56f2016-06-01 10:37:1113424// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0113425TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113426 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1113427 MockRead data_reads[] = {
13428 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313429 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1113430 MockRead("\r\n"),
13431 MockRead("hello world"),
13432 MockRead(SYNCHRONOUS, OK),
13433 };
13434
13435 HttpRequestInfo request;
13436 request.method = "GET";
13437 request.url = GURL("http://www.example.org/");
13438 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013439 request.traffic_annotation =
13440 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113441
Ryan Sleevib8d7ea02018-05-07 20:01:0113442 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113443 session_deps_.socket_factory->AddSocketDataProvider(&data);
13444
13445 TestCompletionCallback callback;
13446
13447 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613448 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113449
13450 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4013451 HttpServerProperties* http_server_properties =
13452 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413453 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913454 http_server_properties
13455 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13456 .empty());
bnce3dd56f2016-06-01 10:37:1113457
tfarina42834112016-09-22 13:38:2013458 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113459 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13460 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1113461
bnc691fda62016-08-12 00:43:1613462 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1113463 ASSERT_TRUE(response);
13464 ASSERT_TRUE(response->headers);
13465 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13466 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213467 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1113468
13469 std::string response_data;
bnc691fda62016-08-12 00:43:1613470 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1113471 EXPECT_EQ("hello world", response_data);
13472
zhongyic4de03032017-05-19 04:07:3413473 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913474 http_server_properties
13475 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13476 .empty());
bnce3dd56f2016-06-01 10:37:1113477}
13478
bnca86731e2017-04-17 12:31:2813479// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2513480// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0113481TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2513482 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2813483 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4513484
bnc8bef8da22016-05-30 01:28:2513485 HttpRequestInfo request;
13486 request.method = "GET";
bncb26024382016-06-29 02:39:4513487 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2513488 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013489 request.traffic_annotation =
13490 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2513491
13492 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13493 StaticSocketDataProvider first_data;
13494 first_data.set_connect_data(mock_connect);
13495 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513496 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613497 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513498 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2513499
13500 MockRead data_reads[] = {
13501 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13502 MockRead(ASYNC, OK),
13503 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113504 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2513505 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13506
13507 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13508
bnc525e175a2016-06-20 12:36:4013509 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2513510 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113511 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
13512 444);
bnc8bef8da22016-05-30 01:28:2513513 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113514 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713515 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13516 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2513517
bnc691fda62016-08-12 00:43:1613518 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2513519 TestCompletionCallback callback;
13520
tfarina42834112016-09-22 13:38:2013521 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2513522 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113523 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2513524}
13525
bnce3dd56f2016-06-01 10:37:1113526// Regression test for https://crbug.com/615497:
13527// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0113528TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1113529 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1113530 HttpRequestInfo request;
13531 request.method = "GET";
13532 request.url = GURL("http://www.example.org/");
13533 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013534 request.traffic_annotation =
13535 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1113536
13537 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13538 StaticSocketDataProvider first_data;
13539 first_data.set_connect_data(mock_connect);
13540 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
13541
13542 MockRead data_reads[] = {
13543 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
13544 MockRead(ASYNC, OK),
13545 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113546 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1113547 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
13548
13549 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13550
bnc525e175a2016-06-20 12:36:4013551 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1113552 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113553 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1113554 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113555 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713556 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13557 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1113558
bnc691fda62016-08-12 00:43:1613559 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1113560 TestCompletionCallback callback;
13561
tfarina42834112016-09-22 13:38:2013562 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1113563 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0113564 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1113565}
13566
bncd16676a2016-07-20 16:23:0113567TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0813568 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0913569 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013570 HttpServerProperties* http_server_properties =
13571 session->http_server_properties();
bncb26024382016-06-29 02:39:4513572 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2113573 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0813574 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113575 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713576 test_server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813577 session->context().quic_context->params()->supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4913578 EXPECT_EQ(1u,
13579 http_server_properties
13580 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13581 .size());
bnc4f575852015-10-14 18:35:0813582
13583 // Send a clear header.
13584 MockRead data_reads[] = {
13585 MockRead("HTTP/1.1 200 OK\r\n"),
13586 MockRead("Alt-Svc: clear\r\n"),
13587 MockRead("\r\n"),
13588 MockRead("hello world"),
13589 MockRead(SYNCHRONOUS, OK),
13590 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113591 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0813592 session_deps_.socket_factory->AddSocketDataProvider(&data);
13593
bncb26024382016-06-29 02:39:4513594 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913595 ssl.ssl_info.cert =
13596 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13597 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513598 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13599
bnc4f575852015-10-14 18:35:0813600 HttpRequestInfo request;
13601 request.method = "GET";
bncb26024382016-06-29 02:39:4513602 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013603 request.traffic_annotation =
13604 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0813605
13606 TestCompletionCallback callback;
13607
bnc691fda62016-08-12 00:43:1613608 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0813609
tfarina42834112016-09-22 13:38:2013610 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113611 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0813612
bnc691fda62016-08-12 00:43:1613613 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213614 ASSERT_TRUE(response);
13615 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0813616 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13617 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213618 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0813619
13620 std::string response_data;
bnc691fda62016-08-12 00:43:1613621 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0813622 EXPECT_EQ("hello world", response_data);
13623
zhongyic4de03032017-05-19 04:07:3413624 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913625 http_server_properties
13626 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13627 .empty());
bnc4f575852015-10-14 18:35:0813628}
13629
bncd16676a2016-07-20 16:23:0113630TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5213631 MockRead data_reads[] = {
13632 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313633 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
13634 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5213635 MockRead("hello world"),
13636 MockRead(SYNCHRONOUS, OK),
13637 };
13638
13639 HttpRequestInfo request;
13640 request.method = "GET";
bncb26024382016-06-29 02:39:4513641 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013642 request.traffic_annotation =
13643 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5213644
Ryan Sleevib8d7ea02018-05-07 20:01:0113645 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5213646 session_deps_.socket_factory->AddSocketDataProvider(&data);
13647
bncb26024382016-06-29 02:39:4513648 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913649 ssl.ssl_info.cert =
13650 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13651 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4513652 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13653
bncc958faa2015-07-31 18:14:5213654 TestCompletionCallback callback;
13655
danakj1fd259a02016-04-16 03:17:0913656 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1613657 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5213658
tfarina42834112016-09-22 13:38:2013659 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113660 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5213661
bncb26024382016-06-29 02:39:4513662 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4013663 HttpServerProperties* http_server_properties =
13664 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3413665 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4913666 http_server_properties
13667 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
13668 .empty());
bncc958faa2015-07-31 18:14:5213669
robpercival214763f2016-07-01 23:27:0113670 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5213671
bnc691fda62016-08-12 00:43:1613672 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213673 ASSERT_TRUE(response);
13674 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5213675 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13676 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213677 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5213678
13679 std::string response_data;
bnc691fda62016-08-12 00:43:1613680 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5213681 EXPECT_EQ("hello world", response_data);
13682
zhongyic4de03032017-05-19 04:07:3413683 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913684 http_server_properties->GetAlternativeServiceInfos(test_server,
13685 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413686 ASSERT_EQ(2u, alternative_service_info_vector.size());
13687
13688 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
13689 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413690 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3413691 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
13692 1234);
13693 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5413694 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5213695}
13696
bncd16676a2016-07-20 16:23:0113697TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613698 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213699 HostPortPair alternative("alternative.example.org", 443);
13700 std::string origin_url = "https://origin.example.org:443";
13701 std::string alternative_url = "https://alternative.example.org:443";
13702
13703 // Negotiate HTTP/1.1 with alternative.example.org.
13704 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613705 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213706 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13707
13708 // HTTP/1.1 data for request.
13709 MockWrite http_writes[] = {
13710 MockWrite("GET / HTTP/1.1\r\n"
13711 "Host: alternative.example.org\r\n"
13712 "Connection: keep-alive\r\n\r\n"),
13713 };
13714
13715 MockRead http_reads[] = {
13716 MockRead("HTTP/1.1 200 OK\r\n"
13717 "Content-Type: text/html; charset=iso-8859-1\r\n"
13718 "Content-Length: 40\r\n\r\n"
13719 "first HTTP/1.1 response from alternative"),
13720 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113721 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213722 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13723
13724 StaticSocketDataProvider data_refused;
13725 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13726 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13727
zhongyi3d4a55e72016-04-22 20:36:4613728 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0913729 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013730 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213731 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2113732 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0213733 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113734 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713735 server, NetworkIsolationKey(), alternative_service, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813736 DefaultSupportedQuicVersions());
zhongyi48704c182015-12-07 07:52:0213737 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513738 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
13739 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0213740
zhongyi48704c182015-12-07 07:52:0213741 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613742 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213743 request.method = "GET";
13744 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1013745 request.traffic_annotation =
13746 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13747
zhongyi48704c182015-12-07 07:52:0213748 TestCompletionCallback callback;
13749 NetErrorDetails details;
13750 EXPECT_FALSE(details.quic_broken);
13751
tfarina42834112016-09-22 13:38:2013752 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613753 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213754 EXPECT_TRUE(details.quic_broken);
13755}
13756
bncd16676a2016-07-20 16:23:0113757TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4613758 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0213759 HostPortPair alternative1("alternative1.example.org", 443);
13760 HostPortPair alternative2("alternative2.example.org", 443);
13761 std::string origin_url = "https://origin.example.org:443";
13762 std::string alternative_url1 = "https://alternative1.example.org:443";
13763 std::string alternative_url2 = "https://alternative2.example.org:443";
13764
13765 // Negotiate HTTP/1.1 with alternative1.example.org.
13766 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613767 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0213768 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13769
13770 // HTTP/1.1 data for request.
13771 MockWrite http_writes[] = {
13772 MockWrite("GET / HTTP/1.1\r\n"
13773 "Host: alternative1.example.org\r\n"
13774 "Connection: keep-alive\r\n\r\n"),
13775 };
13776
13777 MockRead http_reads[] = {
13778 MockRead("HTTP/1.1 200 OK\r\n"
13779 "Content-Type: text/html; charset=iso-8859-1\r\n"
13780 "Content-Length: 40\r\n\r\n"
13781 "first HTTP/1.1 response from alternative1"),
13782 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113783 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0213784 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13785
13786 StaticSocketDataProvider data_refused;
13787 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13788 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13789
danakj1fd259a02016-04-16 03:17:0913790 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013791 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0213792 session->http_server_properties();
13793
zhongyi3d4a55e72016-04-22 20:36:4613794 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0213795 AlternativeServiceInfoVector alternative_service_info_vector;
13796 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
13797
bnc3472afd2016-11-17 15:27:2113798 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2113799 alternative_service_info_vector.push_back(
13800 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13801 alternative_service1, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813802 session->context().quic_context->params()->supported_versions));
bnc3472afd2016-11-17 15:27:2113803 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2113804 alternative_service_info_vector.push_back(
13805 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
13806 alternative_service2, expiration,
Victor Vasilieva1e66d72019-12-05 17:55:3813807 session->context().quic_context->params()->supported_versions));
zhongyi48704c182015-12-07 07:52:0213808
13809 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4913810 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0213811
13812 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0513813 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
13814 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4913815 EXPECT_EQ(2u, http_server_properties
13816 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
13817 .size());
zhongyi48704c182015-12-07 07:52:0213818
zhongyi48704c182015-12-07 07:52:0213819 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4613820 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0213821 request.method = "GET";
13822 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1013823 request.traffic_annotation =
13824 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13825
zhongyi48704c182015-12-07 07:52:0213826 TestCompletionCallback callback;
13827 NetErrorDetails details;
13828 EXPECT_FALSE(details.quic_broken);
13829
tfarina42834112016-09-22 13:38:2013830 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1613831 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0213832 EXPECT_FALSE(details.quic_broken);
13833}
13834
bncd16676a2016-07-20 16:23:0113835TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4213836 HttpRequestInfo request;
13837 request.method = "GET";
bncb26024382016-06-29 02:39:4513838 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013839 request.traffic_annotation =
13840 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4213841
[email protected]d973e99a2012-02-17 21:02:3613842 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4213843 StaticSocketDataProvider first_data;
13844 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713845 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4513846 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613847 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513848 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4213849
13850 MockRead data_reads[] = {
13851 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13852 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613853 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4213854 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113855 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713856 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4213857
danakj1fd259a02016-04-16 03:17:0913858 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4213859
bnc525e175a2016-06-20 12:36:4013860 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313861 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4613862 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1113863 // Port must be < 1024, or the header will be ignored (since initial port was
13864 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2113865 // Port is ignored by MockConnect anyway.
13866 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13867 666);
bnc7dc7e1b42015-07-28 14:43:1213868 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113869 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713870 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4213871
bnc691fda62016-08-12 00:43:1613872 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113873 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4213874
tfarina42834112016-09-22 13:38:2013875 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113876 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13877 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4213878
bnc691fda62016-08-12 00:43:1613879 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213880 ASSERT_TRUE(response);
13881 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4213882 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13883
13884 std::string response_data;
bnc691fda62016-08-12 00:43:1613885 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4213886 EXPECT_EQ("hello world", response_data);
13887
zhongyic4de03032017-05-19 04:07:3413888 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4913889 http_server_properties->GetAlternativeServiceInfos(server,
13890 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3413891 ASSERT_EQ(1u, alternative_service_info_vector.size());
13892 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5413893 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0513894 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
13895 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4213896}
13897
bnc55ff9da2015-08-19 18:42:3513898// Ensure that we are not allowed to redirect traffic via an alternate protocol
13899// to an unrestricted (port >= 1024) when the original traffic was on a
13900// restricted port (port < 1024). Ensure that we can redirect in all other
13901// cases.
bncd16676a2016-07-20 16:23:0113902TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1113903 HttpRequestInfo restricted_port_request;
13904 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513905 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1113906 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013907 restricted_port_request.traffic_annotation =
13908 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1113909
[email protected]d973e99a2012-02-17 21:02:3613910 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1113911 StaticSocketDataProvider first_data;
13912 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713913 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1113914
13915 MockRead data_reads[] = {
13916 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13917 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613918 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1113919 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113920 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713921 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513922 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613923 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513924 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1113925
danakj1fd259a02016-04-16 03:17:0913926 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1113927
bnc525e175a2016-06-20 12:36:4013928 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5313929 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1113930 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113931 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13932 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213933 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113934 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713935 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13936 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113937
bnc691fda62016-08-12 00:43:1613938 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113939 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113940
tfarina42834112016-09-22 13:38:2013941 int rv = trans.Start(&restricted_port_request, callback.callback(),
13942 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113944 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0113945 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1913946}
[email protected]3912662a32011-10-04 00:51:1113947
bnc55ff9da2015-08-19 18:42:3513948// Ensure that we are allowed to redirect traffic via an alternate protocol to
13949// an unrestricted (port >= 1024) when the original traffic was on a restricted
13950// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0113951TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0713952 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1913953
13954 HttpRequestInfo restricted_port_request;
13955 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4513956 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1913957 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013958 restricted_port_request.traffic_annotation =
13959 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1913960
13961 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13962 StaticSocketDataProvider first_data;
13963 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0713964 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1913965
13966 MockRead data_reads[] = {
13967 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13968 MockRead("hello world"),
13969 MockRead(ASYNC, OK),
13970 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113971 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713972 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4513973 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613974 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513975 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1913976
danakj1fd259a02016-04-16 03:17:0913977 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1913978
bnc525e175a2016-06-20 12:36:4013979 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1913980 session->http_server_properties();
13981 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2113982 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13983 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213984 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113985 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713986 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
13987 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1913988
bnc691fda62016-08-12 00:43:1613989 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1913990 TestCompletionCallback callback;
13991
tfarina42834112016-09-22 13:38:2013992 EXPECT_EQ(ERR_IO_PENDING,
13993 trans.Start(&restricted_port_request, callback.callback(),
13994 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1913995 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0113996 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113997}
13998
bnc55ff9da2015-08-19 18:42:3513999// Ensure that we are not allowed to redirect traffic via an alternate protocol
14000// to an unrestricted (port >= 1024) when the original traffic was on a
14001// restricted port (port < 1024). Ensure that we can redirect in all other
14002// cases.
bncd16676a2016-07-20 16:23:0114003TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1114004 HttpRequestInfo restricted_port_request;
14005 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514006 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1114007 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1014008 restricted_port_request.traffic_annotation =
14009 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114010
[email protected]d973e99a2012-02-17 21:02:3614011 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114012 StaticSocketDataProvider first_data;
14013 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714014 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114015
14016 MockRead data_reads[] = {
14017 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14018 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614019 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114020 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114021 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714022 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1114023
bncb26024382016-06-29 02:39:4514024 SSLSocketDataProvider ssl(ASYNC, OK);
14025 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14026
danakj1fd259a02016-04-16 03:17:0914027 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114028
bnc525e175a2016-06-20 12:36:4014029 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314030 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1114031 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2114032 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14033 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214034 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114035 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714036 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
14037 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114038
bnc691fda62016-08-12 00:43:1614039 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114040 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114041
tfarina42834112016-09-22 13:38:2014042 int rv = trans.Start(&restricted_port_request, callback.callback(),
14043 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114044 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114045 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0114046 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1114047}
14048
bnc55ff9da2015-08-19 18:42:3514049// Ensure that we are not allowed to redirect traffic via an alternate protocol
14050// to an unrestricted (port >= 1024) when the original traffic was on a
14051// restricted port (port < 1024). Ensure that we can redirect in all other
14052// cases.
bncd16676a2016-07-20 16:23:0114053TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1114054 HttpRequestInfo unrestricted_port_request;
14055 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514056 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1114057 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1014058 unrestricted_port_request.traffic_annotation =
14059 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114060
[email protected]d973e99a2012-02-17 21:02:3614061 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114062 StaticSocketDataProvider first_data;
14063 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714064 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114065
14066 MockRead data_reads[] = {
14067 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14068 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614069 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114070 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114071 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714072 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4514073 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614074 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514075 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1114076
danakj1fd259a02016-04-16 03:17:0914077 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114078
bnc525e175a2016-06-20 12:36:4014079 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314080 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1114081 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2114082 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14083 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214084 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114085 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714086 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
14087 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114088
bnc691fda62016-08-12 00:43:1614089 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114090 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114091
bnc691fda62016-08-12 00:43:1614092 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2014093 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114094 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114095 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0114096 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1114097}
14098
bnc55ff9da2015-08-19 18:42:3514099// Ensure that we are not allowed to redirect traffic via an alternate protocol
14100// to an unrestricted (port >= 1024) when the original traffic was on a
14101// restricted port (port < 1024). Ensure that we can redirect in all other
14102// cases.
bncd16676a2016-07-20 16:23:0114103TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1114104 HttpRequestInfo unrestricted_port_request;
14105 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4514106 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1114107 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1014108 unrestricted_port_request.traffic_annotation =
14109 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1114110
[email protected]d973e99a2012-02-17 21:02:3614111 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1114112 StaticSocketDataProvider first_data;
14113 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714114 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1114115
14116 MockRead data_reads[] = {
14117 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14118 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614119 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1114120 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114121 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714122 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1114123
bncb26024382016-06-29 02:39:4514124 SSLSocketDataProvider ssl(ASYNC, OK);
14125 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14126
danakj1fd259a02016-04-16 03:17:0914127 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1114128
bnc525e175a2016-06-20 12:36:4014129 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5314130 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2214131 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2114132 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14133 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1214134 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114135 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714136 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
14137 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1114138
bnc691fda62016-08-12 00:43:1614139 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114140 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1114141
bnc691fda62016-08-12 00:43:1614142 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2014143 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114144 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1114145 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0114146 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1114147}
14148
bnc55ff9da2015-08-19 18:42:3514149// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2114150// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
14151// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0114152TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0214153 HttpRequestInfo request;
14154 request.method = "GET";
bncce36dca22015-04-21 22:11:2314155 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014156 request.traffic_annotation =
14157 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0214158
14159 // The alternate protocol request will error out before we attempt to connect,
14160 // so only the standard HTTP request will try to connect.
14161 MockRead data_reads[] = {
14162 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
14163 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0614164 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0214165 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114166 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714167 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0214168
danakj1fd259a02016-04-16 03:17:0914169 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0214170
bnc525e175a2016-06-20 12:36:4014171 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0214172 session->http_server_properties();
14173 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2114174 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
14175 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1214176 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114177 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714178 url::SchemeHostPort(request.url), NetworkIsolationKey(),
14179 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0214180
bnc691fda62016-08-12 00:43:1614181 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0214182 TestCompletionCallback callback;
14183
tfarina42834112016-09-22 13:38:2014184 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114185 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0214186 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0114187 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0214188
bnc691fda62016-08-12 00:43:1614189 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214190 ASSERT_TRUE(response);
14191 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0214192 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14193
14194 std::string response_data;
bnc691fda62016-08-12 00:43:1614195 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0214196 EXPECT_EQ("hello world", response_data);
14197}
14198
bncd16676a2016-07-20 16:23:0114199TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5414200 HttpRequestInfo request;
14201 request.method = "GET";
bncb26024382016-06-29 02:39:4514202 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014203 request.traffic_annotation =
14204 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414205
14206 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214207 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314208 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214209 MockRead("\r\n"),
14210 MockRead("hello world"),
14211 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14212 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5414213
Ryan Sleevib8d7ea02018-05-07 20:01:0114214 StaticSocketDataProvider first_transaction(data_reads,
14215 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714216 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514217 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614218 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514219 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414220
bnc032658ba2016-09-26 18:17:1514221 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414222
Ryan Hamilton0239aac2018-05-19 00:03:1314223 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514224 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114225 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414226
Raul Tambre94493c652019-03-11 17:18:3514227 spdy::SpdySerializedFrame resp(
14228 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314229 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414230 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114231 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414232 };
14233
Ryan Sleevib8d7ea02018-05-07 20:01:0114234 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714235 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414236
[email protected]d973e99a2012-02-17 21:02:3614237 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114238 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514239 hanging_non_alternate_protocol_socket.set_connect_data(
14240 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714241 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514242 &hanging_non_alternate_protocol_socket);
14243
[email protected]49639fa2011-12-20 23:22:4114244 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414245
danakj1fd259a02016-04-16 03:17:0914246 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814247 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914248 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414249
tfarina42834112016-09-22 13:38:2014250 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114251 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14252 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414253
14254 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214255 ASSERT_TRUE(response);
14256 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414257 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14258
14259 std::string response_data;
robpercival214763f2016-07-01 23:27:0114260 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414261 EXPECT_EQ("hello world", response_data);
14262
bnc87dcefc2017-05-25 12:47:5814263 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914264 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414265
tfarina42834112016-09-22 13:38:2014266 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114267 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14268 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414269
14270 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214271 ASSERT_TRUE(response);
14272 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214273 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314274 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214275 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414276
robpercival214763f2016-07-01 23:27:0114277 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414278 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5414279}
14280
bncd16676a2016-07-20 16:23:0114281TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5514282 HttpRequestInfo request;
14283 request.method = "GET";
bncb26024382016-06-29 02:39:4514284 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014285 request.traffic_annotation =
14286 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514287
bncb26024382016-06-29 02:39:4514288 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5514289 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214290 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314291 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214292 MockRead("\r\n"),
14293 MockRead("hello world"),
14294 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14295 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514296 };
14297
Ryan Sleevib8d7ea02018-05-07 20:01:0114298 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4514299 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5514300
bncb26024382016-06-29 02:39:4514301 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914302 ssl_http11.ssl_info.cert =
14303 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14304 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4514305 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
14306
14307 // Second transaction starts an alternative and a non-alternative Job.
14308 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3614309 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114310 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1814311 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1814312 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
14313
Ryan Sleevib8d7ea02018-05-07 20:01:0114314 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1814315 hanging_socket2.set_connect_data(never_finishing_connect);
14316 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5514317
bncb26024382016-06-29 02:39:4514318 // Third transaction starts an alternative and a non-alternative job.
14319 // The non-alternative job hangs, but the alternative one succeeds.
14320 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1314321 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4514322 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1314323 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4514324 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5514325 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4114326 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5514327 };
Raul Tambre94493c652019-03-11 17:18:3514328 spdy::SpdySerializedFrame resp1(
14329 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314330 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3514331 spdy::SpdySerializedFrame resp2(
14332 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1314333 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5514334 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114335 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
14336 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1314337 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5514338 };
14339
Ryan Sleevib8d7ea02018-05-07 20:01:0114340 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714341 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5514342
bnc032658ba2016-09-26 18:17:1514343 AddSSLSocketData();
bncb26024382016-06-29 02:39:4514344
Ryan Sleevib8d7ea02018-05-07 20:01:0114345 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1814346 hanging_socket3.set_connect_data(never_finishing_connect);
14347 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5514348
danakj1fd259a02016-04-16 03:17:0914349 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4114350 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5014351 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514352
tfarina42834112016-09-22 13:38:2014353 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114354 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14355 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514356
14357 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5214358 ASSERT_TRUE(response);
14359 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514360 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14361
14362 std::string response_data;
robpercival214763f2016-07-01 23:27:0114363 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514364 EXPECT_EQ("hello world", response_data);
14365
[email protected]49639fa2011-12-20 23:22:4114366 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5014367 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014368 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114369 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514370
[email protected]49639fa2011-12-20 23:22:4114371 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5014372 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2014373 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114374 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5514375
robpercival214763f2016-07-01 23:27:0114376 EXPECT_THAT(callback2.WaitForResult(), IsOk());
14377 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514378
14379 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5214380 ASSERT_TRUE(response);
14381 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214382 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514383 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214384 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114385 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514386 EXPECT_EQ("hello!", response_data);
14387
14388 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5214389 ASSERT_TRUE(response);
14390 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214391 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5514392 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214393 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0114394 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514395 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5514396}
14397
bncd16676a2016-07-20 16:23:0114398TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5314399 session_deps_.host_resolver->set_synchronous_mode(true);
14400
[email protected]2d6728692011-03-12 01:39:5514401 HttpRequestInfo request;
14402 request.method = "GET";
bncb26024382016-06-29 02:39:4514403 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014404 request.traffic_annotation =
14405 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5514406
14407 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214408 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314409 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214410 MockRead("\r\n"),
14411 MockRead("hello world"),
14412 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14413 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5514414 };
14415
Ryan Sleevib8d7ea02018-05-07 20:01:0114416 StaticSocketDataProvider first_transaction(data_reads,
14417 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714418 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5514419
[email protected]8ddf8322012-02-23 18:08:0614420 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4914421 ssl.ssl_info.cert =
14422 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
14423 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0714424 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514425
[email protected]d973e99a2012-02-17 21:02:3614426 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114427 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514428 hanging_alternate_protocol_socket.set_connect_data(
14429 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714430 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514431 &hanging_alternate_protocol_socket);
14432
bncb26024382016-06-29 02:39:4514433 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0114434 StaticSocketDataProvider second_transaction(data_reads,
14435 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1814436 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4514437 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5514438
[email protected]49639fa2011-12-20 23:22:4114439 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5514440
danakj1fd259a02016-04-16 03:17:0914441 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814442 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914443 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514444
tfarina42834112016-09-22 13:38:2014445 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114446 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14447 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514448
14449 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214450 ASSERT_TRUE(response);
14451 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514452 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14453
14454 std::string response_data;
robpercival214763f2016-07-01 23:27:0114455 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514456 EXPECT_EQ("hello world", response_data);
14457
bnc87dcefc2017-05-25 12:47:5814458 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914459 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5514460
tfarina42834112016-09-22 13:38:2014461 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114462 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14463 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5514464
14465 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214466 ASSERT_TRUE(response);
14467 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5514468 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14469 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214470 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5514471
robpercival214763f2016-07-01 23:27:0114472 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5514473 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5514474}
14475
bnc2e884782016-08-11 19:45:1914476// Test that proxy is resolved using the origin url,
14477// regardless of the alternative server.
14478TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
14479 // Configure proxy to bypass www.example.org, which is the origin URL.
14480 ProxyConfig proxy_config;
14481 proxy_config.proxy_rules().ParseFromString("myproxy:70");
14482 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4914483 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
14484 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1914485
14486 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1914487 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1914488 &capturing_proxy_resolver);
14489
Matt Muellerd9342e3a2019-11-26 01:41:1414490 RecordingTestNetLog net_log;
bnc2e884782016-08-11 19:45:1914491
Bence Béky53a5aef2018-03-29 21:54:1214492 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614493 std::make_unique<ConfiguredProxyResolutionService>(
Bence Béky53a5aef2018-03-29 21:54:1214494 std::move(proxy_config_service), std::move(proxy_resolver_factory),
Eric Roman3be01ba2020-04-03 21:37:0914495 &net_log, /*quick_check_enabled=*/true);
bnc2e884782016-08-11 19:45:1914496
14497 session_deps_.net_log = &net_log;
14498
14499 // Configure alternative service with a hostname that is not bypassed by the
14500 // proxy.
14501 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14502 HttpServerProperties* http_server_properties =
14503 session->http_server_properties();
14504 url::SchemeHostPort server("https", "www.example.org", 443);
14505 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2114506 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1914507 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2114508 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0714509 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1914510
14511 // Non-alternative job should hang.
14512 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114513 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1914514 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
14515 session_deps_.socket_factory->AddSocketDataProvider(
14516 &hanging_alternate_protocol_socket);
14517
bnc032658ba2016-09-26 18:17:1514518 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1914519
14520 HttpRequestInfo request;
14521 request.method = "GET";
14522 request.url = GURL("https://www.example.org/");
14523 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1014524 request.traffic_annotation =
14525 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1914526
Ryan Hamilton0239aac2018-05-19 00:03:1314527 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1914528 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
14529
14530 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
14531
Ryan Hamilton0239aac2018-05-19 00:03:1314532 spdy::SpdySerializedFrame resp(
14533 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
14534 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1914535 MockRead spdy_reads[] = {
14536 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
14537 };
14538
Ryan Sleevib8d7ea02018-05-07 20:01:0114539 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1914540 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
14541
14542 TestCompletionCallback callback;
14543
14544 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14545
tfarina42834112016-09-22 13:38:2014546 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1914547 EXPECT_THAT(callback.GetResult(rv), IsOk());
14548
14549 const HttpResponseInfo* response = trans.GetResponseInfo();
14550 ASSERT_TRUE(response);
14551 ASSERT_TRUE(response->headers);
14552 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
14553 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214554 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1914555
14556 std::string response_data;
14557 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
14558 EXPECT_EQ("hello!", response_data);
14559
14560 // Origin host bypasses proxy, no resolution should have happened.
Matt Menke8045afd2019-11-14 20:31:1914561 ASSERT_TRUE(capturing_proxy_resolver.lookup_info().empty());
bnc2e884782016-08-11 19:45:1914562}
14563
bncd16676a2016-07-20 16:23:0114564TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1114565 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4214566 proxy_config.set_auto_detect(true);
14567 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1114568
sammc5dd160c2015-04-02 02:43:1314569 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4914570 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5614571 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4914572 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
14573 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
14574 std::make_unique<CapturingProxyResolverFactory>(
14575 &capturing_proxy_resolver),
Eric Roman3be01ba2020-04-03 21:37:0914576 nullptr, /*quick_check_enabled=*/true);
Matt Muellerd9342e3a2019-11-26 01:41:1414577 RecordingTestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0714578 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1114579
14580 HttpRequestInfo request;
14581 request.method = "GET";
bncb26024382016-06-29 02:39:4514582 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014583 request.traffic_annotation =
14584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1114585
14586 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214587 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314588 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214589 MockRead("\r\n"),
14590 MockRead("hello world"),
14591 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
14592 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1114593 };
14594
Ryan Sleevib8d7ea02018-05-07 20:01:0114595 StaticSocketDataProvider first_transaction(data_reads,
14596 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714597 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514598 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614599 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1114601
bnc032658ba2016-09-26 18:17:1514602 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1114603
Ryan Hamilton0239aac2018-05-19 00:03:1314604 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514605 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1114606 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1314607 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2514608 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14609 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1314610 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4114611 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1114612 };
14613
[email protected]d911f1b2010-05-05 22:39:4214614 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
14615
Raul Tambre94493c652019-03-11 17:18:3514616 spdy::SpdySerializedFrame resp(
14617 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314618 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1114619 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114620 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
14621 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1114622 };
14623
Ryan Sleevib8d7ea02018-05-07 20:01:0114624 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714625 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1114626
[email protected]d973e99a2012-02-17 21:02:3614627 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0114628 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5514629 hanging_non_alternate_protocol_socket.set_connect_data(
14630 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0714631 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5514632 &hanging_non_alternate_protocol_socket);
14633
[email protected]49639fa2011-12-20 23:22:4114634 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1114635
danakj1fd259a02016-04-16 03:17:0914636 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814637 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914638 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114639
tfarina42834112016-09-22 13:38:2014640 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4114641 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14642 EXPECT_THAT(callback.WaitForResult(), IsOk());
14643
14644 const HttpResponseInfo* response = trans->GetResponseInfo();
14645 ASSERT_TRUE(response);
14646 ASSERT_TRUE(response->headers);
14647 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
14648 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214649 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4114650
14651 std::string response_data;
14652 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
14653 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1114654
bnc87dcefc2017-05-25 12:47:5814655 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914656 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1114657
tfarina42834112016-09-22 13:38:2014658 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114659 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14660 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1114661
mmenkea2dcd3bf2016-08-16 21:49:4114662 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214663 ASSERT_TRUE(response);
14664 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214665 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314666 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214667 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1114668
robpercival214763f2016-07-01 23:27:0114669 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1114670 EXPECT_EQ("hello!", response_data);
Matt Menke8045afd2019-11-14 20:31:1914671 ASSERT_EQ(2u, capturing_proxy_resolver.lookup_info().size());
bncb26024382016-06-29 02:39:4514672 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914673 capturing_proxy_resolver.lookup_info()[0].url.spec());
bncce36dca22015-04-21 22:11:2314674 EXPECT_EQ("https://www.example.org/",
Matt Menke8045afd2019-11-14 20:31:1914675 capturing_proxy_resolver.lookup_info()[1].url.spec());
[email protected]631f1322010-04-30 17:59:1114676
[email protected]029c83b62013-01-24 05:28:2014677 LoadTimingInfo load_timing_info;
14678 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
14679 TestLoadTimingNotReusedWithPac(load_timing_info,
14680 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1114681}
[email protected]631f1322010-04-30 17:59:1114682
bncd16676a2016-07-20 16:23:0114683TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4814684 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5414685 HttpRequestInfo request;
14686 request.method = "GET";
bncb26024382016-06-29 02:39:4514687 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014688 request.traffic_annotation =
14689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5414690
14691 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214692 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314693 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214694 MockRead("\r\n"),
14695 MockRead("hello world"),
14696 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5414697 };
14698
Ryan Sleevib8d7ea02018-05-07 20:01:0114699 StaticSocketDataProvider first_transaction(data_reads,
14700 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0714701 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4514702 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614703 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4514704 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5414705
bnc032658ba2016-09-26 18:17:1514706 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5414707
Ryan Hamilton0239aac2018-05-19 00:03:1314708 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4514709 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114710 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5414711
Raul Tambre94493c652019-03-11 17:18:3514712 spdy::SpdySerializedFrame resp(
14713 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314714 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5414715 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114716 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5414717 };
14718
Ryan Sleevib8d7ea02018-05-07 20:01:0114719 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714720 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5414721
[email protected]83039bb2011-12-09 18:43:5514722 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5414723
danakj1fd259a02016-04-16 03:17:0914724 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5414725
bnc87dcefc2017-05-25 12:47:5814726 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914727 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414728
tfarina42834112016-09-22 13:38:2014729 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114730 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14731 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414732
14733 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214734 ASSERT_TRUE(response);
14735 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5414736 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14737
14738 std::string response_data;
robpercival214763f2016-07-01 23:27:0114739 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414740 EXPECT_EQ("hello world", response_data);
14741
14742 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2514743 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4014744 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1114745 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3414746 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
14747 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2714748 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5214749 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3814750
bnc87dcefc2017-05-25 12:47:5814751 trans =
Jeremy Roman0579ed62017-08-29 15:56:1914752 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5414753
tfarina42834112016-09-22 13:38:2014754 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114755 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14756 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414757
14758 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214759 ASSERT_TRUE(response);
14760 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0214761 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5314762 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214763 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5414764
robpercival214763f2016-07-01 23:27:0114765 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5414766 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4214767}
14768
[email protected]044de0642010-06-17 10:42:1514769// GenerateAuthToken is a mighty big test.
14770// It tests all permutation of GenerateAuthToken behavior:
14771// - Synchronous and Asynchronous completion.
14772// - OK or error on completion.
14773// - Direct connection, non-authenticating proxy, and authenticating proxy.
14774// - HTTP or HTTPS backend (to include proxy tunneling).
14775// - Non-authenticating and authenticating backend.
14776//
[email protected]fe3b7dc2012-02-03 19:52:0914777// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1514778// problems generating an auth token for an authenticating proxy, we don't
14779// need to test all permutations of the backend server).
14780//
14781// The test proceeds by going over each of the configuration cases, and
14782// potentially running up to three rounds in each of the tests. The TestConfig
14783// specifies both the configuration for the test as well as the expectations
14784// for the results.
bncd16676a2016-07-20 16:23:0114785TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5014786 static const char kServer[] = "http://www.example.com";
14787 static const char kSecureServer[] = "https://www.example.com";
14788 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1514789
14790 enum AuthTiming {
14791 AUTH_NONE,
14792 AUTH_SYNC,
14793 AUTH_ASYNC,
14794 };
14795
14796 const MockWrite kGet(
14797 "GET / HTTP/1.1\r\n"
14798 "Host: www.example.com\r\n"
14799 "Connection: keep-alive\r\n\r\n");
14800 const MockWrite kGetProxy(
14801 "GET http://www.example.com/ HTTP/1.1\r\n"
14802 "Host: www.example.com\r\n"
14803 "Proxy-Connection: keep-alive\r\n\r\n");
14804 const MockWrite kGetAuth(
14805 "GET / HTTP/1.1\r\n"
14806 "Host: www.example.com\r\n"
14807 "Connection: keep-alive\r\n"
14808 "Authorization: auth_token\r\n\r\n");
14809 const MockWrite kGetProxyAuth(
14810 "GET http://www.example.com/ HTTP/1.1\r\n"
14811 "Host: www.example.com\r\n"
14812 "Proxy-Connection: keep-alive\r\n"
14813 "Proxy-Authorization: auth_token\r\n\r\n");
14814 const MockWrite kGetAuthThroughProxy(
14815 "GET http://www.example.com/ HTTP/1.1\r\n"
14816 "Host: www.example.com\r\n"
14817 "Proxy-Connection: keep-alive\r\n"
14818 "Authorization: auth_token\r\n\r\n");
14819 const MockWrite kGetAuthWithProxyAuth(
14820 "GET http://www.example.com/ HTTP/1.1\r\n"
14821 "Host: www.example.com\r\n"
14822 "Proxy-Connection: keep-alive\r\n"
14823 "Proxy-Authorization: auth_token\r\n"
14824 "Authorization: auth_token\r\n\r\n");
14825 const MockWrite kConnect(
14826 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714827 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514828 "Proxy-Connection: keep-alive\r\n\r\n");
14829 const MockWrite kConnectProxyAuth(
14830 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1714831 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1514832 "Proxy-Connection: keep-alive\r\n"
14833 "Proxy-Authorization: auth_token\r\n\r\n");
14834
14835 const MockRead kSuccess(
14836 "HTTP/1.1 200 OK\r\n"
14837 "Content-Type: text/html; charset=iso-8859-1\r\n"
14838 "Content-Length: 3\r\n\r\n"
14839 "Yes");
14840 const MockRead kFailure(
14841 "Should not be called.");
14842 const MockRead kServerChallenge(
14843 "HTTP/1.1 401 Unauthorized\r\n"
14844 "WWW-Authenticate: Mock realm=server\r\n"
14845 "Content-Type: text/html; charset=iso-8859-1\r\n"
14846 "Content-Length: 14\r\n\r\n"
14847 "Unauthorized\r\n");
14848 const MockRead kProxyChallenge(
14849 "HTTP/1.1 407 Unauthorized\r\n"
14850 "Proxy-Authenticate: Mock realm=proxy\r\n"
14851 "Proxy-Connection: close\r\n"
14852 "Content-Type: text/html; charset=iso-8859-1\r\n"
14853 "Content-Length: 14\r\n\r\n"
14854 "Unauthorized\r\n");
14855 const MockRead kProxyConnected(
14856 "HTTP/1.1 200 Connection Established\r\n\r\n");
14857
14858 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
14859 // no constructors, but the C++ compiler on Windows warns about
14860 // unspecified data in compound literals. So, moved to using constructors,
14861 // and TestRound's created with the default constructor should not be used.
14862 struct TestRound {
14863 TestRound()
Raul Tambre94493c652019-03-11 17:18:3514864 : expected_rv(ERR_UNEXPECTED),
14865 extra_write(nullptr),
14866 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4314867 TestRound(const MockWrite& write_arg,
14868 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1514869 int expected_rv_arg)
14870 : write(write_arg),
14871 read(read_arg),
14872 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3514873 extra_write(nullptr),
14874 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1514875 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
14876 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0114877 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1514878 : write(write_arg),
14879 read(read_arg),
14880 expected_rv(expected_rv_arg),
14881 extra_write(extra_write_arg),
14882 extra_read(extra_read_arg) {
14883 }
14884 MockWrite write;
14885 MockRead read;
14886 int expected_rv;
14887 const MockWrite* extra_write;
14888 const MockRead* extra_read;
14889 };
14890
14891 static const int kNoSSL = 500;
14892
14893 struct TestConfig {
asanka463ca4262016-11-16 02:34:3114894 int line_number;
thestig9d3bb0c2015-01-24 00:49:5114895 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1514896 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3114897 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5114898 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1514899 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3114900 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1514901 int num_auth_rounds;
14902 int first_ssl_round;
asankae2257db2016-10-11 22:03:1614903 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1514904 } test_configs[] = {
asankac93076192016-10-03 15:46:0214905 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114906 {__LINE__,
14907 nullptr,
asankac93076192016-10-03 15:46:0214908 AUTH_NONE,
14909 OK,
14910 kServer,
14911 AUTH_NONE,
14912 OK,
14913 1,
14914 kNoSSL,
14915 {TestRound(kGet, kSuccess, OK)}},
14916 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3114917 {__LINE__,
14918 nullptr,
asankac93076192016-10-03 15:46:0214919 AUTH_NONE,
14920 OK,
14921 kServer,
14922 AUTH_SYNC,
14923 OK,
14924 2,
14925 kNoSSL,
14926 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514927 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114928 {__LINE__,
14929 nullptr,
asankac93076192016-10-03 15:46:0214930 AUTH_NONE,
14931 OK,
14932 kServer,
14933 AUTH_SYNC,
14934 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1614935 3,
14936 kNoSSL,
14937 {TestRound(kGet, kServerChallenge, OK),
14938 TestRound(kGet, kServerChallenge, OK),
14939 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114940 {__LINE__,
14941 nullptr,
asankae2257db2016-10-11 22:03:1614942 AUTH_NONE,
14943 OK,
14944 kServer,
14945 AUTH_SYNC,
14946 ERR_UNSUPPORTED_AUTH_SCHEME,
14947 2,
14948 kNoSSL,
14949 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114950 {__LINE__,
14951 nullptr,
asankae2257db2016-10-11 22:03:1614952 AUTH_NONE,
14953 OK,
14954 kServer,
14955 AUTH_SYNC,
14956 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
14957 2,
14958 kNoSSL,
14959 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114960 {__LINE__,
14961 kProxy,
asankae2257db2016-10-11 22:03:1614962 AUTH_SYNC,
14963 ERR_FAILED,
14964 kServer,
14965 AUTH_NONE,
14966 OK,
14967 2,
14968 kNoSSL,
14969 {TestRound(kGetProxy, kProxyChallenge, OK),
14970 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114971 {__LINE__,
14972 kProxy,
asankae2257db2016-10-11 22:03:1614973 AUTH_ASYNC,
14974 ERR_FAILED,
14975 kServer,
14976 AUTH_NONE,
14977 OK,
14978 2,
14979 kNoSSL,
14980 {TestRound(kGetProxy, kProxyChallenge, OK),
14981 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114982 {__LINE__,
14983 nullptr,
asankae2257db2016-10-11 22:03:1614984 AUTH_NONE,
14985 OK,
14986 kServer,
14987 AUTH_SYNC,
14988 ERR_FAILED,
asankac93076192016-10-03 15:46:0214989 2,
14990 kNoSSL,
14991 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614992 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3114993 {__LINE__,
14994 nullptr,
asankae2257db2016-10-11 22:03:1614995 AUTH_NONE,
14996 OK,
14997 kServer,
14998 AUTH_ASYNC,
14999 ERR_FAILED,
15000 2,
15001 kNoSSL,
15002 {TestRound(kGet, kServerChallenge, OK),
15003 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3115004 {__LINE__,
15005 nullptr,
asankac93076192016-10-03 15:46:0215006 AUTH_NONE,
15007 OK,
15008 kServer,
15009 AUTH_ASYNC,
15010 OK,
15011 2,
15012 kNoSSL,
15013 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515014 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115015 {__LINE__,
15016 nullptr,
asankac93076192016-10-03 15:46:0215017 AUTH_NONE,
15018 OK,
15019 kServer,
15020 AUTH_ASYNC,
15021 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1615022 3,
asankac93076192016-10-03 15:46:0215023 kNoSSL,
15024 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615025 // The second round uses a HttpAuthHandlerMock that always succeeds.
15026 TestRound(kGet, kServerChallenge, OK),
15027 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215028 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115029 {__LINE__,
15030 kProxy,
asankac93076192016-10-03 15:46:0215031 AUTH_NONE,
15032 OK,
15033 kServer,
15034 AUTH_NONE,
15035 OK,
15036 1,
15037 kNoSSL,
15038 {TestRound(kGetProxy, kSuccess, OK)}},
15039 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115040 {__LINE__,
15041 kProxy,
asankac93076192016-10-03 15:46:0215042 AUTH_NONE,
15043 OK,
15044 kServer,
15045 AUTH_SYNC,
15046 OK,
15047 2,
15048 kNoSSL,
15049 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515050 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115051 {__LINE__,
15052 kProxy,
asankac93076192016-10-03 15:46:0215053 AUTH_NONE,
15054 OK,
15055 kServer,
15056 AUTH_SYNC,
15057 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1615058 3,
asankac93076192016-10-03 15:46:0215059 kNoSSL,
15060 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615061 TestRound(kGetProxy, kServerChallenge, OK),
15062 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115063 {__LINE__,
15064 kProxy,
asankac93076192016-10-03 15:46:0215065 AUTH_NONE,
15066 OK,
15067 kServer,
15068 AUTH_ASYNC,
15069 OK,
15070 2,
15071 kNoSSL,
15072 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515073 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115074 {__LINE__,
15075 kProxy,
asankac93076192016-10-03 15:46:0215076 AUTH_NONE,
15077 OK,
15078 kServer,
15079 AUTH_ASYNC,
15080 ERR_INVALID_AUTH_CREDENTIALS,
15081 2,
15082 kNoSSL,
15083 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615084 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215085 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115086 {__LINE__,
15087 kProxy,
asankac93076192016-10-03 15:46:0215088 AUTH_SYNC,
15089 OK,
15090 kServer,
15091 AUTH_NONE,
15092 OK,
15093 2,
15094 kNoSSL,
15095 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515096 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115097 {__LINE__,
15098 kProxy,
asankac93076192016-10-03 15:46:0215099 AUTH_SYNC,
15100 ERR_INVALID_AUTH_CREDENTIALS,
15101 kServer,
15102 AUTH_NONE,
15103 OK,
15104 2,
15105 kNoSSL,
15106 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615107 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115108 {__LINE__,
15109 kProxy,
asankac93076192016-10-03 15:46:0215110 AUTH_ASYNC,
15111 OK,
15112 kServer,
15113 AUTH_NONE,
15114 OK,
15115 2,
15116 kNoSSL,
15117 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515118 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115119 {__LINE__,
15120 kProxy,
asankac93076192016-10-03 15:46:0215121 AUTH_ASYNC,
15122 ERR_INVALID_AUTH_CREDENTIALS,
15123 kServer,
15124 AUTH_NONE,
15125 OK,
15126 2,
15127 kNoSSL,
15128 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615129 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115130 {__LINE__,
15131 kProxy,
15132 AUTH_ASYNC,
15133 ERR_INVALID_AUTH_CREDENTIALS,
15134 kServer,
15135 AUTH_NONE,
15136 OK,
15137 3,
15138 kNoSSL,
15139 {TestRound(kGetProxy, kProxyChallenge, OK),
15140 TestRound(kGetProxy, kProxyChallenge, OK),
15141 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215142 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115143 {__LINE__,
15144 kProxy,
asankac93076192016-10-03 15:46:0215145 AUTH_SYNC,
15146 OK,
15147 kServer,
15148 AUTH_SYNC,
15149 OK,
15150 3,
15151 kNoSSL,
15152 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515153 TestRound(kGetProxyAuth, kServerChallenge, OK),
15154 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115155 {__LINE__,
15156 kProxy,
asankac93076192016-10-03 15:46:0215157 AUTH_SYNC,
15158 OK,
15159 kServer,
15160 AUTH_SYNC,
15161 ERR_INVALID_AUTH_CREDENTIALS,
15162 3,
15163 kNoSSL,
15164 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515165 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615166 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115167 {__LINE__,
15168 kProxy,
asankac93076192016-10-03 15:46:0215169 AUTH_ASYNC,
15170 OK,
15171 kServer,
15172 AUTH_SYNC,
15173 OK,
15174 3,
15175 kNoSSL,
15176 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515177 TestRound(kGetProxyAuth, kServerChallenge, OK),
15178 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115179 {__LINE__,
15180 kProxy,
asankac93076192016-10-03 15:46:0215181 AUTH_ASYNC,
15182 OK,
15183 kServer,
15184 AUTH_SYNC,
15185 ERR_INVALID_AUTH_CREDENTIALS,
15186 3,
15187 kNoSSL,
15188 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515189 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615190 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115191 {__LINE__,
15192 kProxy,
asankac93076192016-10-03 15:46:0215193 AUTH_SYNC,
15194 OK,
15195 kServer,
15196 AUTH_ASYNC,
15197 OK,
15198 3,
15199 kNoSSL,
15200 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515201 TestRound(kGetProxyAuth, kServerChallenge, OK),
15202 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115203 {__LINE__,
15204 kProxy,
15205 AUTH_SYNC,
15206 ERR_INVALID_AUTH_CREDENTIALS,
15207 kServer,
15208 AUTH_ASYNC,
15209 OK,
15210 4,
15211 kNoSSL,
15212 {TestRound(kGetProxy, kProxyChallenge, OK),
15213 TestRound(kGetProxy, kProxyChallenge, OK),
15214 TestRound(kGetProxyAuth, kServerChallenge, OK),
15215 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
15216 {__LINE__,
15217 kProxy,
asankac93076192016-10-03 15:46:0215218 AUTH_SYNC,
15219 OK,
15220 kServer,
15221 AUTH_ASYNC,
15222 ERR_INVALID_AUTH_CREDENTIALS,
15223 3,
15224 kNoSSL,
15225 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515226 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615227 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115228 {__LINE__,
15229 kProxy,
asankac93076192016-10-03 15:46:0215230 AUTH_ASYNC,
15231 OK,
15232 kServer,
15233 AUTH_ASYNC,
15234 OK,
15235 3,
15236 kNoSSL,
15237 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515238 TestRound(kGetProxyAuth, kServerChallenge, OK),
15239 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115240 {__LINE__,
15241 kProxy,
asankac93076192016-10-03 15:46:0215242 AUTH_ASYNC,
15243 OK,
15244 kServer,
15245 AUTH_ASYNC,
15246 ERR_INVALID_AUTH_CREDENTIALS,
15247 3,
15248 kNoSSL,
15249 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515250 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1615251 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115252 {__LINE__,
15253 kProxy,
15254 AUTH_ASYNC,
15255 ERR_INVALID_AUTH_CREDENTIALS,
15256 kServer,
15257 AUTH_ASYNC,
15258 ERR_INVALID_AUTH_CREDENTIALS,
15259 4,
15260 kNoSSL,
15261 {TestRound(kGetProxy, kProxyChallenge, OK),
15262 TestRound(kGetProxy, kProxyChallenge, OK),
15263 TestRound(kGetProxyAuth, kServerChallenge, OK),
15264 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215265 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3115266 {__LINE__,
15267 nullptr,
asankac93076192016-10-03 15:46:0215268 AUTH_NONE,
15269 OK,
15270 kSecureServer,
15271 AUTH_NONE,
15272 OK,
15273 1,
15274 0,
15275 {TestRound(kGet, kSuccess, OK)}},
15276 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3115277 {__LINE__,
15278 nullptr,
asankac93076192016-10-03 15:46:0215279 AUTH_NONE,
15280 OK,
15281 kSecureServer,
15282 AUTH_SYNC,
15283 OK,
15284 2,
15285 0,
15286 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515287 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115288 {__LINE__,
15289 nullptr,
asankac93076192016-10-03 15:46:0215290 AUTH_NONE,
15291 OK,
15292 kSecureServer,
15293 AUTH_SYNC,
15294 ERR_INVALID_AUTH_CREDENTIALS,
15295 2,
15296 0,
asankae2257db2016-10-11 22:03:1615297 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115298 {__LINE__,
15299 nullptr,
asankac93076192016-10-03 15:46:0215300 AUTH_NONE,
15301 OK,
15302 kSecureServer,
15303 AUTH_ASYNC,
15304 OK,
15305 2,
15306 0,
15307 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515308 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115309 {__LINE__,
15310 nullptr,
asankac93076192016-10-03 15:46:0215311 AUTH_NONE,
15312 OK,
15313 kSecureServer,
15314 AUTH_ASYNC,
15315 ERR_INVALID_AUTH_CREDENTIALS,
15316 2,
15317 0,
asankae2257db2016-10-11 22:03:1615318 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215319 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115320 {__LINE__,
15321 kProxy,
asankac93076192016-10-03 15:46:0215322 AUTH_NONE,
15323 OK,
15324 kSecureServer,
15325 AUTH_NONE,
15326 OK,
15327 1,
15328 0,
15329 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
15330 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3115331 {__LINE__,
15332 kProxy,
asankac93076192016-10-03 15:46:0215333 AUTH_NONE,
15334 OK,
15335 kSecureServer,
15336 AUTH_SYNC,
15337 OK,
15338 2,
15339 0,
15340 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515341 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115342 {__LINE__,
15343 kProxy,
asankac93076192016-10-03 15:46:0215344 AUTH_NONE,
15345 OK,
15346 kSecureServer,
15347 AUTH_SYNC,
15348 ERR_INVALID_AUTH_CREDENTIALS,
15349 2,
15350 0,
15351 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615352 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115353 {__LINE__,
15354 kProxy,
asankac93076192016-10-03 15:46:0215355 AUTH_NONE,
15356 OK,
15357 kSecureServer,
15358 AUTH_ASYNC,
15359 OK,
15360 2,
15361 0,
15362 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515363 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115364 {__LINE__,
15365 kProxy,
asankac93076192016-10-03 15:46:0215366 AUTH_NONE,
15367 OK,
15368 kSecureServer,
15369 AUTH_ASYNC,
15370 ERR_INVALID_AUTH_CREDENTIALS,
15371 2,
15372 0,
15373 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1615374 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0215375 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115376 {__LINE__,
15377 kProxy,
asankac93076192016-10-03 15:46:0215378 AUTH_SYNC,
15379 OK,
15380 kSecureServer,
15381 AUTH_NONE,
15382 OK,
15383 2,
15384 1,
15385 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515386 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115387 {__LINE__,
15388 kProxy,
asankac93076192016-10-03 15:46:0215389 AUTH_SYNC,
15390 ERR_INVALID_AUTH_CREDENTIALS,
15391 kSecureServer,
15392 AUTH_NONE,
15393 OK,
15394 2,
15395 kNoSSL,
15396 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615397 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115398 {__LINE__,
15399 kProxy,
asankae2257db2016-10-11 22:03:1615400 AUTH_SYNC,
15401 ERR_UNSUPPORTED_AUTH_SCHEME,
15402 kSecureServer,
15403 AUTH_NONE,
15404 OK,
15405 2,
15406 kNoSSL,
15407 {TestRound(kConnect, kProxyChallenge, OK),
15408 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115409 {__LINE__,
15410 kProxy,
asankae2257db2016-10-11 22:03:1615411 AUTH_SYNC,
15412 ERR_UNEXPECTED,
15413 kSecureServer,
15414 AUTH_NONE,
15415 OK,
15416 2,
15417 kNoSSL,
15418 {TestRound(kConnect, kProxyChallenge, OK),
15419 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3115420 {__LINE__,
15421 kProxy,
asankac93076192016-10-03 15:46:0215422 AUTH_ASYNC,
15423 OK,
15424 kSecureServer,
15425 AUTH_NONE,
15426 OK,
15427 2,
15428 1,
15429 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1515430 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3115431 {__LINE__,
15432 kProxy,
asankac93076192016-10-03 15:46:0215433 AUTH_ASYNC,
15434 ERR_INVALID_AUTH_CREDENTIALS,
15435 kSecureServer,
15436 AUTH_NONE,
15437 OK,
15438 2,
15439 kNoSSL,
15440 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1615441 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0215442 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3115443 {__LINE__,
15444 kProxy,
asankac93076192016-10-03 15:46:0215445 AUTH_SYNC,
15446 OK,
15447 kSecureServer,
15448 AUTH_SYNC,
15449 OK,
15450 3,
15451 1,
15452 {TestRound(kConnect, kProxyChallenge, OK),
15453 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15454 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515455 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115456 {__LINE__,
15457 kProxy,
asankac93076192016-10-03 15:46:0215458 AUTH_SYNC,
15459 OK,
15460 kSecureServer,
15461 AUTH_SYNC,
15462 ERR_INVALID_AUTH_CREDENTIALS,
15463 3,
15464 1,
15465 {TestRound(kConnect, kProxyChallenge, OK),
15466 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15467 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615468 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115469 {__LINE__,
15470 kProxy,
asankac93076192016-10-03 15:46:0215471 AUTH_ASYNC,
15472 OK,
15473 kSecureServer,
15474 AUTH_SYNC,
15475 OK,
15476 3,
15477 1,
15478 {TestRound(kConnect, kProxyChallenge, OK),
15479 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15480 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515481 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115482 {__LINE__,
15483 kProxy,
asankac93076192016-10-03 15:46:0215484 AUTH_ASYNC,
15485 OK,
15486 kSecureServer,
15487 AUTH_SYNC,
15488 ERR_INVALID_AUTH_CREDENTIALS,
15489 3,
15490 1,
15491 {TestRound(kConnect, kProxyChallenge, OK),
15492 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15493 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615494 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115495 {__LINE__,
15496 kProxy,
asankac93076192016-10-03 15:46:0215497 AUTH_SYNC,
15498 OK,
15499 kSecureServer,
15500 AUTH_ASYNC,
15501 OK,
15502 3,
15503 1,
15504 {TestRound(kConnect, kProxyChallenge, OK),
15505 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15506 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515507 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115508 {__LINE__,
15509 kProxy,
asankac93076192016-10-03 15:46:0215510 AUTH_SYNC,
15511 OK,
15512 kSecureServer,
15513 AUTH_ASYNC,
15514 ERR_INVALID_AUTH_CREDENTIALS,
15515 3,
15516 1,
15517 {TestRound(kConnect, kProxyChallenge, OK),
15518 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15519 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615520 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115521 {__LINE__,
15522 kProxy,
asankac93076192016-10-03 15:46:0215523 AUTH_ASYNC,
15524 OK,
15525 kSecureServer,
15526 AUTH_ASYNC,
15527 OK,
15528 3,
15529 1,
15530 {TestRound(kConnect, kProxyChallenge, OK),
15531 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15532 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1515533 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115534 {__LINE__,
15535 kProxy,
asankac93076192016-10-03 15:46:0215536 AUTH_ASYNC,
15537 OK,
15538 kSecureServer,
15539 AUTH_ASYNC,
15540 ERR_INVALID_AUTH_CREDENTIALS,
15541 3,
15542 1,
15543 {TestRound(kConnect, kProxyChallenge, OK),
15544 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15545 &kServerChallenge),
asankae2257db2016-10-11 22:03:1615546 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3115547 {__LINE__,
15548 kProxy,
15549 AUTH_ASYNC,
15550 ERR_INVALID_AUTH_CREDENTIALS,
15551 kSecureServer,
15552 AUTH_ASYNC,
15553 ERR_INVALID_AUTH_CREDENTIALS,
15554 4,
15555 2,
15556 {TestRound(kConnect, kProxyChallenge, OK),
15557 TestRound(kConnect, kProxyChallenge, OK),
15558 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
15559 &kServerChallenge),
15560 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1515561 };
15562
asanka463ca4262016-11-16 02:34:3115563 for (const auto& test_config : test_configs) {
15564 SCOPED_TRACE(::testing::Message() << "Test config at "
15565 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0815566 HttpAuthHandlerMock::Factory* auth_factory(
15567 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715568 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4915569 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2615570
15571 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1515572 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3115573 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0815574 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15575 std::string auth_challenge = "Mock realm=proxy";
15576 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2415577 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15578 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0815579 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
Matt Menke618134b2020-05-22 02:12:2715580 empty_ssl_info, NetworkIsolationKey(),
15581 origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815582 auth_handler->SetGenerateExpectation(
15583 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115584 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0815585 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
15586 }
[email protected]044de0642010-06-17 10:42:1515587 }
15588 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0015589 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1515590 std::string auth_challenge = "Mock realm=server";
15591 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2415592 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15593 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1515594 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715595 empty_ssl_info, NetworkIsolationKey(),
15596 origin, NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515597 auth_handler->SetGenerateExpectation(
15598 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3115599 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0815600 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1615601
15602 // The second handler always succeeds. It should only be used where there
15603 // are multiple auth sessions for server auth in the same network
15604 // transaction using the same auth scheme.
15605 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1915606 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1615607 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715608 empty_ssl_info, NetworkIsolationKey(),
15609 origin, NetLogWithSource());
asankae2257db2016-10-11 22:03:1615610 second_handler->SetGenerateExpectation(true, OK);
15611 auth_factory->AddMockHandler(second_handler.release(),
15612 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1515613 }
15614 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5915615 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615616 ConfiguredProxyResolutionService::CreateFixed(
15617 test_config.proxy_url, TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515618 } else {
Bence Béky53a5aef2018-03-29 21:54:1215619 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615620 ConfiguredProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1515621 }
15622
15623 HttpRequestInfo request;
15624 request.method = "GET";
15625 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e62018-02-07 07:41:1015626 request.traffic_annotation =
15627 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1515628
danakj1fd259a02016-04-16 03:17:0915629 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1515630
rchcb68dc62015-05-21 04:45:3615631 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
15632
15633 std::vector<std::vector<MockRead>> mock_reads(1);
15634 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1515635 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215636 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1515637 const TestRound& read_write_round = test_config.rounds[round];
15638
15639 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3615640 mock_reads.back().push_back(read_write_round.read);
15641 mock_writes.back().push_back(read_write_round.write);
15642
15643 // kProxyChallenge uses Proxy-Connection: close which means that the
15644 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5415645 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3615646 mock_reads.push_back(std::vector<MockRead>());
15647 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1515648 }
15649
rchcb68dc62015-05-21 04:45:3615650 if (read_write_round.extra_read) {
15651 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1515652 }
rchcb68dc62015-05-21 04:45:3615653 if (read_write_round.extra_write) {
15654 mock_writes.back().push_back(*read_write_round.extra_write);
15655 }
[email protected]044de0642010-06-17 10:42:1515656
15657 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1515658 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0715659 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1515660 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3615661 }
[email protected]044de0642010-06-17 10:42:1515662
danakj1fd259a02016-04-16 03:17:0915663 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3615664 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1915665 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0115666 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3615667 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3215668 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3615669 }
15670
mmenkecc2298e2015-12-07 18:20:1815671 // Transaction must be created after DataProviders, so it's destroyed before
15672 // they are as well.
15673 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15674
rchcb68dc62015-05-21 04:45:3615675 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2215676 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3615677 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1515678 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4115679 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1515680 int rv;
15681 if (round == 0) {
tfarina42834112016-09-22 13:38:2015682 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1515683 } else {
[email protected]49639fa2011-12-20 23:22:4115684 rv = trans.RestartWithAuth(
15685 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1515686 }
15687 if (rv == ERR_IO_PENDING)
15688 rv = callback.WaitForResult();
15689
15690 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1615691 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5015692 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5515693 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1515694 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
15695 continue;
15696 }
15697 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5815698 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1515699 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5815700 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1615701 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1515702 }
15703 }
[email protected]e5ae96a2010-04-14 20:12:4515704 }
15705}
15706
bncd16676a2016-07-20 16:23:0115707TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1415708 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1415709 HttpAuthHandlerMock::Factory* auth_factory(
15710 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0715711 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1215712 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5615713 ConfiguredProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0715714 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1415715
15716 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
15717 auth_handler->set_connection_based(true);
15718 std::string auth_challenge = "Mock realm=server";
15719 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2415720 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
15721 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4915722 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1415723 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
Matt Menke618134b2020-05-22 02:12:2715724 empty_ssl_info, NetworkIsolationKey(), origin,
15725 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0815726 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1415727
[email protected]c871bce92010-07-15 21:51:1415728 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3515729 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1415730 HttpRequestInfo request;
15731 request.method = "GET";
15732 request.url = origin;
Ramin Halavatib5e433e62018-02-07 07:41:1015733 request.traffic_annotation =
15734 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715735
danakj1fd259a02016-04-16 03:17:0915736 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1015737
15738 // Use a TCP Socket Pool with only one connection per group. This is used
15739 // to validate that the TCP socket is not released to the pool between
15740 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4215741 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3615742 CommonConnectJobParams common_connect_job_params(
15743 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2815744 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5915745 50, // Max sockets for pool
15746 1, // Max sockets per group
15747 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3615748 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5215749 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1915750 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4015751 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
15752 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4815753 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1015754
bnc691fda62016-08-12 00:43:1615755 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115756 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1415757
15758 const MockWrite kGet(
15759 "GET / HTTP/1.1\r\n"
15760 "Host: www.example.com\r\n"
15761 "Connection: keep-alive\r\n\r\n");
15762 const MockWrite kGetAuth(
15763 "GET / HTTP/1.1\r\n"
15764 "Host: www.example.com\r\n"
15765 "Connection: keep-alive\r\n"
15766 "Authorization: auth_token\r\n\r\n");
15767
15768 const MockRead kServerChallenge(
15769 "HTTP/1.1 401 Unauthorized\r\n"
15770 "WWW-Authenticate: Mock realm=server\r\n"
15771 "Content-Type: text/html; charset=iso-8859-1\r\n"
15772 "Content-Length: 14\r\n\r\n"
15773 "Unauthorized\r\n");
15774 const MockRead kSuccess(
15775 "HTTP/1.1 200 OK\r\n"
15776 "Content-Type: text/html; charset=iso-8859-1\r\n"
15777 "Content-Length: 3\r\n\r\n"
15778 "Yes");
15779
15780 MockWrite writes[] = {
15781 // First round
15782 kGet,
15783 // Second round
15784 kGetAuth,
15785 // Third round
15786 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3015787 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1015788 kGetAuth,
15789 // Competing request
15790 kGet,
[email protected]c871bce92010-07-15 21:51:1415791 };
15792 MockRead reads[] = {
15793 // First round
15794 kServerChallenge,
15795 // Second round
15796 kServerChallenge,
15797 // Third round
[email protected]eca50e122010-09-11 14:03:3015798 kServerChallenge,
15799 // Fourth round
[email protected]c871bce92010-07-15 21:51:1415800 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1015801 // Competing response
15802 kSuccess,
[email protected]c871bce92010-07-15 21:51:1415803 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115804 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0715805 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1415806
Matt Menkef6edce752019-03-19 17:21:5615807 const ClientSocketPool::GroupId kSocketGroup(
15808 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
dalyk51ab46b2019-10-15 15:14:3415809 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
15810 false /* disable_secure_dns */);
[email protected]7ef4cbbb2011-02-06 11:19:1015811
15812 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1415813 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2015814 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1415815 if (rv == ERR_IO_PENDING)
15816 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115817 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615818 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215819 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815820 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315821 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115822 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15823 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415824
[email protected]7ef4cbbb2011-02-06 11:19:1015825 // In between rounds, another request comes in for the same domain.
15826 // It should not be able to grab the TCP socket that trans has already
15827 // claimed.
bnc691fda62016-08-12 00:43:1615828 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4115829 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2015830 rv = trans_compete.Start(&request, callback_compete.callback(),
15831 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115832 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1015833 // callback_compete.WaitForResult at this point would stall forever,
15834 // since the HttpNetworkTransaction does not release the request back to
15835 // the pool until after authentication completes.
15836
15837 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1415838 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615839 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415840 if (rv == ERR_IO_PENDING)
15841 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115842 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615843 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215844 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815845 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315846 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115847 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15848 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1415849
[email protected]7ef4cbbb2011-02-06 11:19:1015850 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1415851 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615852 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1415853 if (rv == ERR_IO_PENDING)
15854 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115855 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615856 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215857 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815858 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315859 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3115860 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
15861 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3015862
[email protected]7ef4cbbb2011-02-06 11:19:1015863 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3015864 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1615865 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3015866 if (rv == ERR_IO_PENDING)
15867 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115868 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615869 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215870 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5815871 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4315872 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015873
asanka463ca4262016-11-16 02:34:3115874 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
15875 // auth handler should transition to a DONE state in concert with the remote
15876 // server. But that's not something we can test here with a mock handler.
15877 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
15878 auth_handler->state());
15879
[email protected]7ef4cbbb2011-02-06 11:19:1015880 // Read the body since the fourth round was successful. This will also
15881 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4415882 scoped_refptr<IOBufferWithSize> io_buf =
15883 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1615884 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015885 if (rv == ERR_IO_PENDING)
15886 rv = callback.WaitForResult();
15887 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615888 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015889 EXPECT_EQ(0, rv);
15890 // There are still 0 idle sockets, since the trans_compete transaction
15891 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315892 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1015893
15894 // The competing request can now finish. Wait for the headers and then
15895 // read the body.
15896 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0115897 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1615898 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015899 if (rv == ERR_IO_PENDING)
15900 rv = callback.WaitForResult();
15901 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1615902 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1015903 EXPECT_EQ(0, rv);
15904
15905 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4315906 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1415907}
15908
[email protected]65041fa2010-05-21 06:56:5315909// This tests the case that a request is issued via http instead of spdy after
15910// npn is negotiated.
bncd16676a2016-07-20 16:23:0115911TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5315912 HttpRequestInfo request;
15913 request.method = "GET";
bncce36dca22015-04-21 22:11:2315914 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015915 request.traffic_annotation =
15916 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5315917
15918 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2315919 MockWrite(
15920 "GET / HTTP/1.1\r\n"
15921 "Host: www.example.org\r\n"
15922 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5315923 };
15924
15925 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5215926 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4315927 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5215928 MockRead("\r\n"),
15929 MockRead("hello world"),
15930 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5315931 };
15932
[email protected]8ddf8322012-02-23 18:08:0615933 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615934 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5315935
[email protected]bb88e1d32013-05-03 23:11:0715936 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5315937
Ryan Sleevib8d7ea02018-05-07 20:01:0115938 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715939 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5315940
[email protected]49639fa2011-12-20 23:22:4115941 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5315942
danakj1fd259a02016-04-16 03:17:0915943 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615944 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5315945
tfarina42834112016-09-22 13:38:2015946 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5315947
robpercival214763f2016-07-01 23:27:0115948 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15949 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5315950
bnc691fda62016-08-12 00:43:1615951 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215952 ASSERT_TRUE(response);
15953 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5315954 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
15955
15956 std::string response_data;
bnc691fda62016-08-12 00:43:1615957 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5315958 EXPECT_EQ("hello world", response_data);
15959
15960 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215961 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5315962}
[email protected]26ef6582010-06-24 02:30:4715963
bnc55ff9da2015-08-19 18:42:3515964// Simulate the SSL handshake completing with an NPN negotiation followed by an
15965// immediate server closing of the socket.
15966// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0115967TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4715968 HttpRequestInfo request;
15969 request.method = "GET";
bncce36dca22015-04-21 22:11:2315970 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015971 request.traffic_annotation =
15972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4715973
[email protected]8ddf8322012-02-23 18:08:0615974 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615975 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715976 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4715977
Ryan Hamilton0239aac2018-05-19 00:03:1315978 spdy::SpdySerializedFrame req(
15979 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115980 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4715981
15982 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0615983 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4715984 };
15985
Ryan Sleevib8d7ea02018-05-07 20:01:0115986 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715987 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4715988
[email protected]49639fa2011-12-20 23:22:4115989 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4715990
danakj1fd259a02016-04-16 03:17:0915991 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615992 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4715993
tfarina42834112016-09-22 13:38:2015994 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115995 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15996 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4715997}
[email protected]65d34382010-07-01 18:12:2615998
[email protected]795cbf82013-07-22 09:37:2715999// A subclass of HttpAuthHandlerMock that records the request URL when
16000// it gets it. This is needed since the auth handler may get destroyed
16001// before we get a chance to query it.
16002class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
16003 public:
16004 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
16005
Chris Watkins7a41d3552017-12-01 02:13:2716006 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2716007
16008 protected:
dchengb03027d2014-10-21 12:00:2016009 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
16010 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0916011 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2016012 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2716013 *url_ = request->url;
16014 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0916015 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2716016 }
16017
16018 private:
16019 GURL* url_;
16020};
16021
[email protected]8e6441ca2010-08-19 05:56:3816022// Test that if we cancel the transaction as the connection is completing, that
16023// everything tears down correctly.
bncd16676a2016-07-20 16:23:0116024TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3816025 // Setup everything about the connection to complete synchronously, so that
16026 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
16027 // for is the callback from the HttpStreamRequest.
16028 // Then cancel the transaction.
16029 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3616030 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3816031 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0616032 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
16033 MockRead(SYNCHRONOUS, "hello world"),
16034 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3816035 };
16036
[email protected]8e6441ca2010-08-19 05:56:3816037 HttpRequestInfo request;
16038 request.method = "GET";
bncce36dca22015-04-21 22:11:2316039 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016040 request.traffic_annotation =
16041 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3816042
danakj1fd259a02016-04-16 03:17:0916043 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5816044 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1916045 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2716046
Ryan Sleevib8d7ea02018-05-07 20:01:0116047 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3816048 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0716049 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3816050
[email protected]49639fa2011-12-20 23:22:4116051 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3816052
Matt Muellerd9342e3a2019-11-26 01:41:1416053 RecordingBoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4116054 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116055 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3816056 trans.reset(); // Cancel the transaction here.
16057
fdoray92e35a72016-06-10 15:54:5516058 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3016059}
16060
[email protected]ecab6e052014-05-16 14:58:1216061// Test that if a transaction is cancelled after receiving the headers, the
16062// stream is drained properly and added back to the socket pool. The main
16063// purpose of this test is to make sure that an HttpStreamParser can be read
16064// from after the HttpNetworkTransaction and the objects it owns have been
16065// deleted.
16066// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0116067TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1216068 MockRead data_reads[] = {
16069 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
16070 MockRead(ASYNC, "Content-Length: 2\r\n"),
16071 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
16072 MockRead(ASYNC, "1"),
16073 // 2 async reads are necessary to trigger a ReadResponseBody call after the
16074 // HttpNetworkTransaction has been deleted.
16075 MockRead(ASYNC, "2"),
16076 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
16077 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116078 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1216079 session_deps_.socket_factory->AddSocketDataProvider(&data);
16080
danakj1fd259a02016-04-16 03:17:0916081 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1216082
16083 {
16084 HttpRequestInfo request;
16085 request.method = "GET";
bncce36dca22015-04-21 22:11:2316086 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016087 request.traffic_annotation =
16088 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1216089
dcheng48459ac22014-08-26 00:46:4116090 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1216091 TestCompletionCallback callback;
16092
tfarina42834112016-09-22 13:38:2016093 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116094 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1216095 callback.WaitForResult();
16096
16097 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216098 ASSERT_TRUE(response);
16099 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1216100 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16101
16102 // The transaction and HttpRequestInfo are deleted.
16103 }
16104
16105 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5516106 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1216107
16108 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4116109 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1216110}
16111
[email protected]76a505b2010-08-25 06:23:0016112// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0116113TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5916114 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616115 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916116 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416117 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716118 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916119 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016120
[email protected]76a505b2010-08-25 06:23:0016121 HttpRequestInfo request;
16122 request.method = "GET";
bncce36dca22015-04-21 22:11:2316123 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016124 request.traffic_annotation =
16125 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016126
16127 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2316128 MockWrite(
16129 "GET http://www.example.org/ HTTP/1.1\r\n"
16130 "Host: www.example.org\r\n"
16131 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016132 };
16133
16134 MockRead data_reads1[] = {
16135 MockRead("HTTP/1.1 200 OK\r\n"),
16136 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16137 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616138 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0016139 };
16140
Ryan Sleevib8d7ea02018-05-07 20:01:0116141 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716142 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0016143
[email protected]49639fa2011-12-20 23:22:4116144 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016145
bnc691fda62016-08-12 00:43:1616146 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Titouan Rigoudy78af7da2020-07-07 14:30:1216147 ConnectedHandler connected_handler;
16148 trans.SetConnectedCallback(connected_handler.Callback());
[email protected]0b0bf032010-09-21 18:08:5016149
bnc691fda62016-08-12 00:43:1616150 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116151 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016152
16153 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116154 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0016155
bnc691fda62016-08-12 00:43:1616156 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216157 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0016158
16159 EXPECT_TRUE(response->headers->IsKeepAlive());
16160 EXPECT_EQ(200, response->headers->response_code());
16161 EXPECT_EQ(100, response->headers->GetContentLength());
16162 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716163 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16164 HostPortPair::FromString("myproxy:70")),
16165 response->proxy_server);
[email protected]76a505b2010-08-25 06:23:0016166 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2016167
Titouan Rigoudyba507a882020-07-31 12:15:1516168 TransportInfo expected_transport;
16169 expected_transport.type = TransportType::kProxied;
16170 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
16171 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
16172
[email protected]029c83b62013-01-24 05:28:2016173 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616174 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2016175 TestLoadTimingNotReusedWithPac(load_timing_info,
16176 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0016177}
16178
16179// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0116180TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5916181 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616182 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916183 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416184 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716185 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916186 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016187
[email protected]76a505b2010-08-25 06:23:0016188 HttpRequestInfo request;
16189 request.method = "GET";
bncce36dca22015-04-21 22:11:2316190 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016191 request.traffic_annotation =
16192 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016193
16194 // Since we have proxy, should try to establish tunnel.
16195 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1716196 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
16197 "Host: www.example.org:443\r\n"
16198 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016199
rsleevidb16bb02015-11-12 23:47:1716200 MockWrite("GET / HTTP/1.1\r\n"
16201 "Host: www.example.org\r\n"
16202 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016203 };
16204
16205 MockRead data_reads1[] = {
16206 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
16207
16208 MockRead("HTTP/1.1 200 OK\r\n"),
16209 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16210 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616211 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0016212 };
16213
Ryan Sleevib8d7ea02018-05-07 20:01:0116214 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716215 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0616216 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0716217 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0016218
[email protected]49639fa2011-12-20 23:22:4116219 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016220
bnc691fda62016-08-12 00:43:1616221 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Titouan Rigoudy78af7da2020-07-07 14:30:1216222 ConnectedHandler connected_handler;
16223 trans.SetConnectedCallback(connected_handler.Callback());
[email protected]0b0bf032010-09-21 18:08:5016224
bnc691fda62016-08-12 00:43:1616225 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116226 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016227
16228 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116229 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5416230 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0016231 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016232 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16233 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016234 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4016235 entries, pos,
mikecirone8b85c432016-09-08 19:11:0016236 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16237 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016238
bnc691fda62016-08-12 00:43:1616239 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216240 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0016241
16242 EXPECT_TRUE(response->headers->IsKeepAlive());
16243 EXPECT_EQ(200, response->headers->response_code());
16244 EXPECT_EQ(100, response->headers->GetContentLength());
16245 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
16246 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716247 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16248 HostPortPair::FromString("myproxy:70")),
16249 response->proxy_server);
Titouan Rigoudyba507a882020-07-31 12:15:1516250
16251 TransportInfo expected_transport;
16252 expected_transport.type = TransportType::kProxied;
16253 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
16254 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
[email protected]029c83b62013-01-24 05:28:2016255
16256 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616257 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2016258 TestLoadTimingNotReusedWithPac(load_timing_info,
16259 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0016260}
16261
rsleevidb16bb02015-11-12 23:47:1716262// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
16263// literal host.
bncd16676a2016-07-20 16:23:0116264TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5916265 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5616266 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4916267 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416268 RecordingBoundTestNetLog log;
rsleevidb16bb02015-11-12 23:47:1716269 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916270 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1716271
16272 HttpRequestInfo request;
16273 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1516274 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e62018-02-07 07:41:1016275 request.traffic_annotation =
16276 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1716277
16278 // Since we have proxy, should try to establish tunnel.
16279 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1516280 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
16281 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1716282 "Proxy-Connection: keep-alive\r\n\r\n"),
16283
16284 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1516285 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1716286 "Connection: keep-alive\r\n\r\n"),
16287 };
16288
16289 MockRead data_reads1[] = {
16290 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
16291
16292 MockRead("HTTP/1.1 200 OK\r\n"),
16293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16294 MockRead("Content-Length: 100\r\n\r\n"),
16295 MockRead(SYNCHRONOUS, OK),
16296 };
16297
Ryan Sleevib8d7ea02018-05-07 20:01:0116298 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1716299 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16300 SSLSocketDataProvider ssl(ASYNC, OK);
16301 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16302
16303 TestCompletionCallback callback1;
16304
bnc691fda62016-08-12 00:43:1616305 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1716306
bnc691fda62016-08-12 00:43:1616307 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116308 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1716309
16310 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116311 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5416312 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1716313 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016314 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16315 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1716316 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016317 entries, pos,
16318 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16319 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1716320
bnc691fda62016-08-12 00:43:1616321 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5216322 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1716323
16324 EXPECT_TRUE(response->headers->IsKeepAlive());
16325 EXPECT_EQ(200, response->headers->response_code());
16326 EXPECT_EQ(100, response->headers->GetContentLength());
16327 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
16328 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4716329 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
16330 HostPortPair::FromString("myproxy:70")),
16331 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1716332
16333 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1616334 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1716335 TestLoadTimingNotReusedWithPac(load_timing_info,
16336 CONNECT_TIMING_HAS_SSL_TIMES);
16337}
16338
[email protected]76a505b2010-08-25 06:23:0016339// Test a basic HTTPS GET request through a proxy, but the server hangs up
16340// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0116341TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616342 session_deps_.proxy_resolution_service =
16343 ConfiguredProxyResolutionService::CreateFixed(
16344 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416345 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716346 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0916347 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0016348
[email protected]76a505b2010-08-25 06:23:0016349 HttpRequestInfo request;
16350 request.method = "GET";
bncce36dca22015-04-21 22:11:2316351 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016352 request.traffic_annotation =
16353 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0016354
16355 // Since we have proxy, should try to establish tunnel.
16356 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1716357 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
16358 "Host: www.example.org:443\r\n"
16359 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016360
rsleevidb16bb02015-11-12 23:47:1716361 MockWrite("GET / HTTP/1.1\r\n"
16362 "Host: www.example.org\r\n"
16363 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0016364 };
16365
16366 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0016367 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0616368 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0016369 };
16370
Ryan Sleevib8d7ea02018-05-07 20:01:0116371 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0716372 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0616373 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0716374 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0016375
[email protected]49639fa2011-12-20 23:22:4116376 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0016377
bnc691fda62016-08-12 00:43:1616378 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5016379
bnc691fda62016-08-12 00:43:1616380 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0116381 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0016382
16383 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0116384 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5416385 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0016386 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0016387 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
16388 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016389 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4016390 entries, pos,
mikecirone8b85c432016-09-08 19:11:0016391 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
16392 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0016393}
16394
[email protected]749eefa82010-09-13 22:14:0316395// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0116396TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1316397 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4916398 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4116399 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0316400
Raul Tambre94493c652019-03-11 17:18:3516401 spdy::SpdySerializedFrame resp(
16402 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316403 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0316404 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116405 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0316406 };
16407
Ryan Sleevib8d7ea02018-05-07 20:01:0116408 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716409 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0316410
[email protected]8ddf8322012-02-23 18:08:0616411 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616412 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0316414
danakj1fd259a02016-04-16 03:17:0916415 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0316416
16417 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2316418 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4016419 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1116420 PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3416421 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
16422 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]795cbf82013-07-22 09:37:2716423 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5216424 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0316425
16426 HttpRequestInfo request;
16427 request.method = "GET";
bncce36dca22015-04-21 22:11:2316428 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016429 request.traffic_annotation =
16430 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0316431
bnc691fda62016-08-12 00:43:1616432 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0316433
[email protected]41d64e82013-07-03 22:44:2616434 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016435 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116436 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16437 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0316438}
16439
[email protected]73b8dd222010-11-11 19:55:2416440// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1616441// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0216442void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0716443 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2916444 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716445 request_info.url = GURL("https://www.example.com/");
16446 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916447 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016448 request_info.traffic_annotation =
16449 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716450
[email protected]8ddf8322012-02-23 18:08:0616451 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2916452 MockWrite data_writes[] = {
16453 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2416454 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116455 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0716456 session_deps_.socket_factory->AddSocketDataProvider(&data);
16457 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2416458
danakj1fd259a02016-04-16 03:17:0916459 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616460 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2416461
[email protected]49639fa2011-12-20 23:22:4116462 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016463 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2916464 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2416465 rv = callback.WaitForResult();
16466 ASSERT_EQ(error, rv);
16467}
16468
bncd16676a2016-07-20 16:23:0116469TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2416470 // Just check a grab bag of cert errors.
16471 static const int kErrors[] = {
16472 ERR_CERT_COMMON_NAME_INVALID,
16473 ERR_CERT_AUTHORITY_INVALID,
16474 ERR_CERT_DATE_INVALID,
16475 };
Avi Drissman4365a4782018-12-28 19:26:2416476 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0616477 CheckErrorIsPassedBack(kErrors[i], ASYNC);
16478 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2416479 }
16480}
16481
[email protected]bd0b6772011-01-11 19:59:3016482// Ensure that a client certificate is removed from the SSL client auth
16483// cache when:
16484// 1) No proxy is involved.
16485// 2) TLS False Start is disabled.
16486// 3) The initial TLS handshake requests a client certificate.
16487// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116488TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916489 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716490 request_info.url = GURL("https://www.example.com/");
16491 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916492 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016493 request_info.traffic_annotation =
16494 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716495
David Benjamin1c4b6d012019-07-08 17:12:5716496 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116497 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016498
16499 // [ssl_]data1 contains the data for the first SSL handshake. When a
16500 // CertificateRequest is received for the first time, the handshake will
16501 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2916502 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016503 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116505 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716506 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016507
16508 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
16509 // False Start is not being used, the result of the SSL handshake will be
16510 // returned as part of the SSLClientSocket::Connect() call. This test
16511 // matches the result of a server sending a handshake_failure alert,
16512 // rather than a Finished message, because it requires a client
16513 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2916514 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3016515 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716516 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0116517 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0716518 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016519
16520 // [ssl_]data3 contains the data for the third SSL handshake. When a
16521 // connection to a server fails during an SSL handshake,
David Benjamin07a07d652020-02-26 22:26:5916522 // HttpNetworkTransaction will attempt to fallback with legacy cryptography
16523 // enabled on some errors. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3016524 // of the HttpNetworkTransaction. Because this test failure is due to
16525 // requiring a client certificate, this fallback handshake should also
16526 // fail.
ttuttle859dc7a2015-04-23 19:42:2916527 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
David Benjamin07a07d652020-02-26 22:26:5916528 ssl_data3.expected_disable_legacy_crypto = false;
[email protected]bd0b6772011-01-11 19:59:3016529 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716530 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116531 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0716532 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016533
danakj1fd259a02016-04-16 03:17:0916534 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616535 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016536
[email protected]bd0b6772011-01-11 19:59:3016537 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4116538 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016539 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116540 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016541
16542 // Complete the SSL handshake, which should abort due to requiring a
16543 // client certificate.
16544 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116545 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016546
16547 // Indicate that no certificate should be supplied. From the perspective
16548 // of SSLClientCertCache, NULL is just as meaningful as a real
16549 // certificate, so this is the same as supply a
16550 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516551 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116552 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016553
16554 // Ensure the certificate was added to the client auth cache before
16555 // allowing the connection to continue restarting.
16556 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416557 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116558 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416559 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216560 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016561
16562 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716563 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16564 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016565 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116566 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016567
16568 // Ensure that the client certificate is removed from the cache on a
16569 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116570 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416571 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016572}
16573
16574// Ensure that a client certificate is removed from the SSL client auth
16575// cache when:
16576// 1) No proxy is involved.
16577// 2) TLS False Start is enabled.
16578// 3) The initial TLS handshake requests a client certificate.
16579// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0116580TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2916581 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2716582 request_info.url = GURL("https://www.example.com/");
16583 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916584 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016585 request_info.traffic_annotation =
16586 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2716587
David Benjamin1c4b6d012019-07-08 17:12:5716588 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116589 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3016590
16591 // When TLS False Start is used, SSLClientSocket::Connect() calls will
16592 // return successfully after reading up to the peer's Certificate message.
16593 // This is to allow the caller to call SSLClientSocket::Write(), which can
16594 // enqueue application data to be sent in the same packet as the
16595 // ChangeCipherSpec and Finished messages.
16596 // The actual handshake will be finished when SSLClientSocket::Read() is
16597 // called, which expects to process the peer's ChangeCipherSpec and
16598 // Finished messages. If there was an error negotiating with the peer,
16599 // such as due to the peer requiring a client certificate when none was
16600 // supplied, the alert sent by the peer won't be processed until Read() is
16601 // called.
16602
16603 // Like the non-False Start case, when a client certificate is requested by
16604 // the peer, the handshake is aborted during the Connect() call.
16605 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2916606 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3016607 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716608 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0116609 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0716610 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3016611
16612 // When a client certificate is supplied, Connect() will not be aborted
16613 // when the peer requests the certificate. Instead, the handshake will
16614 // artificially succeed, allowing the caller to write the HTTP request to
16615 // the socket. The handshake messages are not processed until Read() is
16616 // called, which then detects that the handshake was aborted, due to the
16617 // peer sending a handshake_failure because it requires a client
16618 // certificate.
ttuttle859dc7a2015-04-23 19:42:2916619 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016620 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716621 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2916622 MockRead data2_reads[] = {
16623 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3016624 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116625 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716626 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3016627
16628 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1716629 // the data for the SSL handshake once the TLSv1.1 connection falls back to
16630 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916631 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3016632 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716633 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0116634 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716635 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3016636
[email protected]80c75f682012-05-26 16:22:1716637 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
16638 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2916639 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1716640 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0716641 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0116642 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0716643 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1716644
[email protected]7799de12013-05-30 05:52:5116645 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2916646 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5116647 ssl_data5.cert_request_info = cert_request.get();
16648 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0116649 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5116650 session_deps_.socket_factory->AddSocketDataProvider(&data5);
16651
danakj1fd259a02016-04-16 03:17:0916652 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616653 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3016654
[email protected]bd0b6772011-01-11 19:59:3016655 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4116656 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2016657 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116658 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016659
16660 // Complete the SSL handshake, which should abort due to requiring a
16661 // client certificate.
16662 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116663 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3016664
16665 // Indicate that no certificate should be supplied. From the perspective
16666 // of SSLClientCertCache, NULL is just as meaningful as a real
16667 // certificate, so this is the same as supply a
16668 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3516669 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0116670 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3016671
16672 // Ensure the certificate was added to the client auth cache before
16673 // allowing the connection to continue restarting.
16674 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5416675 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116676 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416677 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5216678 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3016679
[email protected]bd0b6772011-01-11 19:59:3016680 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1716681 // then consume ssl_data3 and ssl_data4, both of which should also fail.
16682 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3016683 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116684 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3016685
16686 // Ensure that the client certificate is removed from the cache on a
16687 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4116688 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5416689 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3016690}
16691
[email protected]8c405132011-01-11 22:03:1816692// Ensure that a client certificate is removed from the SSL client auth
16693// cache when:
16694// 1) An HTTPS proxy is involved.
16695// 3) The HTTPS proxy requests a client certificate.
16696// 4) The client supplies an invalid/unacceptable certificate for the
16697// proxy.
bncd16676a2016-07-20 16:23:0116698TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Nicolas Arciniegad2013f92020-02-07 23:00:5616699 session_deps_.proxy_resolution_service =
16700 ConfiguredProxyResolutionService::CreateFixed(
16701 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1416702 RecordingBoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716703 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1816704
David Benjamin3b94b0f2019-04-25 23:07:5216705 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4116706 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1816707
David Benjamin3b94b0f2019-04-25 23:07:5216708 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
16709 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2916710 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1816711 requests[0].url = GURL("https://www.example.com/");
16712 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916713 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016714 requests[0].traffic_annotation =
16715 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816716
David Benjamin3b94b0f2019-04-25 23:07:5216717 // HTTPS requests are tunneled.
16718 MockWrite https_writes[] = {
16719 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
16720 "Host: www.example.com:443\r\n"
16721 "Proxy-Connection: keep-alive\r\n\r\n"),
16722 };
16723
[email protected]8c405132011-01-11 22:03:1816724 requests[1].url = GURL("http://www.example.com/");
16725 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2916726 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1016727 requests[1].traffic_annotation =
16728 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1816729
David Benjamin3b94b0f2019-04-25 23:07:5216730 // HTTP requests are not.
16731 MockWrite http_writes[] = {
16732 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
16733 "Host: www.example.com\r\n"
16734 "Proxy-Connection: keep-alive\r\n\r\n"),
16735 };
[email protected]8c405132011-01-11 22:03:1816736
David Benjamin3b94b0f2019-04-25 23:07:5216737 // When the server rejects the client certificate, it will close the
16738 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
16739 // TLS 1.2 with False Start), the error is returned out of the first Read().
16740 for (bool reject_in_connect : {true, false}) {
16741 SCOPED_TRACE(reject_in_connect);
16742 // Client certificate errors are typically signaled with
16743 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
16744 // protocol error.
16745 for (Error reject_error :
16746 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
16747 SCOPED_TRACE(reject_error);
16748 // Tunneled and non-tunneled requests are handled differently. Test both.
16749 for (const HttpRequestInfo& request : requests) {
16750 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1816751
David Benjamin3b94b0f2019-04-25 23:07:5216752 session_deps_.socket_factory =
16753 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1816754
David Benjamin3b94b0f2019-04-25 23:07:5216755 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
David Benjamin07a07d652020-02-26 22:26:5916756 // [ssl_]data[1-3].
David Benjamin3b94b0f2019-04-25 23:07:5216757 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
16758 ssl_data1.cert_request_info = cert_request.get();
16759 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16760 StaticSocketDataProvider data1;
16761 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1816762
David Benjamin3b94b0f2019-04-25 23:07:5216763 base::Optional<SSLSocketDataProvider> ssl_data2;
16764 base::Optional<StaticSocketDataProvider> data2;
16765 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
16766 if (reject_in_connect) {
16767 ssl_data2.emplace(ASYNC, reject_error);
16768 // There are no reads or writes.
16769 data2.emplace();
16770 } else {
16771 ssl_data2.emplace(ASYNC, OK);
16772 // We will get one Write() in before observing the error in Read().
16773 if (request.url.SchemeIsCryptographic()) {
16774 data2.emplace(error_in_read, https_writes);
16775 } else {
16776 data2.emplace(error_in_read, http_writes);
16777 }
16778 }
16779 ssl_data2->cert_request_info = cert_request.get();
David Benjamin3b94b0f2019-04-25 23:07:5216780 session_deps_.socket_factory->AddSSLSocketDataProvider(
16781 &ssl_data2.value());
16782 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1816783
David Benjamin07a07d652020-02-26 22:26:5916784 // If the handshake returns ERR_SSL_PROTOCOL_ERROR, we attempt to
16785 // connect twice.
16786 base::Optional<SSLSocketDataProvider> ssl_data3;
16787 base::Optional<StaticSocketDataProvider> data3;
16788 if (reject_in_connect && reject_error == ERR_SSL_PROTOCOL_ERROR) {
16789 ssl_data3.emplace(ASYNC, reject_error);
16790 data3.emplace(); // There are no reads or writes.
16791 ssl_data3->cert_request_info = cert_request.get();
16792 session_deps_.socket_factory->AddSSLSocketDataProvider(
16793 &ssl_data3.value());
16794 session_deps_.socket_factory->AddSocketDataProvider(&data3.value());
16795 }
16796
David Benjamin3b94b0f2019-04-25 23:07:5216797 std::unique_ptr<HttpNetworkSession> session =
16798 CreateSession(&session_deps_);
16799 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16800
16801 // Begin the SSL handshake with the proxy.
16802 TestCompletionCallback callback;
16803 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16804 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16805
16806 // Complete the SSL handshake, which should abort due to requiring a
16807 // client certificate.
16808 rv = callback.WaitForResult();
16809 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16810
16811 // Indicate that no certificate should be supplied. From the
16812 // perspective of SSLClientCertCache, NULL is just as meaningful as a
16813 // real certificate, so this is the same as supply a
16814 // legitimate-but-unacceptable certificate.
16815 rv =
16816 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
16817 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16818
16819 // Ensure the certificate was added to the client auth cache before
16820 // allowing the connection to continue restarting.
16821 scoped_refptr<X509Certificate> client_cert;
16822 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116823 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216824 HostPortPair("proxy", 70), &client_cert, &client_private_key));
16825 ASSERT_FALSE(client_cert);
16826 // Ensure the certificate was NOT cached for the endpoint. This only
16827 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4116828 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216829 HostPortPair("www.example.com", 443), &client_cert,
16830 &client_private_key));
16831
16832 // Restart the handshake. This will consume ssl_data2. The result code
16833 // is checked against what ssl_data2 should return.
16834 rv = callback.WaitForResult();
16835 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
16836 IsError(reject_error)));
16837
16838 // Now that the new handshake has failed, ensure that the client
16839 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4116840 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216841 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4116842 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5216843 HostPortPair("www.example.com", 443), &client_cert,
16844 &client_private_key));
16845 }
16846 }
[email protected]8c405132011-01-11 22:03:1816847 }
16848}
16849
David Benjamin1a0566082019-04-30 07:36:1916850// Test that HttpNetworkTransaction correctly handles (mocked) certificate
16851// requests during a TLS renegotiation.
16852TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
16853 HttpRequestInfo request_info;
16854 request_info.url = GURL("https://www.example.com/");
16855 request_info.method = "GET";
16856 request_info.load_flags = LOAD_NORMAL;
16857 request_info.traffic_annotation =
16858 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16859
16860 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
16861 cert_request->host_and_port = HostPortPair("www.example.com", 443);
16862
16863 std::unique_ptr<FakeClientCertIdentity> identity =
16864 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
16865 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
16866 ASSERT_TRUE(identity);
16867
16868 // The first connection's handshake succeeds, but we get
16869 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
16870 SSLSocketDataProvider ssl_data1(ASYNC, OK);
16871 ssl_data1.cert_request_info = cert_request.get();
16872 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
16873 MockWrite data1_writes[] = {
16874 MockWrite("GET / HTTP/1.1\r\n"
16875 "Host: www.example.com\r\n"
16876 "Connection: keep-alive\r\n\r\n"),
16877 };
16878 MockRead data1_reads[] = {
16879 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
16880 };
16881 StaticSocketDataProvider data1(data1_reads, data1_writes);
16882 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16883
16884 // After supplying with certificate, we restart the request from the top,
16885 // which succeeds this time.
16886 SSLSocketDataProvider ssl_data2(ASYNC, OK);
16887 ssl_data2.expected_send_client_cert = true;
16888 ssl_data2.expected_client_cert = identity->certificate();
16889 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
16890 MockWrite data2_writes[] = {
16891 MockWrite("GET / HTTP/1.1\r\n"
16892 "Host: www.example.com\r\n"
16893 "Connection: keep-alive\r\n\r\n"),
16894 };
16895 MockRead data2_reads[] = {
16896 MockRead("HTTP/1.1 200 OK\r\n"
16897 "Content-Length: 0\r\n\r\n"),
16898 };
16899 StaticSocketDataProvider data2(data2_reads, data2_writes);
16900 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16901
16902 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
16903 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16904
16905 TestCompletionCallback callback;
16906 int rv = callback.GetResult(
16907 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
16908 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
16909
16910 rv = trans.RestartWithCertificate(identity->certificate(),
16911 identity->ssl_private_key(),
16912 callback.callback());
16913 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
16914
16915 // Ensure the certificate was added to the client auth cache
16916 // allowing the connection to continue restarting.
16917 scoped_refptr<X509Certificate> client_cert;
16918 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4116919 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916920 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16921 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16922
16923 // Complete the handshake. The request now succeeds.
16924 rv = callback.WaitForResult();
16925 ASSERT_THAT(rv, IsError(OK));
16926 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
16927
16928 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4116929 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1916930 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
16931 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
16932}
16933
bncd16676a2016-07-20 16:23:0116934TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4616935 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1916936 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0916937 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616938
bnc032658ba2016-09-26 18:17:1516939 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616940
Ryan Hamilton0239aac2018-05-19 00:03:1316941 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916942 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816943 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316944 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716945 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616946 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116947 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616948 };
Ryan Hamilton0239aac2018-05-19 00:03:1316949 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516950 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316951 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116952 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316953 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516954 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316955 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116956 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616957 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116958 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16959 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316960 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616961 };
16962
eroman36d84e54432016-03-17 03:23:0216963 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216964 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116965 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716966 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616967
[email protected]aa22b242011-11-16 18:58:2916968 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616969 HttpRequestInfo request1;
16970 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316971 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616972 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016973 request1.traffic_annotation =
16974 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016975 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616976
tfarina42834112016-09-22 13:38:2016977 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116978 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16979 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616980
16981 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216982 ASSERT_TRUE(response);
16983 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216984 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616985
16986 std::string response_data;
robpercival214763f2016-07-01 23:27:0116987 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616988 EXPECT_EQ("hello!", response_data);
16989
bnca4d611d2016-09-22 19:55:3716990 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316991 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3316992 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
16993 base::nullopt);
robpercival214763f2016-07-01 23:27:0116994 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616995
16996 HttpRequestInfo request2;
16997 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716998 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616999 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017000 request2.traffic_annotation =
17001 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017002 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617003
tfarina42834112016-09-22 13:38:2017004 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117005 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17006 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617007
17008 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217009 ASSERT_TRUE(response);
17010 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217011 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617012 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217013 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117014 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617015 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617016}
17017
bncd16676a2016-07-20 16:23:0117018TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0217019 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1917020 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0917021 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0217022
bnc032658ba2016-09-26 18:17:1517023 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0217024
Ryan Hamilton0239aac2018-05-19 00:03:1317025 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917026 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817027 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317028 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717029 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0217030 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117031 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0217032 };
Ryan Hamilton0239aac2018-05-19 00:03:1317033 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517034 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317035 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117036 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317037 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517038 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317039 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117040 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0217041 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117042 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17043 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317044 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0217045 };
17046
eroman36d84e54432016-03-17 03:23:0217047 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217048 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117049 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717050 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0217051
17052 TestCompletionCallback callback;
17053 HttpRequestInfo request1;
17054 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317055 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0217056 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017057 request1.traffic_annotation =
17058 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017059 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0217060
tfarina42834112016-09-22 13:38:2017061 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117062 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17063 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217064
17065 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217066 ASSERT_TRUE(response);
17067 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217068 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0217069
17070 std::string response_data;
robpercival214763f2016-07-01 23:27:0117071 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217072 EXPECT_EQ("hello!", response_data);
17073
17074 HttpRequestInfo request2;
17075 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717076 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0217077 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017078 request2.traffic_annotation =
17079 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017080 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0217081
tfarina42834112016-09-22 13:38:2017082 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117083 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17084 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217085
17086 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217087 ASSERT_TRUE(response);
17088 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217089 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0217090 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217091 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117092 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0217093 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0217094}
17095
bnc8016c1f2017-03-31 02:11:2917096// Regression test for https://crbug.com/546991.
17097// The server might not be able to serve an IP pooled request, and might send a
17098// 421 Misdirected Request response status to indicate this.
17099// HttpNetworkTransaction should reset the request and retry without IP pooling.
17100TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
17101 // Two hosts resolve to the same IP address.
17102 const std::string ip_addr = "1.2.3.4";
17103 IPAddress ip;
17104 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
17105 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17106
Jeremy Roman0579ed62017-08-29 15:56:1917107 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2917108 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
17109 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
17110
17111 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17112
17113 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1317114 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2917115 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
17116 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317117 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2917118 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317119 spdy::SpdySerializedFrame rst(
17120 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2917121 MockWrite writes1[] = {
17122 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
17123 CreateMockWrite(rst, 6),
17124 };
17125
17126 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1317127 spdy::SpdySerializedFrame resp1(
17128 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17129 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
17130 spdy::SpdyHeaderBlock response_headers;
17131 response_headers[spdy::kHttp2StatusHeader] = "421";
17132 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2917133 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
17134 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
17135 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
17136
17137 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117138 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2917139 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17140
17141 AddSSLSocketData();
17142
17143 // Retry the second request on a second connection.
17144 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1317145 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2917146 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
17147 MockWrite writes2[] = {
17148 CreateMockWrite(req3, 0),
17149 };
17150
Ryan Hamilton0239aac2018-05-19 00:03:1317151 spdy::SpdySerializedFrame resp3(
17152 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
17153 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2917154 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
17155 MockRead(ASYNC, 0, 3)};
17156
17157 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117158 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2917159 session_deps_.socket_factory->AddSocketDataProvider(&data2);
17160
17161 AddSSLSocketData();
17162
17163 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317164 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317165 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17166 base::nullopt);
bnc8016c1f2017-03-31 02:11:2917167 EXPECT_THAT(rv, IsOk());
17168
17169 HttpRequestInfo request1;
17170 request1.method = "GET";
17171 request1.url = GURL("https://www.example.org/");
17172 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017173 request1.traffic_annotation =
17174 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2917175 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17176
Eric Orthf4db66a2019-02-19 21:35:3317177 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2917178 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
17179 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17180 rv = callback.WaitForResult();
17181 EXPECT_THAT(rv, IsOk());
17182
17183 const HttpResponseInfo* response = trans1.GetResponseInfo();
17184 ASSERT_TRUE(response);
17185 ASSERT_TRUE(response->headers);
17186 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17187 EXPECT_TRUE(response->was_fetched_via_spdy);
17188 EXPECT_TRUE(response->was_alpn_negotiated);
17189 std::string response_data;
17190 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
17191 EXPECT_EQ("hello!", response_data);
17192
17193 HttpRequestInfo request2;
17194 request2.method = "GET";
17195 request2.url = GURL("https://mail.example.org/");
17196 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017197 request2.traffic_annotation =
17198 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2917199 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17200
Matt Muellerd9342e3a2019-11-26 01:41:1417201 RecordingBoundTestNetLog log;
bnc8016c1f2017-03-31 02:11:2917202 rv = trans2.Start(&request2, callback.callback(), log.bound());
17203 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17204 rv = callback.WaitForResult();
17205 EXPECT_THAT(rv, IsOk());
17206
17207 response = trans2.GetResponseInfo();
17208 ASSERT_TRUE(response);
17209 ASSERT_TRUE(response->headers);
17210 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17211 EXPECT_TRUE(response->was_fetched_via_spdy);
17212 EXPECT_TRUE(response->was_alpn_negotiated);
17213 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17214 EXPECT_EQ("hello!", response_data);
17215
Eric Roman79cc7552019-07-19 02:17:5417216 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5917217 ExpectLogContainsSomewhere(
17218 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2917219 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5917220}
17221
17222// Test that HTTP 421 responses are properly returned to the caller if received
17223// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
17224// portions of the response.
17225TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
17226 // Two hosts resolve to the same IP address.
17227 const std::string ip_addr = "1.2.3.4";
17228 IPAddress ip;
17229 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
17230 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17231
Jeremy Roman0579ed62017-08-29 15:56:1917232 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5917233 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
17234 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
17235
17236 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17237
17238 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1317239 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5917240 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
17241 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317242 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5917243 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317244 spdy::SpdySerializedFrame rst(
17245 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5917246 MockWrite writes1[] = {
17247 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
17248 CreateMockWrite(rst, 6),
17249 };
17250
17251 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1317252 spdy::SpdySerializedFrame resp1(
17253 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17254 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
17255 spdy::SpdyHeaderBlock response_headers;
17256 response_headers[spdy::kHttp2StatusHeader] = "421";
17257 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5917258 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
17259 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
17260 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
17261
17262 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117263 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5917264 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17265
17266 AddSSLSocketData();
17267
17268 // Retry the second request on a second connection. It returns 421 Misdirected
17269 // Retry again.
17270 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1317271 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5917272 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
17273 MockWrite writes2[] = {
17274 CreateMockWrite(req3, 0),
17275 };
17276
Ryan Hamilton0239aac2018-05-19 00:03:1317277 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5917278 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1317279 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5917280 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
17281 MockRead(ASYNC, 0, 3)};
17282
17283 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117284 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5917285 session_deps_.socket_factory->AddSocketDataProvider(&data2);
17286
17287 AddSSLSocketData();
17288
17289 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317290 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317291 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17292 base::nullopt);
davidbence688ae2017-05-04 15:12:5917293 EXPECT_THAT(rv, IsOk());
17294
17295 HttpRequestInfo request1;
17296 request1.method = "GET";
17297 request1.url = GURL("https://www.example.org/");
17298 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017299 request1.traffic_annotation =
17300 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917301 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17302
Eric Orthf4db66a2019-02-19 21:35:3317303 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5917304 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
17305 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17306 rv = callback.WaitForResult();
17307 EXPECT_THAT(rv, IsOk());
17308
17309 const HttpResponseInfo* response = trans1.GetResponseInfo();
17310 ASSERT_TRUE(response);
17311 ASSERT_TRUE(response->headers);
17312 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17313 EXPECT_TRUE(response->was_fetched_via_spdy);
17314 EXPECT_TRUE(response->was_alpn_negotiated);
17315 std::string response_data;
17316 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
17317 EXPECT_EQ("hello!", response_data);
17318
17319 HttpRequestInfo request2;
17320 request2.method = "GET";
17321 request2.url = GURL("https://mail.example.org/");
17322 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017323 request2.traffic_annotation =
17324 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5917325 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17326
Matt Muellerd9342e3a2019-11-26 01:41:1417327 RecordingBoundTestNetLog log;
davidbence688ae2017-05-04 15:12:5917328 rv = trans2.Start(&request2, callback.callback(), log.bound());
17329 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17330 rv = callback.WaitForResult();
17331 EXPECT_THAT(rv, IsOk());
17332
17333 // After a retry, the 421 Misdirected Request is reported back up to the
17334 // caller.
17335 response = trans2.GetResponseInfo();
17336 ASSERT_TRUE(response);
17337 ASSERT_TRUE(response->headers);
17338 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
17339 EXPECT_TRUE(response->was_fetched_via_spdy);
17340 EXPECT_TRUE(response->was_alpn_negotiated);
17341 EXPECT_TRUE(response->ssl_info.cert);
17342 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17343 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2917344}
17345
bncd16676a2016-07-20 16:23:0117346TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1317347 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3417348 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
17349 session_deps_.host_resolver =
17350 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0917351 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4617352
bnc032658ba2016-09-26 18:17:1517353 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4617354
Ryan Hamilton0239aac2018-05-19 00:03:1317355 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4917356 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3817357 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1317358 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3717359 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4617360 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117361 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4617362 };
Ryan Hamilton0239aac2018-05-19 00:03:1317363 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3517364 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317365 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4117366 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1317367 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517368 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317369 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117370 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4617371 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117372 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
17373 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1317374 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4617375 };
17376
eroman36d84e54432016-03-17 03:23:0217377 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0217378 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0117379 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0717380 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4617381
[email protected]aa22b242011-11-16 18:58:2917382 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4617383 HttpRequestInfo request1;
17384 request1.method = "GET";
bncce36dca22015-04-21 22:11:2317385 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4617386 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017387 request1.traffic_annotation =
17388 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017389 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617390
tfarina42834112016-09-22 13:38:2017391 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117392 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17393 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617394
17395 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217396 ASSERT_TRUE(response);
17397 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217398 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617399
17400 std::string response_data;
robpercival214763f2016-07-01 23:27:0117401 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617402 EXPECT_EQ("hello!", response_data);
17403
17404 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3317405 rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3317406 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
17407 base::nullopt);
robpercival214763f2016-07-01 23:27:0117408 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4617409
17410 HttpRequestInfo request2;
17411 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3717412 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4617413 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017414 request2.traffic_annotation =
17415 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017416 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4617417
tfarina42834112016-09-22 13:38:2017418 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117419 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17420 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617421
17422 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217423 ASSERT_TRUE(response);
17424 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217425 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4617426 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217427 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117428 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4617429 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4617430}
17431
bncd16676a2016-07-20 16:23:0117432TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2317433 const std::string https_url = "https://www.example.org:8080/";
17434 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417435
17436 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1317437 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917438 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0417439
17440 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117441 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0417442 };
17443
Raul Tambre94493c652019-03-11 17:18:3517444 spdy::SpdySerializedFrame resp1(
17445 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317446 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117447 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5917448 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0417449
Ryan Sleevib8d7ea02018-05-07 20:01:0117450 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417451 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717452 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417453
17454 // HTTP GET for the HTTP URL
17455 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1317456 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3417457 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2317458 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3417459 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0417460 };
17461
17462 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1317463 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
17464 MockRead(ASYNC, 2, "hello"),
17465 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0417466 };
17467
Ryan Sleevib8d7ea02018-05-07 20:01:0117468 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0417469
[email protected]8450d722012-07-02 19:14:0417470 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617471 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0717472 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17473 session_deps_.socket_factory->AddSocketDataProvider(&data1);
17474 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0417475
danakj1fd259a02016-04-16 03:17:0917476 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0417477
17478 // Start the first transaction to set up the SpdySession
17479 HttpRequestInfo request1;
17480 request1.method = "GET";
17481 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417482 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017483 request1.traffic_annotation =
17484 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017485 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417486 TestCompletionCallback callback1;
17487 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017488 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517489 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417490
robpercival214763f2016-07-01 23:27:0117491 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417492 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17493
17494 // Now, start the HTTP request
17495 HttpRequestInfo request2;
17496 request2.method = "GET";
17497 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417498 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017499 request2.traffic_annotation =
17500 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017501 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417502 TestCompletionCallback callback2;
17503 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017504 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5517505 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0417506
robpercival214763f2016-07-01 23:27:0117507 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0417508 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
17509}
17510
bnc5452e2a2015-05-08 16:27:4217511// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
17512// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0117513TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2517514 url::SchemeHostPort server("https", "www.example.org", 443);
17515 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4217516
bnc8bef8da22016-05-30 01:28:2517517 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4217518 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617519 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217520 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17521
17522 // No data should be read from the alternative, because HTTP/1.1 is
17523 // negotiated.
17524 StaticSocketDataProvider data;
17525 session_deps_.socket_factory->AddSocketDataProvider(&data);
17526
17527 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4617528 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4217529 // mocked. This way the request relies on the alternate Job.
17530 StaticSocketDataProvider data_refused;
17531 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17532 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17533
zhongyi3d4a55e72016-04-22 20:36:4617534 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917535 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017536 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217537 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117538 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217539 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117540 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717541 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217542
bnc5452e2a2015-05-08 16:27:4217543 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4617544 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217545 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2517546 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e62018-02-07 07:41:1017547 request.traffic_annotation =
17548 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217549 TestCompletionCallback callback;
17550
17551 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5217552 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2017553 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5217554 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4217555}
17556
bnc40448a532015-05-11 19:13:1417557// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4617558// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1417559// succeeds, the request should succeed, even if the latter fails because
17560// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0117561TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2517562 url::SchemeHostPort server("https", "www.example.org", 443);
17563 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1417564
17565 // Negotiate HTTP/1.1 with alternative.
17566 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617567 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417568 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
17569
17570 // No data should be read from the alternative, because HTTP/1.1 is
17571 // negotiated.
17572 StaticSocketDataProvider data;
17573 session_deps_.socket_factory->AddSocketDataProvider(&data);
17574
zhongyi3d4a55e72016-04-22 20:36:4617575 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1417576 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617577 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1417578 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
17579
17580 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2517581 MockWrite("GET / HTTP/1.1\r\n"
17582 "Host: www.example.org\r\n"
17583 "Connection: keep-alive\r\n\r\n"),
17584 MockWrite("GET /second HTTP/1.1\r\n"
17585 "Host: www.example.org\r\n"
17586 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1417587 };
17588
17589 MockRead http_reads[] = {
17590 MockRead("HTTP/1.1 200 OK\r\n"),
17591 MockRead("Content-Type: text/html\r\n"),
17592 MockRead("Content-Length: 6\r\n\r\n"),
17593 MockRead("foobar"),
17594 MockRead("HTTP/1.1 200 OK\r\n"),
17595 MockRead("Content-Type: text/html\r\n"),
17596 MockRead("Content-Length: 7\r\n\r\n"),
17597 MockRead("another"),
17598 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117599 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1417600 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17601
zhongyi3d4a55e72016-04-22 20:36:4617602 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917603 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017604 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1417605 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117606 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217607 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117608 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717609 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1417610
17611 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17612 HttpRequestInfo request1;
17613 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2517614 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1417615 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017616 request1.traffic_annotation =
17617 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417618 TestCompletionCallback callback1;
17619
tfarina42834112016-09-22 13:38:2017620 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417621 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117622 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417623
17624 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5217625 ASSERT_TRUE(response1);
17626 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1417627 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
17628
17629 std::string response_data1;
robpercival214763f2016-07-01 23:27:0117630 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1417631 EXPECT_EQ("foobar", response_data1);
17632
17633 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
17634 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0517635 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
17636 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1417637
zhongyi3d4a55e72016-04-22 20:36:4617638 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1417639 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4617640 // to server.
bnc40448a532015-05-11 19:13:1417641 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17642 HttpRequestInfo request2;
17643 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2517644 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1417645 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017646 request2.traffic_annotation =
17647 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1417648 TestCompletionCallback callback2;
17649
tfarina42834112016-09-22 13:38:2017650 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1417651 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0117652 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1417653
17654 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217655 ASSERT_TRUE(response2);
17656 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1417657 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
17658
17659 std::string response_data2;
robpercival214763f2016-07-01 23:27:0117660 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1417661 EXPECT_EQ("another", response_data2);
17662}
17663
bnc5452e2a2015-05-08 16:27:4217664// Alternative service requires HTTP/2 (or SPDY), but there is already a
17665// HTTP/1.1 socket open to the alternative server. That socket should not be
17666// used.
bncd16676a2016-07-20 16:23:0117667TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4617668 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4217669 HostPortPair alternative("alternative.example.org", 443);
17670 std::string origin_url = "https://origin.example.org:443";
17671 std::string alternative_url = "https://alternative.example.org:443";
17672
17673 // Negotiate HTTP/1.1 with alternative.example.org.
17674 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3617675 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4217676 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17677
17678 // HTTP/1.1 data for |request1| and |request2|.
17679 MockWrite http_writes[] = {
17680 MockWrite(
17681 "GET / HTTP/1.1\r\n"
17682 "Host: alternative.example.org\r\n"
17683 "Connection: keep-alive\r\n\r\n"),
17684 MockWrite(
17685 "GET / HTTP/1.1\r\n"
17686 "Host: alternative.example.org\r\n"
17687 "Connection: keep-alive\r\n\r\n"),
17688 };
17689
17690 MockRead http_reads[] = {
17691 MockRead(
17692 "HTTP/1.1 200 OK\r\n"
17693 "Content-Type: text/html; charset=iso-8859-1\r\n"
17694 "Content-Length: 40\r\n\r\n"
17695 "first HTTP/1.1 response from alternative"),
17696 MockRead(
17697 "HTTP/1.1 200 OK\r\n"
17698 "Content-Type: text/html; charset=iso-8859-1\r\n"
17699 "Content-Length: 41\r\n\r\n"
17700 "second HTTP/1.1 response from alternative"),
17701 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117702 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4217703 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17704
17705 // This test documents that an alternate Job should not pool to an already
17706 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4617707 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4217708 StaticSocketDataProvider data_refused;
17709 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
17710 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
17711
zhongyi3d4a55e72016-04-22 20:36:4617712 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0917713 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4017714 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4217715 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2117716 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1217717 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2117718 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0717719 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4217720
17721 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4217722 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4617723 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217724 request1.method = "GET";
17725 request1.url = GURL(alternative_url);
17726 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017727 request1.traffic_annotation =
17728 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217729 TestCompletionCallback callback1;
17730
tfarina42834112016-09-22 13:38:2017731 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117732 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617733 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217734 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5217735 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4217736 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217737 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217738 EXPECT_FALSE(response1->was_fetched_via_spdy);
17739 std::string response_data1;
bnc691fda62016-08-12 00:43:1617740 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4217741 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
17742
17743 // Request for origin.example.org, which has an alternative service. This
17744 // will start two Jobs: the alternative looks for connections to pool to,
17745 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4617746 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4217747 // this request fails.
bnc5452e2a2015-05-08 16:27:4217748 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4617749 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217750 request2.method = "GET";
17751 request2.url = GURL(origin_url);
17752 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017753 request2.traffic_annotation =
17754 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217755 TestCompletionCallback callback2;
17756
tfarina42834112016-09-22 13:38:2017757 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117758 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4217759
17760 // Another transaction to alternative. This is to test that the HTTP/1.1
17761 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4217762 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4617763 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4217764 request3.method = "GET";
17765 request3.url = GURL(alternative_url);
17766 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017767 request3.traffic_annotation =
17768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4217769 TestCompletionCallback callback3;
17770
tfarina42834112016-09-22 13:38:2017771 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117772 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1617773 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4217774 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5217775 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4217776 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5217777 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4217778 EXPECT_FALSE(response3->was_fetched_via_spdy);
17779 std::string response_data3;
bnc691fda62016-08-12 00:43:1617780 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4217781 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
17782}
17783
bncd16676a2016-07-20 16:23:0117784TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2317785 const std::string https_url = "https://www.example.org:8080/";
17786 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0417787
rdsmithebb50aa2015-11-12 03:44:3817788 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0117789 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3817790
[email protected]8450d722012-07-02 19:14:0417791 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2317792 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0417793 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
17794 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
17795 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1317796 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4917797 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1317798 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0217799 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3917800
17801 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1317802 spdy::SpdyHeaderBlock req2_block;
17803 req2_block[spdy::kHttp2MethodHeader] = "GET";
17804 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
17805 req2_block[spdy::kHttp2SchemeHeader] = "http";
17806 req2_block[spdy::kHttp2PathHeader] = "/";
17807 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1517808 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0417809
17810 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117811 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
17812 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0417813 };
17814
Ryan Hamilton0239aac2018-05-19 00:03:1317815 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1517816 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317817 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1517818 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317819 spdy::SpdySerializedFrame body1(
17820 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
17821 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3817822 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317823 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3817824 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3517825 spdy::SpdySerializedFrame resp2(
17826 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1317827 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3317828 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117829 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3317830 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4117831 CreateMockRead(wrapped_resp1, 4),
17832 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3317833 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4117834 CreateMockRead(resp2, 8),
17835 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3317836 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
17837 };
[email protected]8450d722012-07-02 19:14:0417838
Ryan Sleevib8d7ea02018-05-07 20:01:0117839 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0417840 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5717841 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0417842
Lily Houghton8c2f97d2018-01-22 05:06:5917843 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617844 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4917845 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1417846 RecordingTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0717847 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0417848 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617849 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317850 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0417851 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617852 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317853 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17854 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0417855
danakj1fd259a02016-04-16 03:17:0917856 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0417857
17858 // Start the first transaction to set up the SpdySession
17859 HttpRequestInfo request1;
17860 request1.method = "GET";
17861 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0417862 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017863 request1.traffic_annotation =
17864 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017865 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0417866 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2017867 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417868
mmenke666a6fea2015-12-19 04:16:3317869 // This pause is a hack to avoid running into https://crbug.com/497228.
17870 data1.RunUntilPaused();
17871 base::RunLoop().RunUntilIdle();
17872 data1.Resume();
robpercival214763f2016-07-01 23:27:0117873 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0417874 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
17875
[email protected]f6c63db52013-02-02 00:35:2217876 LoadTimingInfo load_timing_info1;
17877 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
17878 TestLoadTimingNotReusedWithPac(load_timing_info1,
17879 CONNECT_TIMING_HAS_SSL_TIMES);
17880
mmenke666a6fea2015-12-19 04:16:3317881 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0417882 HttpRequestInfo request2;
17883 request2.method = "GET";
17884 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0417885 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017886 request2.traffic_annotation =
17887 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5017888 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0417889 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2017890 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0417891
mmenke666a6fea2015-12-19 04:16:3317892 // This pause is a hack to avoid running into https://crbug.com/497228.
17893 data1.RunUntilPaused();
17894 base::RunLoop().RunUntilIdle();
17895 data1.Resume();
robpercival214763f2016-07-01 23:27:0117896 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3317897
[email protected]8450d722012-07-02 19:14:0417898 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2217899
17900 LoadTimingInfo load_timing_info2;
17901 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
17902 // The established SPDY sessions is considered reused by the HTTP request.
17903 TestLoadTimingReusedWithPac(load_timing_info2);
17904 // HTTP requests over a SPDY session should have a different connection
17905 // socket_log_id than requests over a tunnel.
17906 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0417907}
17908
[email protected]2d88e7d2012-07-19 17:55:1717909// Test that in the case where we have a SPDY session to a SPDY proxy
17910// that we do not pool other origins that resolve to the same IP when
17911// the certificate does not match the new origin.
17912// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0117913TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2317914 const std::string url1 = "http://www.example.org/";
17915 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1717916 const std::string ip_addr = "1.2.3.4";
17917
rdsmithebb50aa2015-11-12 03:44:3817918 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0117919 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3817920
[email protected]2d88e7d2012-07-19 17:55:1717921 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1317922 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2317923 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1317924 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1517925 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1717926
17927 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4117928 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1717929 };
17930
Raul Tambre94493c652019-03-11 17:18:3517931 spdy::SpdySerializedFrame resp1(
17932 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317933 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1717934 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4117935 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
17936 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1717937 };
17938
Ryan Sleevib8d7ea02018-05-07 20:01:0117939 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3217940 IPAddress ip;
martijn654c8c42016-02-10 22:10:5917941 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1717942 IPEndPoint peer_addr = IPEndPoint(ip, 443);
17943 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3317944 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1717945
17946 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1317947 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4917948 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1717949
17950 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4117951 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1717952 };
17953
Ryan Hamilton0239aac2018-05-19 00:03:1317954 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3517955 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317956 spdy::SpdySerializedFrame body2(
17957 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4117958 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3317959 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1717960
Ryan Sleevib8d7ea02018-05-07 20:01:0117961 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1717962 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3317963 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1717964
17965 // Set up a proxy config that sends HTTP requests to a proxy, and
17966 // all others direct.
17967 ProxyConfig proxy_config;
17968 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4917969 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5617970 std::make_unique<ConfiguredProxyResolutionService>(
Ramin Halavatica8d5252018-03-12 05:33:4917971 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
17972 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0917973 nullptr, nullptr, /*quick_check_enabled=*/true);
[email protected]2d88e7d2012-07-19 17:55:1717974
bncce36dca22015-04-21 22:11:2317975 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3617976 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1717977 // Load a valid cert. Note, that this does not need to
17978 // be valid for proxy because the MockSSLClientSocket does
17979 // not actually verify it. But SpdySession will use this
17980 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4917981 ssl1.ssl_info.cert =
17982 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
17983 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3317984 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
17985 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1717986
17987 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3617988 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3317989 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
17990 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1717991
Jeremy Roman0579ed62017-08-29 15:56:1917992 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2317993 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0717994 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1717995
danakj1fd259a02016-04-16 03:17:0917996 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1717997
17998 // Start the first transaction to set up the SpdySession
17999 HttpRequestInfo request1;
18000 request1.method = "GET";
18001 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1718002 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018003 request1.traffic_annotation =
18004 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018005 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1718006 TestCompletionCallback callback1;
18007 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018008 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3318009 // This pause is a hack to avoid running into https://crbug.com/497228.
18010 data1.RunUntilPaused();
18011 base::RunLoop().RunUntilIdle();
18012 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1718013
robpercival214763f2016-07-01 23:27:0118014 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1718015 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
18016
18017 // Now, start the HTTP request
18018 HttpRequestInfo request2;
18019 request2.method = "GET";
18020 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1718021 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018022 request2.traffic_annotation =
18023 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018024 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1718025 TestCompletionCallback callback2;
18026 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018027 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5518028 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1718029
18030 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0118031 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1718032 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
18033}
18034
[email protected]85f97342013-04-17 06:12:2418035// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
18036// error) in SPDY session, removes the socket from pool and closes the SPDY
18037// session. Verify that new url's from the same HttpNetworkSession (and a new
18038// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0118039TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2318040 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2418041
18042 MockRead reads1[] = {
18043 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
18044 };
18045
Ryan Sleevib8d7ea02018-05-07 20:01:0118046 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2418047
Ryan Hamilton0239aac2018-05-19 00:03:1318048 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4918049 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2418050 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4118051 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2418052 };
18053
Raul Tambre94493c652019-03-11 17:18:3518054 spdy::SpdySerializedFrame resp2(
18055 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318056 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2418057 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4118058 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
18059 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2418060 };
18061
Ryan Sleevib8d7ea02018-05-07 20:01:0118062 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2418063
[email protected]85f97342013-04-17 06:12:2418064 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618065 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5018066 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18067 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2418068
18069 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618070 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5018071 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18072 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2418073
danakj1fd259a02016-04-16 03:17:0918074 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5018075 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2418076
18077 // Start the first transaction to set up the SpdySession and verify that
18078 // connection was closed.
18079 HttpRequestInfo request1;
18080 request1.method = "GET";
18081 request1.url = GURL(https_url);
18082 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018083 request1.traffic_annotation =
18084 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018085 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2418086 TestCompletionCallback callback1;
18087 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018088 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118089 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2418090
18091 // Now, start the second request and make sure it succeeds.
18092 HttpRequestInfo request2;
18093 request2.method = "GET";
18094 request2.url = GURL(https_url);
18095 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018096 request2.traffic_annotation =
18097 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5018098 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2418099 TestCompletionCallback callback2;
18100 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018101 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2418102
robpercival214763f2016-07-01 23:27:0118103 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2418104 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
18105}
18106
bncd16676a2016-07-20 16:23:0118107TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0318108 ClientSocketPoolManager::set_max_sockets_per_group(
18109 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18110 ClientSocketPoolManager::set_max_sockets_per_pool(
18111 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18112
18113 // Use two different hosts with different IPs so they don't get pooled.
18114 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
18115 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0918116 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0318117
18118 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618119 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0318120 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3618121 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0318122 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18123 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18124
Ryan Hamilton0239aac2018-05-19 00:03:1318125 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4918126 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0318127 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4118128 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0318129 };
Ryan Hamilton0239aac2018-05-19 00:03:1318130 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3518131 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318132 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4118133 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0318134 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4118135 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5918136 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0318137 };
18138
rdsmithebb50aa2015-11-12 03:44:3818139 // Use a separate test instance for the separate SpdySession that will be
18140 // created.
bncd16676a2016-07-20 16:23:0118141 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0118142 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1218143 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0318144
Ryan Hamilton0239aac2018-05-19 00:03:1318145 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4918146 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0318147 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4118148 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0318149 };
Ryan Hamilton0239aac2018-05-19 00:03:1318150 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3518151 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1318152 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4118153 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0318154 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4118155 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5918156 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0318157 };
18158
Ryan Sleevib8d7ea02018-05-07 20:01:0118159 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1218160 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0318161
18162 MockWrite http_write[] = {
18163 MockWrite("GET / HTTP/1.1\r\n"
18164 "Host: www.a.com\r\n"
18165 "Connection: keep-alive\r\n\r\n"),
18166 };
18167
18168 MockRead http_read[] = {
18169 MockRead("HTTP/1.1 200 OK\r\n"),
18170 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18171 MockRead("Content-Length: 6\r\n\r\n"),
18172 MockRead("hello!"),
18173 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118174 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0318175 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18176
18177 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1118178 SpdySessionKey spdy_session_key_a(
18179 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418180 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18181 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318182 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618183 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318184
18185 TestCompletionCallback callback;
18186 HttpRequestInfo request1;
18187 request1.method = "GET";
18188 request1.url = GURL("https://www.a.com/");
18189 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018190 request1.traffic_annotation =
18191 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818192 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918193 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318194
tfarina42834112016-09-22 13:38:2018195 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118196 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18197 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318198
18199 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218200 ASSERT_TRUE(response);
18201 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0218202 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0318203 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218204 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0318205
18206 std::string response_data;
robpercival214763f2016-07-01 23:27:0118207 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318208 EXPECT_EQ("hello!", response_data);
18209 trans.reset();
18210 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2618211 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318212
18213 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1118214 SpdySessionKey spdy_session_key_b(
18215 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418216 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18217 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318218 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618219 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318220 HttpRequestInfo request2;
18221 request2.method = "GET";
18222 request2.url = GURL("https://www.b.com/");
18223 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018224 request2.traffic_annotation =
18225 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818226 trans =
Jeremy Roman0579ed62017-08-29 15:56:1918227 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318228
tfarina42834112016-09-22 13:38:2018229 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118230 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18231 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318232
18233 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218234 ASSERT_TRUE(response);
18235 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0218236 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0318237 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218238 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0118239 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318240 EXPECT_EQ("hello!", response_data);
18241 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618242 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318243 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2618244 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318245
18246 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1118247 SpdySessionKey spdy_session_key_a1(
18248 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
dalyk51ab46b2019-10-15 15:14:3418249 SpdySessionKey::IsProxySession::kFalse, SocketTag(),
18250 NetworkIsolationKey(), false /* disable_secure_dns */);
[email protected]483fa202013-05-14 01:07:0318251 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618252 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0318253 HttpRequestInfo request3;
18254 request3.method = "GET";
18255 request3.url = GURL("http://www.a.com/");
18256 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018257 request3.traffic_annotation =
18258 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5818259 trans =
Jeremy Roman0579ed62017-08-29 15:56:1918260 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0318261
tfarina42834112016-09-22 13:38:2018262 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118263 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18264 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0318265
18266 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5218267 ASSERT_TRUE(response);
18268 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0318269 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
18270 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5218271 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0118272 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0318273 EXPECT_EQ("hello!", response_data);
18274 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618275 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0318276 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2618277 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0318278}
18279
bncd16676a2016-07-20 16:23:0118280TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0418281 HttpRequestInfo request;
18282 request.method = "GET";
bncce36dca22015-04-21 22:11:2318283 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018284 request.traffic_annotation =
18285 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418286
danakj1fd259a02016-04-16 03:17:0918287 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618288 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418289
ttuttled9dbc652015-09-29 20:00:5918290 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418291 StaticSocketDataProvider data;
18292 data.set_connect_data(mock_connect);
18293 session_deps_.socket_factory->AddSocketDataProvider(&data);
18294
18295 TestCompletionCallback callback;
18296
tfarina42834112016-09-22 13:38:2018297 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418299
18300 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118301 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418302
ttuttle1f2d7e92015-04-28 16:17:4718303 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618304 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718305 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118306 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918307
18308 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618309 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918310 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418311}
18312
bncd16676a2016-07-20 16:23:0118313TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0418314 HttpRequestInfo request;
18315 request.method = "GET";
bncce36dca22015-04-21 22:11:2318316 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018317 request.traffic_annotation =
18318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418319
danakj1fd259a02016-04-16 03:17:0918320 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618321 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418322
ttuttled9dbc652015-09-29 20:00:5918323 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0418324 StaticSocketDataProvider data;
18325 data.set_connect_data(mock_connect);
18326 session_deps_.socket_factory->AddSocketDataProvider(&data);
18327
18328 TestCompletionCallback callback;
18329
tfarina42834112016-09-22 13:38:2018330 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118331 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418332
18333 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118334 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0418335
ttuttle1f2d7e92015-04-28 16:17:4718336 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1618337 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4718338 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0118339 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5918340
18341 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1618342 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5918343 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0418344}
18345
bncd16676a2016-07-20 16:23:0118346TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418347 HttpRequestInfo request;
18348 request.method = "GET";
bncce36dca22015-04-21 22:11:2318349 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018350 request.traffic_annotation =
18351 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418352
danakj1fd259a02016-04-16 03:17:0918353 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618354 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418355
18356 MockWrite data_writes[] = {
18357 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18358 };
18359 MockRead data_reads[] = {
18360 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18361 };
18362
Ryan Sleevib8d7ea02018-05-07 20:01:0118363 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418364 session_deps_.socket_factory->AddSocketDataProvider(&data);
18365
18366 TestCompletionCallback callback;
18367
tfarina42834112016-09-22 13:38:2018368 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118369 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418370
18371 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118372 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418373}
18374
bncd16676a2016-07-20 16:23:0118375TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0418376 HttpRequestInfo request;
18377 request.method = "GET";
bncce36dca22015-04-21 22:11:2318378 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018379 request.traffic_annotation =
18380 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418381
danakj1fd259a02016-04-16 03:17:0918382 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618383 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418384
18385 MockWrite data_writes[] = {
18386 MockWrite(ASYNC, ERR_CONNECTION_RESET),
18387 };
18388 MockRead data_reads[] = {
18389 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
18390 };
18391
Ryan Sleevib8d7ea02018-05-07 20:01:0118392 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418393 session_deps_.socket_factory->AddSocketDataProvider(&data);
18394
18395 TestCompletionCallback callback;
18396
tfarina42834112016-09-22 13:38:2018397 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118398 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418399
18400 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118401 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418402}
18403
bncd16676a2016-07-20 16:23:0118404TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418405 HttpRequestInfo request;
18406 request.method = "GET";
bncce36dca22015-04-21 22:11:2318407 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018408 request.traffic_annotation =
18409 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418410
danakj1fd259a02016-04-16 03:17:0918411 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618412 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418413
18414 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318415 MockWrite(
18416 "GET / HTTP/1.1\r\n"
18417 "Host: www.example.org\r\n"
18418 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418419 };
18420 MockRead data_reads[] = {
18421 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
18422 };
18423
Ryan Sleevib8d7ea02018-05-07 20:01:0118424 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418425 session_deps_.socket_factory->AddSocketDataProvider(&data);
18426
18427 TestCompletionCallback callback;
18428
tfarina42834112016-09-22 13:38:2018429 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118430 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418431
18432 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118433 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418434}
18435
bncd16676a2016-07-20 16:23:0118436TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0418437 HttpRequestInfo request;
18438 request.method = "GET";
bncce36dca22015-04-21 22:11:2318439 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018440 request.traffic_annotation =
18441 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0418442
danakj1fd259a02016-04-16 03:17:0918443 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618444 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0418445
18446 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2318447 MockWrite(
18448 "GET / HTTP/1.1\r\n"
18449 "Host: www.example.org\r\n"
18450 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0418451 };
18452 MockRead data_reads[] = {
18453 MockRead(ASYNC, ERR_CONNECTION_RESET),
18454 };
18455
Ryan Sleevib8d7ea02018-05-07 20:01:0118456 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0418457 session_deps_.socket_factory->AddSocketDataProvider(&data);
18458
18459 TestCompletionCallback callback;
18460
tfarina42834112016-09-22 13:38:2018461 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118462 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0418463
18464 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118465 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0418466}
18467
[email protected]043b68c82013-08-22 23:41:5218468// Tests that when a used socket is returned to the SSL socket pool, it's closed
18469// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118470TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5218471 ClientSocketPoolManager::set_max_sockets_per_group(
18472 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18473 ClientSocketPoolManager::set_max_sockets_per_pool(
18474 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18475
18476 // Set up SSL request.
18477
18478 HttpRequestInfo ssl_request;
18479 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2318480 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018481 ssl_request.traffic_annotation =
18482 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218483
18484 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2318485 MockWrite(
18486 "GET / HTTP/1.1\r\n"
18487 "Host: www.example.org\r\n"
18488 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218489 };
18490 MockRead ssl_reads[] = {
18491 MockRead("HTTP/1.1 200 OK\r\n"),
18492 MockRead("Content-Length: 11\r\n\r\n"),
18493 MockRead("hello world"),
18494 MockRead(SYNCHRONOUS, OK),
18495 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118496 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5218497 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18498
18499 SSLSocketDataProvider ssl(ASYNC, OK);
18500 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18501
18502 // Set up HTTP request.
18503
18504 HttpRequestInfo http_request;
18505 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318506 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018507 http_request.traffic_annotation =
18508 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218509
18510 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318511 MockWrite(
18512 "GET / HTTP/1.1\r\n"
18513 "Host: www.example.org\r\n"
18514 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218515 };
18516 MockRead http_reads[] = {
18517 MockRead("HTTP/1.1 200 OK\r\n"),
18518 MockRead("Content-Length: 7\r\n\r\n"),
18519 MockRead("falafel"),
18520 MockRead(SYNCHRONOUS, OK),
18521 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118522 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218523 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18524
danakj1fd259a02016-04-16 03:17:0918525 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218526
18527 // Start the SSL request.
18528 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1618529 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018530 ASSERT_EQ(ERR_IO_PENDING,
18531 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
18532 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5218533
18534 // Start the HTTP request. Pool should stall.
18535 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618536 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018537 ASSERT_EQ(ERR_IO_PENDING,
18538 http_trans.Start(&http_request, http_callback.callback(),
18539 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118540 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218541
18542 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0118543 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218544 std::string response_data;
bnc691fda62016-08-12 00:43:1618545 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218546 EXPECT_EQ("hello world", response_data);
18547
18548 // The SSL socket should automatically be closed, so the HTTP request can
18549 // start.
Matt Menke9d5e2c92019-02-05 01:42:2318550 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4118551 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218552
18553 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0118554 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1618555 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218556 EXPECT_EQ("falafel", response_data);
18557
dcheng48459ac22014-08-26 00:46:4118558 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218559}
18560
18561// Tests that when a SSL connection is established but there's no corresponding
18562// request that needs it, the new socket is closed if the transport socket pool
18563// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0118564TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5218565 ClientSocketPoolManager::set_max_sockets_per_group(
18566 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18567 ClientSocketPoolManager::set_max_sockets_per_pool(
18568 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
18569
18570 // Set up an ssl request.
18571
18572 HttpRequestInfo ssl_request;
18573 ssl_request.method = "GET";
18574 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1018575 ssl_request.traffic_annotation =
18576 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218577
18578 // No data will be sent on the SSL socket.
18579 StaticSocketDataProvider ssl_data;
18580 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
18581
18582 SSLSocketDataProvider ssl(ASYNC, OK);
18583 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18584
18585 // Set up HTTP request.
18586
18587 HttpRequestInfo http_request;
18588 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2318589 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018590 http_request.traffic_annotation =
18591 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5218592
18593 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2318594 MockWrite(
18595 "GET / HTTP/1.1\r\n"
18596 "Host: www.example.org\r\n"
18597 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5218598 };
18599 MockRead http_reads[] = {
18600 MockRead("HTTP/1.1 200 OK\r\n"),
18601 MockRead("Content-Length: 7\r\n\r\n"),
18602 MockRead("falafel"),
18603 MockRead(SYNCHRONOUS, OK),
18604 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118605 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5218606 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
18607
danakj1fd259a02016-04-16 03:17:0918608 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5218609
18610 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
18611 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2918612 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5918613 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2318614 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218615
18616 // Start the HTTP request. Pool should stall.
18617 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1618618 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018619 ASSERT_EQ(ERR_IO_PENDING,
18620 http_trans.Start(&http_request, http_callback.callback(),
18621 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4118622 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5218623
18624 // The SSL connection will automatically be closed once the connection is
18625 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0118626 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5218627 std::string response_data;
bnc691fda62016-08-12 00:43:1618628 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5218629 EXPECT_EQ("falafel", response_data);
18630
dcheng48459ac22014-08-26 00:46:4118631 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5218632}
18633
bncd16676a2016-07-20 16:23:0118634TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918635 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218636 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918637 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218638 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418639
18640 HttpRequestInfo request;
18641 request.method = "POST";
18642 request.url = GURL("http://www.foo.com/");
18643 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018644 request.traffic_annotation =
18645 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418646
danakj1fd259a02016-04-16 03:17:0918647 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618648 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418649 // Send headers successfully, but get an error while sending the body.
18650 MockWrite data_writes[] = {
18651 MockWrite("POST / HTTP/1.1\r\n"
18652 "Host: www.foo.com\r\n"
18653 "Connection: keep-alive\r\n"
18654 "Content-Length: 3\r\n\r\n"),
18655 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18656 };
18657
18658 MockRead data_reads[] = {
18659 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18660 MockRead("hello world"),
18661 MockRead(SYNCHRONOUS, OK),
18662 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118663 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418664 session_deps_.socket_factory->AddSocketDataProvider(&data);
18665
18666 TestCompletionCallback callback;
18667
tfarina42834112016-09-22 13:38:2018668 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118669 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418670
18671 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118672 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418673
bnc691fda62016-08-12 00:43:1618674 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218675 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418676
wezca1070932016-05-26 20:30:5218677 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418678 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18679
18680 std::string response_data;
bnc691fda62016-08-12 00:43:1618681 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118682 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418683 EXPECT_EQ("hello world", response_data);
18684}
18685
18686// This test makes sure the retry logic doesn't trigger when reading an error
18687// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0118688TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418689 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0918690 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5418691 MockWrite data_writes[] = {
18692 MockWrite("GET / HTTP/1.1\r\n"
18693 "Host: www.foo.com\r\n"
18694 "Connection: keep-alive\r\n\r\n"),
18695 MockWrite("POST / HTTP/1.1\r\n"
18696 "Host: www.foo.com\r\n"
18697 "Connection: keep-alive\r\n"
18698 "Content-Length: 3\r\n\r\n"),
18699 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18700 };
18701
18702 MockRead data_reads[] = {
18703 MockRead("HTTP/1.1 200 Peachy\r\n"
18704 "Content-Length: 14\r\n\r\n"),
18705 MockRead("first response"),
18706 MockRead("HTTP/1.1 400 Not OK\r\n"
18707 "Content-Length: 15\r\n\r\n"),
18708 MockRead("second response"),
18709 MockRead(SYNCHRONOUS, OK),
18710 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118711 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418712 session_deps_.socket_factory->AddSocketDataProvider(&data);
18713
18714 TestCompletionCallback callback;
18715 HttpRequestInfo request1;
18716 request1.method = "GET";
18717 request1.url = GURL("http://www.foo.com/");
18718 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018719 request1.traffic_annotation =
18720 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418721
bnc87dcefc2017-05-25 12:47:5818722 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1918723 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018724 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118725 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418726
18727 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118728 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418729
18730 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5218731 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5418732
wezca1070932016-05-26 20:30:5218733 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5418734 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
18735
18736 std::string response_data1;
18737 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0118738 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418739 EXPECT_EQ("first response", response_data1);
18740 // Delete the transaction to release the socket back into the socket pool.
18741 trans1.reset();
18742
danakj1fd259a02016-04-16 03:17:0918743 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218744 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918745 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218746 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418747
18748 HttpRequestInfo request2;
18749 request2.method = "POST";
18750 request2.url = GURL("http://www.foo.com/");
18751 request2.upload_data_stream = &upload_data_stream;
18752 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1018753 request2.traffic_annotation =
18754 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418755
bnc691fda62016-08-12 00:43:1618756 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2018757 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118758 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418759
18760 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118761 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418762
bnc691fda62016-08-12 00:43:1618763 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5218764 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5418765
wezca1070932016-05-26 20:30:5218766 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5418767 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
18768
18769 std::string response_data2;
bnc691fda62016-08-12 00:43:1618770 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0118771 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418772 EXPECT_EQ("second response", response_data2);
18773}
18774
bncd16676a2016-07-20 16:23:0118775TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418776 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0918777 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218778 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918779 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218780 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418781
18782 HttpRequestInfo request;
18783 request.method = "POST";
18784 request.url = GURL("http://www.foo.com/");
18785 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018786 request.traffic_annotation =
18787 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418788
danakj1fd259a02016-04-16 03:17:0918789 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618790 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418791 // Send headers successfully, but get an error while sending the body.
18792 MockWrite data_writes[] = {
18793 MockWrite("POST / HTTP/1.1\r\n"
18794 "Host: www.foo.com\r\n"
18795 "Connection: keep-alive\r\n"
18796 "Content-Length: 3\r\n\r\n"
18797 "fo"),
18798 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18799 };
18800
18801 MockRead data_reads[] = {
18802 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18803 MockRead("hello world"),
18804 MockRead(SYNCHRONOUS, OK),
18805 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118806 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418807 session_deps_.socket_factory->AddSocketDataProvider(&data);
18808
18809 TestCompletionCallback callback;
18810
tfarina42834112016-09-22 13:38:2018811 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118812 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418813
18814 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118815 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418816
bnc691fda62016-08-12 00:43:1618817 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218818 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418819
wezca1070932016-05-26 20:30:5218820 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418821 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18822
18823 std::string response_data;
bnc691fda62016-08-12 00:43:1618824 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118825 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418826 EXPECT_EQ("hello world", response_data);
18827}
18828
18829// This tests the more common case than the previous test, where headers and
18830// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0118831TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0718832 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5418833
18834 HttpRequestInfo request;
18835 request.method = "POST";
18836 request.url = GURL("http://www.foo.com/");
18837 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018838 request.traffic_annotation =
18839 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418840
danakj1fd259a02016-04-16 03:17:0918841 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618842 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418843 // Send headers successfully, but get an error while sending the body.
18844 MockWrite data_writes[] = {
18845 MockWrite("POST / HTTP/1.1\r\n"
18846 "Host: www.foo.com\r\n"
18847 "Connection: keep-alive\r\n"
18848 "Transfer-Encoding: chunked\r\n\r\n"),
18849 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18850 };
18851
18852 MockRead data_reads[] = {
18853 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18854 MockRead("hello world"),
18855 MockRead(SYNCHRONOUS, OK),
18856 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118857 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418858 session_deps_.socket_factory->AddSocketDataProvider(&data);
18859
18860 TestCompletionCallback callback;
18861
tfarina42834112016-09-22 13:38:2018862 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118863 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418864 // Make sure the headers are sent before adding a chunk. This ensures that
18865 // they can't be merged with the body in a single send. Not currently
18866 // necessary since a chunked body is never merged with headers, but this makes
18867 // the test more future proof.
18868 base::RunLoop().RunUntilIdle();
18869
mmenkecbc2b712014-10-09 20:29:0718870 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5418871
18872 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118873 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418874
bnc691fda62016-08-12 00:43:1618875 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218876 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418877
wezca1070932016-05-26 20:30:5218878 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418879 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18880
18881 std::string response_data;
bnc691fda62016-08-12 00:43:1618882 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118883 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418884 EXPECT_EQ("hello world", response_data);
18885}
18886
bncd16676a2016-07-20 16:23:0118887TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918888 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218889 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918890 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218891 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418892
18893 HttpRequestInfo request;
18894 request.method = "POST";
18895 request.url = GURL("http://www.foo.com/");
18896 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018897 request.traffic_annotation =
18898 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418899
danakj1fd259a02016-04-16 03:17:0918900 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618901 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418902
18903 MockWrite data_writes[] = {
18904 MockWrite("POST / HTTP/1.1\r\n"
18905 "Host: www.foo.com\r\n"
18906 "Connection: keep-alive\r\n"
18907 "Content-Length: 3\r\n\r\n"),
18908 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18909 };
18910
18911 MockRead data_reads[] = {
18912 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
18913 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
18914 MockRead("hello world"),
18915 MockRead(SYNCHRONOUS, OK),
18916 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118917 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418918 session_deps_.socket_factory->AddSocketDataProvider(&data);
18919
18920 TestCompletionCallback callback;
18921
tfarina42834112016-09-22 13:38:2018922 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118923 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418924
18925 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118926 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418927
bnc691fda62016-08-12 00:43:1618928 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5218929 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5418930
wezca1070932016-05-26 20:30:5218931 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5418932 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
18933
18934 std::string response_data;
bnc691fda62016-08-12 00:43:1618935 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0118936 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5418937 EXPECT_EQ("hello world", response_data);
18938}
18939
bncd16676a2016-07-20 16:23:0118940TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0918941 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218942 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918943 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218944 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418945
18946 HttpRequestInfo request;
18947 request.method = "POST";
18948 request.url = GURL("http://www.foo.com/");
18949 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018950 request.traffic_annotation =
18951 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418952
danakj1fd259a02016-04-16 03:17:0918953 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618954 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418955 // Send headers successfully, but get an error while sending the body.
18956 MockWrite data_writes[] = {
18957 MockWrite("POST / HTTP/1.1\r\n"
18958 "Host: www.foo.com\r\n"
18959 "Connection: keep-alive\r\n"
18960 "Content-Length: 3\r\n\r\n"),
18961 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
18962 };
18963
18964 MockRead data_reads[] = {
18965 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
18966 MockRead("hello world"),
18967 MockRead(SYNCHRONOUS, OK),
18968 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118969 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5418970 session_deps_.socket_factory->AddSocketDataProvider(&data);
18971
18972 TestCompletionCallback callback;
18973
tfarina42834112016-09-22 13:38:2018974 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118975 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5418976
18977 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118978 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5418979}
18980
bncd16676a2016-07-20 16:23:0118981TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5418982 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0918983 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218984 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918985 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218986 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5418987
18988 HttpRequestInfo request;
18989 request.method = "POST";
18990 request.url = GURL("http://www.foo.com/");
18991 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018992 request.traffic_annotation =
18993 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5418994
danakj1fd259a02016-04-16 03:17:0918995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618996 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5418997 // Send headers successfully, but get an error while sending the body.
18998 MockWrite data_writes[] = {
18999 MockWrite("POST / HTTP/1.1\r\n"
19000 "Host: www.foo.com\r\n"
19001 "Connection: keep-alive\r\n"
19002 "Content-Length: 3\r\n\r\n"),
19003 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19004 };
19005
19006 MockRead data_reads[] = {
19007 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
19008 MockRead("HTTP/1.0 302 Redirect\r\n"),
19009 MockRead("Location: http://somewhere-else.com/\r\n"),
19010 MockRead("Content-Length: 0\r\n\r\n"),
19011 MockRead(SYNCHRONOUS, OK),
19012 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119013 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419014 session_deps_.socket_factory->AddSocketDataProvider(&data);
19015
19016 TestCompletionCallback callback;
19017
tfarina42834112016-09-22 13:38:2019018 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119019 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419020
19021 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119022 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419023}
19024
bncd16676a2016-07-20 16:23:0119025TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0919026 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219027 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919028 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219029 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5419030
19031 HttpRequestInfo request;
19032 request.method = "POST";
19033 request.url = GURL("http://www.foo.com/");
19034 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019035 request.traffic_annotation =
19036 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5419037
danakj1fd259a02016-04-16 03:17:0919038 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619039 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419040 // Send headers successfully, but get an error while sending the body.
19041 MockWrite data_writes[] = {
19042 MockWrite("POST / HTTP/1.1\r\n"
19043 "Host: www.foo.com\r\n"
19044 "Connection: keep-alive\r\n"
19045 "Content-Length: 3\r\n\r\n"),
19046 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19047 };
19048
19049 MockRead data_reads[] = {
19050 MockRead("HTTP 0.9 rocks!"),
19051 MockRead(SYNCHRONOUS, OK),
19052 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119053 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419054 session_deps_.socket_factory->AddSocketDataProvider(&data);
19055
19056 TestCompletionCallback callback;
19057
tfarina42834112016-09-22 13:38:2019058 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119059 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419060
19061 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119062 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419063}
19064
bncd16676a2016-07-20 16:23:0119065TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0919066 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219067 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919068 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219069 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5419070
19071 HttpRequestInfo request;
19072 request.method = "POST";
19073 request.url = GURL("http://www.foo.com/");
19074 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019075 request.traffic_annotation =
19076 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5419077
danakj1fd259a02016-04-16 03:17:0919078 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619079 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5419080 // Send headers successfully, but get an error while sending the body.
19081 MockWrite data_writes[] = {
19082 MockWrite("POST / HTTP/1.1\r\n"
19083 "Host: www.foo.com\r\n"
19084 "Connection: keep-alive\r\n"
19085 "Content-Length: 3\r\n\r\n"),
19086 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
19087 };
19088
19089 MockRead data_reads[] = {
19090 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
19091 MockRead(SYNCHRONOUS, OK),
19092 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119093 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5419094 session_deps_.socket_factory->AddSocketDataProvider(&data);
19095
19096 TestCompletionCallback callback;
19097
tfarina42834112016-09-22 13:38:2019098 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119099 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5419100
19101 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119102 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5419103}
19104
Bence Békydca6bd92018-01-30 13:43:0619105#if BUILDFLAG(ENABLE_WEBSOCKETS)
19106
19107namespace {
19108
19109void AddWebSocketHeaders(HttpRequestHeaders* headers) {
19110 headers->SetHeader("Connection", "Upgrade");
19111 headers->SetHeader("Upgrade", "websocket");
19112 headers->SetHeader("Origin", "http://www.example.org");
19113 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0619114}
19115
19116} // namespace
19117
19118TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0119119 for (bool secure : {true, false}) {
19120 MockWrite data_writes[] = {
19121 MockWrite("GET / HTTP/1.1\r\n"
19122 "Host: www.example.org\r\n"
19123 "Connection: Upgrade\r\n"
19124 "Upgrade: websocket\r\n"
19125 "Origin: http://www.example.org\r\n"
19126 "Sec-WebSocket-Version: 13\r\n"
19127 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19128 "Sec-WebSocket-Extensions: permessage-deflate; "
19129 "client_max_window_bits\r\n\r\n")};
19130
19131 MockRead data_reads[] = {
19132 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19133 "Upgrade: websocket\r\n"
19134 "Connection: Upgrade\r\n"
19135 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
19136
Ryan Sleevib8d7ea02018-05-07 20:01:0119137 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0119138 session_deps_.socket_factory->AddSocketDataProvider(&data);
19139 SSLSocketDataProvider ssl(ASYNC, OK);
19140 if (secure)
19141 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0619142
19143 HttpRequestInfo request;
19144 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0119145 request.url =
19146 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
19147 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e62018-02-07 07:41:1019148 request.traffic_annotation =
19149 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0619150
Bence Béky2fcf4fa2018-04-06 20:06:0119151 TestWebSocketHandshakeStreamCreateHelper
19152 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1519153
Bence Béky2fcf4fa2018-04-06 20:06:0119154 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0619155 HttpNetworkTransaction trans(LOW, session.get());
19156 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0119157 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0619158
19159 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0119160 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19161 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0619162
Bence Béky2fcf4fa2018-04-06 20:06:0119163 const HttpStreamRequest* stream_request = trans.stream_request_.get();
19164 ASSERT_TRUE(stream_request);
19165 EXPECT_EQ(&websocket_handshake_stream_create_helper,
19166 stream_request->websocket_handshake_stream_create_helper());
19167
19168 rv = callback.WaitForResult();
19169 EXPECT_THAT(rv, IsOk());
19170
19171 EXPECT_TRUE(data.AllReadDataConsumed());
19172 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0619173 }
19174}
19175
Adam Rice425cf122015-01-19 06:18:2419176// Verify that proxy headers are not sent to the destination server when
19177// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0119178TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2419179 HttpRequestInfo request;
19180 request.method = "GET";
bncce36dca22015-04-21 22:11:2319181 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019182 request.traffic_annotation =
19183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419184 AddWebSocketHeaders(&request.extra_headers);
19185
19186 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5919187 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619188 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919189 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419190
danakj1fd259a02016-04-16 03:17:0919191 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2419192
19193 // Since a proxy is configured, try to establish a tunnel.
19194 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1719195 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19196 "Host: www.example.org:443\r\n"
19197 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419198
19199 // After calling trans->RestartWithAuth(), this is the request we should
19200 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1719201 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19202 "Host: www.example.org:443\r\n"
19203 "Proxy-Connection: keep-alive\r\n"
19204 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419205
rsleevidb16bb02015-11-12 23:47:1719206 MockWrite("GET / HTTP/1.1\r\n"
19207 "Host: www.example.org\r\n"
19208 "Connection: Upgrade\r\n"
19209 "Upgrade: websocket\r\n"
19210 "Origin: http://www.example.org\r\n"
19211 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1519212 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19213 "Sec-WebSocket-Extensions: permessage-deflate; "
19214 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419215
19216 // The proxy responds to the connect with a 407, using a persistent
19217 // connection.
19218 MockRead data_reads[] = {
19219 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1519220 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
19221 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
19222 "Content-Length: 0\r\n"
19223 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419224
19225 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19226
Bence Béky8d1c6052018-02-07 12:48:1519227 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19228 "Upgrade: websocket\r\n"
19229 "Connection: Upgrade\r\n"
19230 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419231
Ryan Sleevib8d7ea02018-05-07 20:01:0119232 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2419233 session_deps_.socket_factory->AddSocketDataProvider(&data);
19234 SSLSocketDataProvider ssl(ASYNC, OK);
19235 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19236
Bence Béky8d1c6052018-02-07 12:48:1519237 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
19238
bnc87dcefc2017-05-25 12:47:5819239 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1919240 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2419241 trans->SetWebSocketHandshakeStreamCreateHelper(
19242 &websocket_stream_create_helper);
19243
19244 {
19245 TestCompletionCallback callback;
19246
tfarina42834112016-09-22 13:38:2019247 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119248 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419249
19250 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119251 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419252 }
19253
19254 const HttpResponseInfo* response = trans->GetResponseInfo();
19255 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219256 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419257 EXPECT_EQ(407, response->headers->response_code());
19258
19259 {
19260 TestCompletionCallback callback;
19261
19262 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
19263 callback.callback());
robpercival214763f2016-07-01 23:27:0119264 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419265
19266 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119267 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419268 }
19269
19270 response = trans->GetResponseInfo();
19271 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219272 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419273
19274 EXPECT_EQ(101, response->headers->response_code());
19275
19276 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119277 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419278}
19279
19280// Verify that proxy headers are not sent to the destination server when
19281// establishing a tunnel for an insecure WebSocket connection.
19282// This requires the authentication info to be injected into the auth cache
19283// due to crbug.com/395064
19284// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0119285TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2419286 HttpRequestInfo request;
19287 request.method = "GET";
bncce36dca22015-04-21 22:11:2319288 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019289 request.traffic_annotation =
19290 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419291 AddWebSocketHeaders(&request.extra_headers);
19292
19293 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5919294 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619295 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919296 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2419297
danakj1fd259a02016-04-16 03:17:0919298 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2419299
19300 MockWrite data_writes[] = {
19301 // Try to establish a tunnel for the WebSocket connection, with
19302 // credentials. Because WebSockets have a separate set of socket pools,
19303 // they cannot and will not use the same TCP/IP connection as the
19304 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1519305 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
19306 "Host: www.example.org:80\r\n"
19307 "Proxy-Connection: keep-alive\r\n"
19308 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2419309
Bence Béky8d1c6052018-02-07 12:48:1519310 MockWrite("GET / HTTP/1.1\r\n"
19311 "Host: www.example.org\r\n"
19312 "Connection: Upgrade\r\n"
19313 "Upgrade: websocket\r\n"
19314 "Origin: http://www.example.org\r\n"
19315 "Sec-WebSocket-Version: 13\r\n"
19316 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
19317 "Sec-WebSocket-Extensions: permessage-deflate; "
19318 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419319
19320 MockRead data_reads[] = {
19321 // HTTP CONNECT with credentials.
19322 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19323
19324 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1519325 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
19326 "Upgrade: websocket\r\n"
19327 "Connection: Upgrade\r\n"
19328 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2419329
Ryan Sleevib8d7ea02018-05-07 20:01:0119330 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2419331 session_deps_.socket_factory->AddSocketDataProvider(&data);
19332
19333 session->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:3319334 GURL("http://myproxy:70/"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:2619335 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
19336 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Adam Rice425cf122015-01-19 06:18:2419337
Bence Béky8d1c6052018-02-07 12:48:1519338 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
19339
bnc87dcefc2017-05-25 12:47:5819340 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1919341 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2419342 trans->SetWebSocketHandshakeStreamCreateHelper(
19343 &websocket_stream_create_helper);
19344
19345 TestCompletionCallback callback;
19346
tfarina42834112016-09-22 13:38:2019347 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0119348 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2419349
19350 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0119351 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2419352
19353 const HttpResponseInfo* response = trans->GetResponseInfo();
19354 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5219355 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2419356
19357 EXPECT_EQ(101, response->headers->response_code());
19358
19359 trans.reset();
Matt Menke433de6d2020-03-04 00:24:1119360 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Adam Rice425cf122015-01-19 06:18:2419361}
19362
Matt Menke1d6093e32019-03-22 17:33:4319363// WebSockets over QUIC is not supported, including over QUIC proxies.
19364TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
19365 for (bool secure : {true, false}) {
19366 SCOPED_TRACE(secure);
19367 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619368 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menke1d6093e32019-03-22 17:33:4319369 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
19370 session_deps_.enable_quic = true;
19371
19372 HttpRequestInfo request;
19373 request.url =
19374 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
19375 AddWebSocketHeaders(&request.extra_headers);
19376 request.traffic_annotation =
19377 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19378
19379 TestWebSocketHandshakeStreamCreateHelper
19380 websocket_handshake_stream_create_helper;
19381
19382 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19383 HttpNetworkTransaction trans(LOW, session.get());
19384 trans.SetWebSocketHandshakeStreamCreateHelper(
19385 &websocket_handshake_stream_create_helper);
19386
19387 TestCompletionCallback callback;
19388 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19389 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19390
19391 rv = callback.WaitForResult();
19392 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
19393 }
19394}
19395
Bence Békydca6bd92018-01-30 13:43:0619396#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
19397
bncd16676a2016-07-20 16:23:0119398TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0919399 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219400 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919401 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219402 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219403
19404 HttpRequestInfo request;
19405 request.method = "POST";
19406 request.url = GURL("http://www.foo.com/");
19407 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019408 request.traffic_annotation =
19409 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219410
danakj1fd259a02016-04-16 03:17:0919411 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619412 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219413 MockWrite data_writes[] = {
19414 MockWrite("POST / HTTP/1.1\r\n"
19415 "Host: www.foo.com\r\n"
19416 "Connection: keep-alive\r\n"
19417 "Content-Length: 3\r\n\r\n"),
19418 MockWrite("foo"),
19419 };
19420
19421 MockRead data_reads[] = {
19422 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19423 MockRead(SYNCHRONOUS, OK),
19424 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119425 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219426 session_deps_.socket_factory->AddSocketDataProvider(&data);
19427
19428 TestCompletionCallback callback;
19429
19430 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019431 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119432 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219433
19434 std::string response_data;
bnc691fda62016-08-12 00:43:1619435 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219436
Ryan Sleevib8d7ea02018-05-07 20:01:0119437 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19438 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219439}
19440
bncd16676a2016-07-20 16:23:0119441TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0919442 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2219443 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1919444 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2219445 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2219446
19447 HttpRequestInfo request;
19448 request.method = "POST";
19449 request.url = GURL("http://www.foo.com/");
19450 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019451 request.traffic_annotation =
19452 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219453
danakj1fd259a02016-04-16 03:17:0919454 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619455 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219456 MockWrite data_writes[] = {
19457 MockWrite("POST / HTTP/1.1\r\n"
19458 "Host: www.foo.com\r\n"
19459 "Connection: keep-alive\r\n"
19460 "Content-Length: 3\r\n\r\n"),
19461 MockWrite("foo"),
19462 };
19463
19464 MockRead data_reads[] = {
19465 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
19466 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19467 MockRead(SYNCHRONOUS, OK),
19468 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119469 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219470 session_deps_.socket_factory->AddSocketDataProvider(&data);
19471
19472 TestCompletionCallback callback;
19473
19474 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019475 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0119476 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219477
19478 std::string response_data;
bnc691fda62016-08-12 00:43:1619479 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219480
Ryan Sleevib8d7ea02018-05-07 20:01:0119481 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19482 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219483}
19484
bncd16676a2016-07-20 16:23:0119485TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2219486 ChunkedUploadDataStream upload_data_stream(0);
19487
19488 HttpRequestInfo request;
19489 request.method = "POST";
19490 request.url = GURL("http://www.foo.com/");
19491 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1019492 request.traffic_annotation =
19493 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2219494
danakj1fd259a02016-04-16 03:17:0919495 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1619496 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2219497 // Send headers successfully, but get an error while sending the body.
19498 MockWrite data_writes[] = {
19499 MockWrite("POST / HTTP/1.1\r\n"
19500 "Host: www.foo.com\r\n"
19501 "Connection: keep-alive\r\n"
19502 "Transfer-Encoding: chunked\r\n\r\n"),
19503 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
19504 };
19505
19506 MockRead data_reads[] = {
19507 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
19508 MockRead(SYNCHRONOUS, OK),
19509 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119510 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2219511 session_deps_.socket_factory->AddSocketDataProvider(&data);
19512
19513 TestCompletionCallback callback;
19514
19515 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2019516 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2219517
19518 base::RunLoop().RunUntilIdle();
19519 upload_data_stream.AppendData("f", 1, false);
19520
19521 base::RunLoop().RunUntilIdle();
19522 upload_data_stream.AppendData("oo", 2, true);
19523
robpercival214763f2016-07-01 23:27:0119524 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2219525
19526 std::string response_data;
bnc691fda62016-08-12 00:43:1619527 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2219528
Ryan Sleevib8d7ea02018-05-07 20:01:0119529 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
19530 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2219531}
19532
eustasc7d27da2017-04-06 10:33:2019533void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
19534 const std::string& accept_encoding,
19535 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0319536 const std::string& location,
eustasc7d27da2017-04-06 10:33:2019537 bool should_match) {
19538 HttpRequestInfo request;
19539 request.method = "GET";
19540 request.url = GURL("http://www.foo.com/");
19541 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
19542 accept_encoding);
Ramin Halavatib5e433e62018-02-07 07:41:1019543 request.traffic_annotation =
19544 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2019545
19546 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
19547 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19548 // Send headers successfully, but get an error while sending the body.
19549 MockWrite data_writes[] = {
19550 MockWrite("GET / HTTP/1.1\r\n"
19551 "Host: www.foo.com\r\n"
19552 "Connection: keep-alive\r\n"
19553 "Accept-Encoding: "),
19554 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
19555 };
19556
sky50576f32017-05-01 19:28:0319557 std::string response_code = "200 OK";
19558 std::string extra;
19559 if (!location.empty()) {
19560 response_code = "301 Redirect\r\nLocation: ";
19561 response_code.append(location);
19562 }
19563
eustasc7d27da2017-04-06 10:33:2019564 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0319565 MockRead("HTTP/1.0 "),
19566 MockRead(response_code.data()),
19567 MockRead("\r\nContent-Encoding: "),
19568 MockRead(content_encoding.data()),
19569 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2019570 MockRead(SYNCHRONOUS, OK),
19571 };
Ryan Sleevib8d7ea02018-05-07 20:01:0119572 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2019573 session_deps->socket_factory->AddSocketDataProvider(&data);
19574
19575 TestCompletionCallback callback;
19576
19577 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19578 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19579
19580 rv = callback.WaitForResult();
19581 if (should_match) {
19582 EXPECT_THAT(rv, IsOk());
19583 } else {
19584 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
19585 }
19586}
19587
19588TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0319589 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2019590}
19591
19592TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0319593 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
19594 true);
eustasc7d27da2017-04-06 10:33:2019595}
19596
19597TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
19598 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0319599 "", false);
19600}
19601
19602TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
19603 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
19604 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2019605}
19606
xunjieli96f2a402017-06-05 17:24:2719607TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
19608 ProxyConfig proxy_config;
19609 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19610 proxy_config.set_pac_mandatory(true);
19611 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619612 session_deps_.proxy_resolution_service.reset(
19613 new ConfiguredProxyResolutionService(
19614 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19615 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0919616 std::make_unique<FailingProxyResolverFactory>(), nullptr,
19617 /*quick_check_enabled=*/true));
xunjieli96f2a402017-06-05 17:24:2719618
19619 HttpRequestInfo request;
19620 request.method = "GET";
19621 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019622 request.traffic_annotation =
19623 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719624
19625 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19626 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19627
19628 TestCompletionCallback callback;
19629
19630 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19631 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19632 EXPECT_THAT(callback.WaitForResult(),
19633 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19634}
19635
19636TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
19637 ProxyConfig proxy_config;
19638 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
19639 proxy_config.set_pac_mandatory(true);
19640 MockAsyncProxyResolverFactory* proxy_resolver_factory =
19641 new MockAsyncProxyResolverFactory(false);
19642 MockAsyncProxyResolver resolver;
Nicolas Arciniegad2013f92020-02-07 23:00:5619643 session_deps_.proxy_resolution_service.reset(
19644 new ConfiguredProxyResolutionService(
19645 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
19646 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Eric Roman3be01ba2020-04-03 21:37:0919647 base::WrapUnique(proxy_resolver_factory), nullptr,
19648 /*quick_check_enabled=*/true));
xunjieli96f2a402017-06-05 17:24:2719649 HttpRequestInfo request;
19650 request.method = "GET";
19651 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019652 request.traffic_annotation =
19653 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719654
19655 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19656 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19657
19658 TestCompletionCallback callback;
19659 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19660 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19661
19662 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
19663 ERR_FAILED, &resolver);
19664 EXPECT_THAT(callback.WaitForResult(),
19665 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
19666}
19667
19668TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5919669 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619670 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Ramin Halavatica8d5252018-03-12 05:33:4919671 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719672 session_deps_.enable_quic = false;
19673 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19674
19675 HttpRequestInfo request;
19676 request.method = "GET";
19677 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1019678 request.traffic_annotation =
19679 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2719680
19681 TestCompletionCallback callback;
19682 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19683 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19684 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19685
19686 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
19687}
19688
Douglas Creager3cb042052018-11-06 23:08:5219689//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1419690// Reporting tests
19691
19692#if BUILDFLAG(ENABLE_REPORTING)
19693class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
19694 protected:
19695 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619696 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1419697 auto test_reporting_context = std::make_unique<TestReportingContext>(
19698 &clock_, &tick_clock_, ReportingPolicy());
19699 test_reporting_context_ = test_reporting_context.get();
19700 session_deps_.reporting_service =
19701 ReportingService::CreateForTesting(std::move(test_reporting_context));
19702 }
19703
19704 TestReportingContext* reporting_context() const {
19705 return test_reporting_context_;
19706 }
19707
19708 void clear_reporting_service() {
19709 session_deps_.reporting_service.reset();
19710 test_reporting_context_ = nullptr;
19711 }
19712
19713 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4219714 void RequestPolicy(CertStatus cert_status = 0) {
19715 HttpRequestInfo request;
19716 request.method = "GET";
19717 request.url = GURL(url_);
19718 request.traffic_annotation =
19719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19720
Lily Chend3930e72019-03-01 19:31:1119721 MockWrite data_writes[] = {
19722 MockWrite("GET / HTTP/1.1\r\n"
19723 "Host: www.example.org\r\n"
19724 "Connection: keep-alive\r\n\r\n"),
19725 };
Douglas Creager134b52e2018-11-09 18:00:1419726 MockRead data_reads[] = {
19727 MockRead("HTTP/1.0 200 OK\r\n"),
19728 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
19729 "\"endpoints\": [{\"url\": "
19730 "\"https://www.example.org/upload/\"}]}\r\n"),
19731 MockRead("\r\n"),
19732 MockRead("hello world"),
19733 MockRead(SYNCHRONOUS, OK),
19734 };
Douglas Creager134b52e2018-11-09 18:00:1419735
Lily Chenfec60d92019-01-24 01:16:4219736 StaticSocketDataProvider reads(data_reads, data_writes);
19737 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1419738
19739 SSLSocketDataProvider ssl(ASYNC, OK);
19740 if (request.url.SchemeIsCryptographic()) {
19741 ssl.ssl_info.cert =
19742 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19743 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219744 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1419745 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19746 }
19747
Douglas Creager134b52e2018-11-09 18:00:1419748 TestCompletionCallback callback;
19749 auto session = CreateSession(&session_deps_);
19750 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19751 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4219752 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1419753 }
19754
19755 protected:
19756 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1419757
19758 private:
19759 TestReportingContext* test_reporting_context_;
19760};
19761
19762TEST_F(HttpNetworkTransactionReportingTest,
19763 DontProcessReportToHeaderNoService) {
Douglas Creager134b52e2018-11-09 18:00:1419764 clear_reporting_service();
19765 RequestPolicy();
Lily Chen9364a4c2020-06-25 16:07:5219766 // No crash.
Douglas Creager134b52e2018-11-09 18:00:1419767}
19768
19769TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
Douglas Creager134b52e2018-11-09 18:00:1419770 url_ = "http://www.example.org/";
19771 RequestPolicy();
Lily Chen9364a4c2020-06-25 16:07:5219772 EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
Douglas Creager134b52e2018-11-09 18:00:1419773}
19774
19775TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
19776 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5419777 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1019778 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5419779 reporting_context()->cache()->GetEndpointForTesting(
Lily Chenad5dd0802020-03-10 21:58:0919780 ReportingEndpointGroupKey(
19781 NetworkIsolationKey(),
19782 url::Origin::Create(GURL("https://www.example.org/")), "nel"),
Lily Chenefb6fcf2019-04-19 04:17:5419783 GURL("https://www.example.org/upload/"));
19784 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1419785}
19786
19787TEST_F(HttpNetworkTransactionReportingTest,
19788 DontProcessReportToHeaderInvalidHttps) {
Lily Chenfec60d92019-01-24 01:16:4219789 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
19790 RequestPolicy(cert_status);
Lily Chen9364a4c2020-06-25 16:07:5219791 EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
Douglas Creager134b52e2018-11-09 18:00:1419792}
19793#endif // BUILDFLAG(ENABLE_REPORTING)
19794
19795//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5219796// Network Error Logging tests
19797
19798#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4219799namespace {
19800
19801const char kUserAgent[] = "Mozilla/1.0";
19802const char kReferrer[] = "https://www.referrer.org/";
19803
19804} // namespace
19805
Douglas Creager3cb042052018-11-06 23:08:5219806class HttpNetworkTransactionNetworkErrorLoggingTest
19807 : public HttpNetworkTransactionTest {
19808 protected:
19809 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3619810 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5219811 auto network_error_logging_service =
19812 std::make_unique<TestNetworkErrorLoggingService>();
19813 test_network_error_logging_service_ = network_error_logging_service.get();
19814 session_deps_.network_error_logging_service =
19815 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4219816
19817 extra_headers_.SetHeader("User-Agent", kUserAgent);
19818 extra_headers_.SetHeader("Referer", kReferrer);
19819
19820 request_.method = "GET";
19821 request_.url = GURL(url_);
19822 request_.extra_headers = extra_headers_;
19823 request_.reporting_upload_depth = reporting_upload_depth_;
19824 request_.traffic_annotation =
19825 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5219826 }
19827
19828 TestNetworkErrorLoggingService* network_error_logging_service() const {
19829 return test_network_error_logging_service_;
19830 }
19831
19832 void clear_network_error_logging_service() {
19833 session_deps_.network_error_logging_service.reset();
19834 test_network_error_logging_service_ = nullptr;
19835 }
19836
19837 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4219838 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3619839 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5319840 MockWrite data_writes[] = {
19841 MockWrite("GET / HTTP/1.1\r\n"
19842 "Host: www.example.org\r\n"
19843 "Connection: keep-alive\r\n"),
19844 MockWrite(ASYNC, extra_header_string.data(),
19845 extra_header_string.size()),
19846 };
Lily Chend3930e72019-03-01 19:31:1119847 MockRead data_reads[] = {
19848 MockRead("HTTP/1.0 200 OK\r\n"),
19849 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19850 MockRead("\r\n"),
19851 MockRead("hello world"),
19852 MockRead(SYNCHRONOUS, OK),
19853 };
Douglas Creager3cb042052018-11-06 23:08:5219854
Lily Chenfec60d92019-01-24 01:16:4219855 StaticSocketDataProvider reads(data_reads, data_writes);
19856 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5219857
19858 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4219859 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5219860 ssl.ssl_info.cert =
19861 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19862 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4219863 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5219864 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19865 }
19866
Douglas Creager3cb042052018-11-06 23:08:5219867 TestCompletionCallback callback;
19868 auto session = CreateSession(&session_deps_);
19869 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4219870 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
19871 EXPECT_THAT(callback.GetResult(rv), IsOk());
19872
19873 std::string response_data;
19874 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
19875 EXPECT_EQ("hello world", response_data);
19876 }
19877
19878 void CheckReport(size_t index,
19879 int status_code,
19880 int error_type,
19881 IPAddress server_ip = IPAddress::IPv4Localhost()) {
19882 ASSERT_LT(index, network_error_logging_service()->errors().size());
19883
19884 const NetworkErrorLoggingService::RequestDetails& error =
19885 network_error_logging_service()->errors()[index];
19886 EXPECT_EQ(url_, error.uri);
19887 EXPECT_EQ(kReferrer, error.referrer);
19888 EXPECT_EQ(kUserAgent, error.user_agent);
19889 EXPECT_EQ(server_ip, error.server_ip);
19890 EXPECT_EQ("http/1.1", error.protocol);
19891 EXPECT_EQ("GET", error.method);
19892 EXPECT_EQ(status_code, error.status_code);
19893 EXPECT_EQ(error_type, error.type);
19894 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5219895 }
19896
19897 protected:
19898 std::string url_ = "https://www.example.org/";
19899 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4219900 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3619901 HttpRequestHeaders extra_headers_;
19902 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5219903
19904 private:
19905 TestNetworkErrorLoggingService* test_network_error_logging_service_;
19906};
19907
19908TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19909 DontProcessNelHeaderNoService) {
Douglas Creager3cb042052018-11-06 23:08:5219910 clear_network_error_logging_service();
19911 RequestPolicy();
Lily Chena9e9d6cb2020-06-25 17:34:4919912 // No crash.
Douglas Creager3cb042052018-11-06 23:08:5219913}
19914
19915TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19916 DontProcessNelHeaderHttp) {
Douglas Creager3cb042052018-11-06 23:08:5219917 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4219918 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5219919 RequestPolicy();
Lily Chena9e9d6cb2020-06-25 17:34:4919920 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
Douglas Creager3cb042052018-11-06 23:08:5219921}
19922
Lily Chen90ae93cc2019-02-14 01:15:3919923// Don't set NEL policies received on a proxied connection.
19924TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19925 DontProcessNelHeaderProxy) {
19926 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5619927 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3919928 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Muellerd9342e3a2019-11-26 01:41:1419929 RecordingBoundTestNetLog log;
Lily Chen90ae93cc2019-02-14 01:15:3919930 session_deps_.net_log = log.bound().net_log();
19931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19932
19933 HttpRequestInfo request;
19934 request.method = "GET";
19935 request.url = GURL("https://www.example.org/");
19936 request.traffic_annotation =
19937 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19938
19939 // Since we have proxy, should try to establish tunnel.
19940 MockWrite data_writes1[] = {
19941 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19942 "Host: www.example.org:443\r\n"
19943 "Proxy-Connection: keep-alive\r\n\r\n"),
19944
19945 MockWrite("GET / HTTP/1.1\r\n"
19946 "Host: www.example.org\r\n"
19947 "Connection: keep-alive\r\n\r\n"),
19948 };
19949
19950 MockRead data_reads1[] = {
19951 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19952
19953 MockRead("HTTP/1.1 200 OK\r\n"),
19954 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
19955 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19956 MockRead("Content-Length: 100\r\n\r\n"),
19957 MockRead(SYNCHRONOUS, OK),
19958 };
19959
19960 StaticSocketDataProvider data1(data_reads1, data_writes1);
19961 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19962 SSLSocketDataProvider ssl(ASYNC, OK);
19963 ssl.ssl_info.cert =
19964 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
19965 ASSERT_TRUE(ssl.ssl_info.cert);
19966 ssl.ssl_info.cert_status = 0;
19967 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19968
19969 TestCompletionCallback callback1;
19970 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19971
19972 int rv = trans.Start(&request, callback1.callback(), log.bound());
19973 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19974
19975 rv = callback1.WaitForResult();
19976 EXPECT_THAT(rv, IsOk());
19977
19978 const HttpResponseInfo* response = trans.GetResponseInfo();
19979 ASSERT_TRUE(response);
19980 EXPECT_EQ(200, response->headers->response_code());
19981 EXPECT_TRUE(response->was_fetched_via_proxy);
19982
19983 // No NEL header was set.
19984 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
19985}
19986
Douglas Creager3cb042052018-11-06 23:08:5219987TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
19988 RequestPolicy();
19989 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
19990 const auto& header = network_error_logging_service()->headers()[0];
19991 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
19992 header.origin);
19993 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
19994 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
19995}
19996
19997TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19998 DontProcessNelHeaderInvalidHttps) {
Lily Chenfec60d92019-01-24 01:16:4219999 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
20000 RequestPolicy(cert_status);
Lily Chena9e9d6cb2020-06-25 17:34:4920001 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
Douglas Creager3cb042052018-11-06 23:08:5220002}
Douglas Creageref5eecdc2018-11-09 20:50:3620003
Lily Chenfec60d92019-01-24 01:16:4220004TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3620005 RequestPolicy();
20006 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220007 CheckReport(0 /* index */, 200 /* status_code */, OK);
20008}
20009
20010TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20011 CreateReportErrorAfterStart) {
20012 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20013 auto trans =
20014 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20015
20016 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
20017 StaticSocketDataProvider data;
20018 data.set_connect_data(mock_connect);
20019 session_deps_.socket_factory->AddSocketDataProvider(&data);
20020
20021 TestCompletionCallback callback;
20022
20023 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20024 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
20025
20026 trans.reset();
20027
20028 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20029 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
20030 IPAddress() /* server_ip */);
20031}
20032
20033// Same as above except the error is ASYNC
20034TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20035 CreateReportErrorAfterStartAsync) {
20036 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20037 auto trans =
20038 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20039
20040 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
20041 StaticSocketDataProvider data;
20042 data.set_connect_data(mock_connect);
20043 session_deps_.socket_factory->AddSocketDataProvider(&data);
20044
20045 TestCompletionCallback callback;
20046
20047 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20048 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
20049
20050 trans.reset();
20051
20052 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20053 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
20054 IPAddress() /* server_ip */);
20055}
20056
20057TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20058 CreateReportReadBodyError) {
20059 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5320060 MockWrite data_writes[] = {
20061 MockWrite("GET / HTTP/1.1\r\n"
20062 "Host: www.example.org\r\n"
20063 "Connection: keep-alive\r\n"),
20064 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20065 };
Lily Chend3930e72019-03-01 19:31:1120066 MockRead data_reads[] = {
20067 MockRead("HTTP/1.0 200 OK\r\n"),
20068 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
20069 MockRead("hello world"),
20070 MockRead(SYNCHRONOUS, OK),
20071 };
Lily Chenfec60d92019-01-24 01:16:4220072
20073 StaticSocketDataProvider reads(data_reads, data_writes);
20074 session_deps_.socket_factory->AddSocketDataProvider(&reads);
20075
20076 SSLSocketDataProvider ssl(ASYNC, OK);
20077 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20078
20079 // Log start time
20080 base::TimeTicks start_time = base::TimeTicks::Now();
20081
20082 TestCompletionCallback callback;
20083 auto session = CreateSession(&session_deps_);
20084 auto trans =
20085 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20086 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20087 EXPECT_THAT(callback.GetResult(rv), IsOk());
20088
20089 const HttpResponseInfo* response = trans->GetResponseInfo();
20090 ASSERT_TRUE(response);
20091
20092 EXPECT_TRUE(response->headers);
20093 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20094
20095 std::string response_data;
20096 rv = ReadTransaction(trans.get(), &response_data);
20097 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
20098
20099 trans.reset();
20100
20101 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20102
20103 CheckReport(0 /* index */, 200 /* status_code */,
20104 ERR_CONTENT_LENGTH_MISMATCH);
20105 const NetworkErrorLoggingService::RequestDetails& error =
20106 network_error_logging_service()->errors()[0];
20107 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
20108}
20109
20110// Same as above except the final read is ASYNC.
20111TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20112 CreateReportReadBodyErrorAsync) {
20113 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5320114 MockWrite data_writes[] = {
20115 MockWrite("GET / HTTP/1.1\r\n"
20116 "Host: www.example.org\r\n"
20117 "Connection: keep-alive\r\n"),
20118 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20119 };
Lily Chend3930e72019-03-01 19:31:1120120 MockRead data_reads[] = {
20121 MockRead("HTTP/1.0 200 OK\r\n"),
20122 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
20123 MockRead("hello world"),
20124 MockRead(ASYNC, OK),
20125 };
Lily Chenfec60d92019-01-24 01:16:4220126
20127 StaticSocketDataProvider reads(data_reads, data_writes);
20128 session_deps_.socket_factory->AddSocketDataProvider(&reads);
20129
20130 SSLSocketDataProvider ssl(ASYNC, OK);
20131 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20132
20133 // Log start time
20134 base::TimeTicks start_time = base::TimeTicks::Now();
20135
20136 TestCompletionCallback callback;
20137 auto session = CreateSession(&session_deps_);
20138 auto trans =
20139 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20140 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20141 EXPECT_THAT(callback.GetResult(rv), IsOk());
20142
20143 const HttpResponseInfo* response = trans->GetResponseInfo();
20144 ASSERT_TRUE(response);
20145
20146 EXPECT_TRUE(response->headers);
20147 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20148
20149 std::string response_data;
20150 rv = ReadTransaction(trans.get(), &response_data);
20151 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
20152
20153 trans.reset();
20154
20155 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20156
20157 CheckReport(0 /* index */, 200 /* status_code */,
20158 ERR_CONTENT_LENGTH_MISMATCH);
20159 const NetworkErrorLoggingService::RequestDetails& error =
20160 network_error_logging_service()->errors()[0];
20161 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
20162}
20163
20164TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20165 CreateReportRestartWithAuth) {
20166 std::string extra_header_string = extra_headers_.ToString();
20167 static const base::TimeDelta kSleepDuration =
20168 base::TimeDelta::FromMilliseconds(10);
20169
20170 MockWrite data_writes1[] = {
20171 MockWrite("GET / HTTP/1.1\r\n"
20172 "Host: www.example.org\r\n"
20173 "Connection: keep-alive\r\n"),
20174 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20175 };
20176
20177 MockRead data_reads1[] = {
20178 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
20179 // Give a couple authenticate options (only the middle one is actually
20180 // supported).
20181 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
20182 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20183 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
20184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20185 // Large content-length -- won't matter, as connection will be reset.
20186 MockRead("Content-Length: 10000\r\n\r\n"),
20187 MockRead(SYNCHRONOUS, ERR_FAILED),
20188 };
20189
20190 // After calling trans->RestartWithAuth(), this is the request we should
20191 // be issuing -- the final header line contains the credentials.
20192 MockWrite data_writes2[] = {
20193 MockWrite("GET / HTTP/1.1\r\n"
20194 "Host: www.example.org\r\n"
20195 "Connection: keep-alive\r\n"
20196 "Authorization: Basic Zm9vOmJhcg==\r\n"),
20197 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20198 };
20199
20200 // Lastly, the server responds with the actual content.
20201 MockRead data_reads2[] = {
20202 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20203 MockRead("hello world"),
20204 MockRead(SYNCHRONOUS, OK),
20205 };
20206
20207 StaticSocketDataProvider data1(data_reads1, data_writes1);
20208 StaticSocketDataProvider data2(data_reads2, data_writes2);
20209 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20210 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20211
20212 SSLSocketDataProvider ssl1(ASYNC, OK);
20213 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20214 SSLSocketDataProvider ssl2(ASYNC, OK);
20215 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20216
20217 base::TimeTicks start_time = base::TimeTicks::Now();
20218 base::TimeTicks restart_time;
20219
20220 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20221 auto trans =
20222 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20223
20224 TestCompletionCallback callback1;
20225
20226 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
20227 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20228
20229 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20230
20231 TestCompletionCallback callback2;
20232
20233 // Wait 10 ms then restart with auth
20234 FastForwardBy(kSleepDuration);
20235 restart_time = base::TimeTicks::Now();
20236 rv =
20237 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20238 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20239
20240 std::string response_data;
20241 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20242 EXPECT_EQ("hello world", response_data);
20243
20244 trans.reset();
20245
20246 // One 401 report for the auth challenge, then a 200 report for the successful
20247 // retry. Note that we don't report the error draining the body, as the first
20248 // request already generated a report for the auth challenge.
20249 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20250
20251 // Check error report contents
20252 CheckReport(0 /* index */, 401 /* status_code */, OK);
20253 CheckReport(1 /* index */, 200 /* status_code */, OK);
20254
20255 const NetworkErrorLoggingService::RequestDetails& error1 =
20256 network_error_logging_service()->errors()[0];
20257 const NetworkErrorLoggingService::RequestDetails& error2 =
20258 network_error_logging_service()->errors()[1];
20259
20260 // Sanity-check elapsed time values
20261 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20262 // Check that the start time is refreshed when restarting with auth.
20263 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20264}
20265
20266// Same as above, except draining the body before restarting fails
20267// asynchronously.
20268TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20269 CreateReportRestartWithAuthAsync) {
20270 std::string extra_header_string = extra_headers_.ToString();
20271 static const base::TimeDelta kSleepDuration =
20272 base::TimeDelta::FromMilliseconds(10);
20273
20274 MockWrite data_writes1[] = {
20275 MockWrite("GET / HTTP/1.1\r\n"
20276 "Host: www.example.org\r\n"
20277 "Connection: keep-alive\r\n"),
20278 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20279 };
20280
20281 MockRead data_reads1[] = {
20282 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
20283 // Give a couple authenticate options (only the middle one is actually
20284 // supported).
20285 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
20286 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20287 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
20288 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20289 // Large content-length -- won't matter, as connection will be reset.
20290 MockRead("Content-Length: 10000\r\n\r\n"),
20291 MockRead(ASYNC, ERR_FAILED),
20292 };
20293
20294 // After calling trans->RestartWithAuth(), this is the request we should
20295 // be issuing -- the final header line contains the credentials.
20296 MockWrite data_writes2[] = {
20297 MockWrite("GET / HTTP/1.1\r\n"
20298 "Host: www.example.org\r\n"
20299 "Connection: keep-alive\r\n"
20300 "Authorization: Basic Zm9vOmJhcg==\r\n"),
20301 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20302 };
20303
20304 // Lastly, the server responds with the actual content.
20305 MockRead data_reads2[] = {
20306 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20307 MockRead("hello world"),
20308 MockRead(SYNCHRONOUS, OK),
20309 };
20310
20311 StaticSocketDataProvider data1(data_reads1, data_writes1);
20312 StaticSocketDataProvider data2(data_reads2, data_writes2);
20313 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20314 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20315
20316 SSLSocketDataProvider ssl1(ASYNC, OK);
20317 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20318 SSLSocketDataProvider ssl2(ASYNC, OK);
20319 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20320
20321 base::TimeTicks start_time = base::TimeTicks::Now();
20322 base::TimeTicks restart_time;
20323
20324 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20325 auto trans =
20326 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20327
20328 TestCompletionCallback callback1;
20329
20330 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
20331 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20332
20333 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20334
20335 TestCompletionCallback callback2;
20336
20337 // Wait 10 ms then restart with auth
20338 FastForwardBy(kSleepDuration);
20339 restart_time = base::TimeTicks::Now();
20340 rv =
20341 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20342 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20343
20344 std::string response_data;
20345 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20346 EXPECT_EQ("hello world", response_data);
20347
20348 trans.reset();
20349
20350 // One 401 report for the auth challenge, then a 200 report for the successful
20351 // retry. Note that we don't report the error draining the body, as the first
20352 // request already generated a report for the auth challenge.
20353 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
20354
20355 // Check error report contents
20356 CheckReport(0 /* index */, 401 /* status_code */, OK);
20357 CheckReport(1 /* index */, 200 /* status_code */, OK);
20358
20359 const NetworkErrorLoggingService::RequestDetails& error1 =
20360 network_error_logging_service()->errors()[0];
20361 const NetworkErrorLoggingService::RequestDetails& error2 =
20362 network_error_logging_service()->errors()[1];
20363
20364 // Sanity-check elapsed time values
20365 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
20366 // Check that the start time is refreshed when restarting with auth.
20367 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
20368}
20369
20370TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20371 CreateReportRetryKeepAliveConnectionReset) {
20372 std::string extra_header_string = extra_headers_.ToString();
20373 MockWrite data_writes1[] = {
20374 MockWrite("GET / HTTP/1.1\r\n"
20375 "Host: www.example.org\r\n"
20376 "Connection: keep-alive\r\n"),
20377 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20378 MockWrite("GET / HTTP/1.1\r\n"
20379 "Host: www.example.org\r\n"
20380 "Connection: keep-alive\r\n"),
20381 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20382 };
20383
20384 MockRead data_reads1[] = {
20385 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20386 MockRead("hello"),
20387 // Connection is reset
20388 MockRead(ASYNC, ERR_CONNECTION_RESET),
20389 };
20390
20391 // Successful retry
20392 MockRead data_reads2[] = {
20393 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20394 MockRead("world"),
20395 MockRead(ASYNC, OK),
20396 };
20397
20398 StaticSocketDataProvider data1(data_reads1, data_writes1);
20399 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20400 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20401 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20402
20403 SSLSocketDataProvider ssl1(ASYNC, OK);
20404 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20405 SSLSocketDataProvider ssl2(ASYNC, OK);
20406 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20407
20408 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20409 auto trans1 =
20410 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20411
20412 TestCompletionCallback callback1;
20413
20414 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20415 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20416
20417 std::string response_data;
20418 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20419 EXPECT_EQ("hello", response_data);
20420
20421 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20422
20423 auto trans2 =
20424 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20425
20426 TestCompletionCallback callback2;
20427
20428 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20429 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20430
20431 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20432 EXPECT_EQ("world", response_data);
20433
20434 trans1.reset();
20435 trans2.reset();
20436
20437 // One OK report from first request, then a ERR_CONNECTION_RESET report from
20438 // the second request, then an OK report from the successful retry.
20439 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20440
20441 // Check error report contents
20442 CheckReport(0 /* index */, 200 /* status_code */, OK);
20443 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
20444 CheckReport(2 /* index */, 200 /* status_code */, OK);
20445}
20446
20447TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20448 CreateReportRetryKeepAlive408) {
20449 std::string extra_header_string = extra_headers_.ToString();
20450 MockWrite data_writes1[] = {
20451 MockWrite("GET / HTTP/1.1\r\n"
20452 "Host: www.example.org\r\n"
20453 "Connection: keep-alive\r\n"),
20454 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20455 MockWrite("GET / HTTP/1.1\r\n"
20456 "Host: www.example.org\r\n"
20457 "Connection: keep-alive\r\n"),
20458 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20459 };
20460
20461 MockRead data_reads1[] = {
20462 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20463 MockRead("hello"),
20464 // 408 Request Timeout
20465 MockRead(SYNCHRONOUS,
20466 "HTTP/1.1 408 Request Timeout\r\n"
20467 "Connection: Keep-Alive\r\n"
20468 "Content-Length: 6\r\n\r\n"
20469 "Pickle"),
20470 };
20471
20472 // Successful retry
20473 MockRead data_reads2[] = {
20474 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
20475 MockRead("world"),
20476 MockRead(ASYNC, OK),
20477 };
20478
20479 StaticSocketDataProvider data1(data_reads1, data_writes1);
20480 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
20481 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20482 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20483
20484 SSLSocketDataProvider ssl1(ASYNC, OK);
20485 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20486 SSLSocketDataProvider ssl2(ASYNC, OK);
20487 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20488
20489 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20490 auto trans1 =
20491 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20492
20493 TestCompletionCallback callback1;
20494
20495 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
20496 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20497
20498 std::string response_data;
20499 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20500 EXPECT_EQ("hello", response_data);
20501
20502 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20503
20504 auto trans2 =
20505 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20506
20507 TestCompletionCallback callback2;
20508
20509 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
20510 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20511
20512 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20513 EXPECT_EQ("world", response_data);
20514
20515 trans1.reset();
20516 trans2.reset();
20517
20518 // One 200 report from first request, then a 408 report from
20519 // the second request, then a 200 report from the successful retry.
20520 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20521
20522 // Check error report contents
20523 CheckReport(0 /* index */, 200 /* status_code */, OK);
20524 CheckReport(1 /* index */, 408 /* status_code */, OK);
20525 CheckReport(2 /* index */, 200 /* status_code */, OK);
20526}
20527
20528TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20529 CreateReportRetry421WithoutConnectionPooling) {
20530 // Two hosts resolve to the same IP address.
20531 const std::string ip_addr = "1.2.3.4";
20532 IPAddress ip;
20533 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20534 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20535
20536 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20537 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20538 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20539
20540 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20541
20542 // Two requests on the first connection.
20543 spdy::SpdySerializedFrame req1(
20544 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20545 spdy_util_.UpdateWithStreamDestruction(1);
20546 spdy::SpdySerializedFrame req2(
20547 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20548 spdy::SpdySerializedFrame rst(
20549 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20550 MockWrite writes1[] = {
20551 CreateMockWrite(req1, 0),
20552 CreateMockWrite(req2, 3),
20553 CreateMockWrite(rst, 6),
20554 };
20555
20556 // The first one succeeds, the second gets error 421 Misdirected Request.
20557 spdy::SpdySerializedFrame resp1(
20558 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20559 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
20560 spdy::SpdyHeaderBlock response_headers;
20561 response_headers[spdy::kHttp2StatusHeader] = "421";
20562 spdy::SpdySerializedFrame resp2(
20563 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
20564 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20565 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20566
20567 MockConnect connect1(ASYNC, OK, peer_addr);
20568 SequencedSocketData data1(connect1, reads1, writes1);
20569 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20570
20571 AddSSLSocketData();
20572
20573 // Retry the second request on a second connection.
20574 SpdyTestUtil spdy_util2;
20575 spdy::SpdySerializedFrame req3(
20576 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20577 MockWrite writes2[] = {
20578 CreateMockWrite(req3, 0),
20579 };
20580
20581 spdy::SpdySerializedFrame resp3(
20582 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20583 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20584 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20585 MockRead(ASYNC, 0, 3)};
20586
20587 MockConnect connect2(ASYNC, OK, peer_addr);
20588 SequencedSocketData data2(connect2, reads2, writes2);
20589 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20590
20591 AddSSLSocketData();
20592
20593 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3320594 int rv = session_deps_.host_resolver->LoadIntoCache(
Matt Menkecd439232019-11-05 15:15:3320595 HostPortPair("mail.example.com", 443), NetworkIsolationKey(),
20596 base::nullopt);
Eric Orthf4db66a2019-02-19 21:35:3320597 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4220598
20599 HttpRequestInfo request1;
20600 request1.method = "GET";
20601 request1.url = GURL("https://www.example.org/");
20602 request1.load_flags = 0;
20603 request1.traffic_annotation =
20604 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20605 auto trans1 =
20606 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20607
Eric Orthf4db66a2019-02-19 21:35:3320608 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220609 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20610 EXPECT_THAT(callback.GetResult(rv), IsOk());
20611
20612 const HttpResponseInfo* response = trans1->GetResponseInfo();
20613 ASSERT_TRUE(response);
20614 ASSERT_TRUE(response->headers);
20615 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20616 EXPECT_TRUE(response->was_fetched_via_spdy);
20617 EXPECT_TRUE(response->was_alpn_negotiated);
20618 std::string response_data;
20619 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
20620 EXPECT_EQ("hello!", response_data);
20621
20622 trans1.reset();
20623
20624 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20625
20626 HttpRequestInfo request2;
20627 request2.method = "GET";
20628 request2.url = GURL("https://mail.example.org/");
20629 request2.load_flags = 0;
20630 request2.traffic_annotation =
20631 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20632 auto trans2 =
20633 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20634
Matt Muellerd9342e3a2019-11-26 01:41:1420635 RecordingBoundTestNetLog log;
Lily Chenfec60d92019-01-24 01:16:4220636 rv = trans2->Start(&request2, callback.callback(), log.bound());
20637 EXPECT_THAT(callback.GetResult(rv), IsOk());
20638
20639 response = trans2->GetResponseInfo();
20640 ASSERT_TRUE(response);
20641 ASSERT_TRUE(response->headers);
20642 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20643 EXPECT_TRUE(response->was_fetched_via_spdy);
20644 EXPECT_TRUE(response->was_alpn_negotiated);
20645 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
20646 EXPECT_EQ("hello!", response_data);
20647
20648 trans2.reset();
20649
20650 // One 200 report from the first request, then a 421 report from the
20651 // second request, then a 200 report from the successful retry.
20652 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
20653
20654 // Check error report contents
20655 const NetworkErrorLoggingService::RequestDetails& error1 =
20656 network_error_logging_service()->errors()[0];
20657 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
20658 EXPECT_TRUE(error1.referrer.is_empty());
20659 EXPECT_EQ("", error1.user_agent);
20660 EXPECT_EQ(ip, error1.server_ip);
20661 EXPECT_EQ("h2", error1.protocol);
20662 EXPECT_EQ("GET", error1.method);
20663 EXPECT_EQ(200, error1.status_code);
20664 EXPECT_EQ(OK, error1.type);
20665 EXPECT_EQ(0, error1.reporting_upload_depth);
20666
20667 const NetworkErrorLoggingService::RequestDetails& error2 =
20668 network_error_logging_service()->errors()[1];
20669 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
20670 EXPECT_TRUE(error2.referrer.is_empty());
20671 EXPECT_EQ("", error2.user_agent);
20672 EXPECT_EQ(ip, error2.server_ip);
20673 EXPECT_EQ("h2", error2.protocol);
20674 EXPECT_EQ("GET", error2.method);
20675 EXPECT_EQ(421, error2.status_code);
20676 EXPECT_EQ(OK, error2.type);
20677 EXPECT_EQ(0, error2.reporting_upload_depth);
20678
20679 const NetworkErrorLoggingService::RequestDetails& error3 =
20680 network_error_logging_service()->errors()[2];
20681 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
20682 EXPECT_TRUE(error3.referrer.is_empty());
20683 EXPECT_EQ("", error3.user_agent);
20684 EXPECT_EQ(ip, error3.server_ip);
20685 EXPECT_EQ("h2", error3.protocol);
20686 EXPECT_EQ("GET", error3.method);
20687 EXPECT_EQ(200, error3.status_code);
20688 EXPECT_EQ(OK, error3.type);
20689 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3620690}
20691
Lily Chend3930e72019-03-01 19:31:1120692TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20693 CreateReportCancelAfterStart) {
20694 StaticSocketDataProvider data;
20695 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
20696 session_deps_.socket_factory->AddSocketDataProvider(&data);
20697
20698 TestCompletionCallback callback;
20699 auto session = CreateSession(&session_deps_);
20700 auto trans =
20701 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20702 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20703 EXPECT_EQ(rv, ERR_IO_PENDING);
20704
20705 // Cancel after start.
20706 trans.reset();
20707
20708 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20709 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
20710 IPAddress() /* server_ip */);
20711}
20712
20713TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20714 CreateReportCancelBeforeReadingBody) {
20715 std::string extra_header_string = extra_headers_.ToString();
20716 MockWrite data_writes[] = {
20717 MockWrite("GET / HTTP/1.1\r\n"
20718 "Host: www.example.org\r\n"
20719 "Connection: keep-alive\r\n"),
20720 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20721 };
20722 MockRead data_reads[] = {
20723 MockRead("HTTP/1.0 200 OK\r\n"),
20724 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
20725 };
20726
20727 StaticSocketDataProvider data(data_reads, data_writes);
20728 session_deps_.socket_factory->AddSocketDataProvider(&data);
20729
20730 SSLSocketDataProvider ssl(ASYNC, OK);
20731 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20732
20733 TestCompletionCallback callback;
20734 auto session = CreateSession(&session_deps_);
20735 auto trans =
20736 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20737 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20738 EXPECT_THAT(callback.GetResult(rv), IsOk());
20739
20740 const HttpResponseInfo* response = trans->GetResponseInfo();
20741 ASSERT_TRUE(response);
20742
20743 EXPECT_TRUE(response->headers);
20744 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
20745
20746 // Cancel before reading the body.
20747 trans.reset();
20748
20749 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
20750 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
20751}
20752
Lily Chen00196ab62018-12-04 19:52:2920753TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
Lily Chen00196ab62018-12-04 19:52:2920754 RequestPolicy();
20755 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20756 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20757
20758 // Make HTTP request
20759 std::string extra_header_string = extra_headers_.ToString();
20760 MockRead data_reads[] = {
20761 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
20762 MockRead("hello world"),
20763 MockRead(SYNCHRONOUS, OK),
20764 };
20765 MockWrite data_writes[] = {
20766 MockWrite("GET / HTTP/1.1\r\n"
20767 "Host: www.example.org\r\n"
20768 "Connection: keep-alive\r\n"),
20769 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
20770 };
20771
Lily Chend3930e72019-03-01 19:31:1120772 StaticSocketDataProvider data(data_reads, data_writes);
20773 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2920774
Lily Chenfec60d92019-01-24 01:16:4220775 // Insecure url
20776 url_ = "http://www.example.org/";
20777 request_.url = GURL(url_);
20778
Lily Chen00196ab62018-12-04 19:52:2920779 TestCompletionCallback callback;
20780 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4220781 auto trans =
20782 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20783 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20784 EXPECT_THAT(callback.GetResult(rv), IsOk());
20785
20786 std::string response_data;
20787 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20788 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2920789
20790 // Insecure request does not generate a report
Lily Chen00196ab62018-12-04 19:52:2920791 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20792}
20793
20794TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20795 DontCreateReportHttpError) {
Lily Chen00196ab62018-12-04 19:52:2920796 RequestPolicy();
20797 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
20798 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20799
20800 // Make HTTP request that fails
20801 MockRead data_reads[] = {
20802 MockRead("hello world"),
20803 MockRead(SYNCHRONOUS, OK),
20804 };
20805
20806 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
20807 session_deps_.socket_factory->AddSocketDataProvider(&data);
20808
Lily Chenfec60d92019-01-24 01:16:4220809 url_ = "http://www.originwithoutpolicy.com:2000/";
20810 request_.url = GURL(url_);
20811
Lily Chen00196ab62018-12-04 19:52:2920812 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20813
Lily Chen00196ab62018-12-04 19:52:2920814 auto trans =
20815 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2920816 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4220817 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2920818 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
20819
20820 // Insecure request does not generate a report, regardless of existence of a
20821 // policy for the origin.
Lily Chen00196ab62018-12-04 19:52:2920822 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
20823}
20824
Lily Chen90ae93cc2019-02-14 01:15:3920825// Don't report on proxy auth challenges, don't report if connecting through a
20826// proxy.
20827TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
20828 HttpRequestInfo request;
20829 request.method = "GET";
20830 request.url = GURL("https://www.example.org/");
20831 request.traffic_annotation =
20832 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20833
20834 // Configure against proxy server "myproxy:70".
20835 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5620836 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Lily Chen90ae93cc2019-02-14 01:15:3920837 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20838 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20839
20840 // Since we have proxy, should try to establish tunnel.
20841 MockWrite data_writes1[] = {
20842 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20843 "Host: www.example.org:443\r\n"
20844 "Proxy-Connection: keep-alive\r\n\r\n"),
20845 };
20846
20847 // The proxy responds to the connect with a 407, using a non-persistent
20848 // connection.
20849 MockRead data_reads1[] = {
20850 // No credentials.
20851 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
20852 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
20853 MockRead("Proxy-Connection: close\r\n\r\n"),
20854 };
20855
20856 MockWrite data_writes2[] = {
20857 // After calling trans->RestartWithAuth(), this is the request we should
20858 // be issuing -- the final header line contains the credentials.
20859 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
20860 "Host: www.example.org:443\r\n"
20861 "Proxy-Connection: keep-alive\r\n"
20862 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
20863
20864 MockWrite("GET / HTTP/1.1\r\n"
20865 "Host: www.example.org\r\n"
20866 "Connection: keep-alive\r\n\r\n"),
20867 };
20868
20869 MockRead data_reads2[] = {
20870 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
20871
20872 MockRead("HTTP/1.1 200 OK\r\n"),
20873 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
20874 MockRead("Content-Length: 5\r\n\r\n"),
20875 MockRead(SYNCHRONOUS, "hello"),
20876 };
20877
20878 StaticSocketDataProvider data1(data_reads1, data_writes1);
20879 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20880 StaticSocketDataProvider data2(data_reads2, data_writes2);
20881 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20882 SSLSocketDataProvider ssl(ASYNC, OK);
20883 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20884
20885 TestCompletionCallback callback1;
20886
20887 auto trans =
20888 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20889
20890 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
20891 EXPECT_THAT(callback1.GetResult(rv), IsOk());
20892
20893 const HttpResponseInfo* response = trans->GetResponseInfo();
20894 EXPECT_EQ(407, response->headers->response_code());
20895
20896 std::string response_data;
20897 rv = ReadTransaction(trans.get(), &response_data);
20898 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
20899
20900 // No NEL report is generated for the 407.
20901 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20902
20903 TestCompletionCallback callback2;
20904
20905 rv =
20906 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
20907 EXPECT_THAT(callback2.GetResult(rv), IsOk());
20908
20909 response = trans->GetResponseInfo();
20910 EXPECT_EQ(200, response->headers->response_code());
20911
20912 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20913 EXPECT_EQ("hello", response_data);
20914
20915 trans.reset();
20916
20917 // No NEL report is generated because we are behind a proxy.
20918 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
20919}
20920
Douglas Creageref5eecdc2018-11-09 20:50:3620921TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
20922 ReportContainsUploadDepth) {
20923 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4220924 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3620925 RequestPolicy();
20926 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220927 const NetworkErrorLoggingService::RequestDetails& error =
20928 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3620929 EXPECT_EQ(7, error.reporting_upload_depth);
20930}
20931
Lily Chenfec60d92019-01-24 01:16:4220932TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
20933 std::string extra_header_string = extra_headers_.ToString();
20934 static const base::TimeDelta kSleepDuration =
20935 base::TimeDelta::FromMilliseconds(10);
20936
20937 std::vector<MockWrite> data_writes = {
20938 MockWrite(ASYNC, 0,
20939 "GET / HTTP/1.1\r\n"
20940 "Host: www.example.org\r\n"
20941 "Connection: keep-alive\r\n"),
20942 MockWrite(ASYNC, 1, extra_header_string.data()),
20943 };
20944
20945 std::vector<MockRead> data_reads = {
20946 // Write one byte of the status line, followed by a pause.
20947 MockRead(ASYNC, 2, "H"),
20948 MockRead(ASYNC, ERR_IO_PENDING, 3),
20949 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
20950 MockRead(ASYNC, 5, "hello world"),
20951 MockRead(SYNCHRONOUS, OK, 6),
20952 };
20953
20954 SequencedSocketData data(data_reads, data_writes);
20955 session_deps_.socket_factory->AddSocketDataProvider(&data);
20956
20957 SSLSocketDataProvider ssl(ASYNC, OK);
20958 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20959
20960 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20961
20962 auto trans =
20963 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20964
20965 TestCompletionCallback callback;
20966
20967 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
20968 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20969
20970 data.RunUntilPaused();
20971 ASSERT_TRUE(data.IsPaused());
20972 FastForwardBy(kSleepDuration);
20973 data.Resume();
20974
20975 EXPECT_THAT(callback.GetResult(rv), IsOk());
20976
20977 std::string response_data;
20978 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
20979 EXPECT_EQ("hello world", response_data);
20980
20981 trans.reset();
20982
Douglas Creageref5eecdc2018-11-09 20:50:3620983 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4220984
20985 CheckReport(0 /* index */, 200 /* status_code */, OK);
20986
20987 const NetworkErrorLoggingService::RequestDetails& error =
20988 network_error_logging_service()->errors()[0];
20989
20990 // Sanity-check elapsed time in error report
20991 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3620992}
Lily Chenfec60d92019-01-24 01:16:4220993
Douglas Creager3cb042052018-11-06 23:08:5220994#endif // BUILDFLAG(ENABLE_REPORTING)
20995
Batalov Vladislava4e97a502019-04-11 15:35:2320996TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
20997 HttpRequestInfo request;
20998 request.method = "GET";
20999 request.url = GURL("http://example.org/");
21000
21001 request.load_flags = LOAD_ONLY_FROM_CACHE;
21002
21003 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21004 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21005 TestCompletionCallback callback1;
21006 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
21007
21008 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
21009}
21010
Steven Valdez1c1859172019-04-10 15:33:2821011TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
David Benjaminbae08ba2019-10-18 21:06:1521012 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821013 HttpRequestInfo request;
21014 request.method = "GET";
21015 request.url = GURL("https://www.example.org/");
21016 request.traffic_annotation =
21017 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21018
21019 MockWrite data_writes[] = {
21020 MockWrite("GET / HTTP/1.1\r\n"
21021 "Host: www.example.org\r\n"
21022 "Connection: keep-alive\r\n\r\n"),
21023 };
21024
Steven Valdez1c1859172019-04-10 15:33:2821025 MockRead data_reads[] = {
21026 MockRead("HTTP/1.1 200 OK\r\n"),
21027 MockRead("Content-Length: 1\r\n\r\n"),
21028 MockRead(SYNCHRONOUS, "1"),
21029 };
21030
21031 StaticSocketDataProvider data(data_reads, data_writes);
21032 session_deps_.socket_factory->AddSocketDataProvider(&data);
21033 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521034 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821035 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521036 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821037 session_deps_.enable_early_data = true;
21038 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21039
21040 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21041
21042 TestCompletionCallback callback;
21043 auto trans =
21044 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21045
David Benjaminbae08ba2019-10-18 21:06:1521046 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821047 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21048 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21049
21050 rv = callback.WaitForResult();
21051 EXPECT_THAT(rv, IsOk());
21052
21053 const HttpResponseInfo* response = trans->GetResponseInfo();
21054 ASSERT_TRUE(response);
21055 ASSERT_TRUE(response->headers);
21056 EXPECT_EQ(200, response->headers->response_code());
21057 EXPECT_EQ(1, response->headers->GetContentLength());
21058
21059 // Check that ConfirmHandshake wasn't called.
21060 ASSERT_FALSE(ssl.ConfirmDataConsumed());
21061 ASSERT_TRUE(ssl.WriteBeforeConfirm());
21062
David Benjaminbae08ba2019-10-18 21:06:1521063 // The handshake time should include the time it took to run Connect(), but
21064 // not ConfirmHandshake().
21065 LoadTimingInfo load_timing_info;
21066 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21067 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21068 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21069 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
21070 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
21071
Steven Valdez1c1859172019-04-10 15:33:2821072 trans.reset();
21073
Matt Menke433de6d2020-03-04 00:24:1121074 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821075}
21076
21077TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1521078 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821079 HttpRequestInfo request;
21080 request.method = "POST";
21081 request.url = GURL("https://www.example.org/");
21082 request.traffic_annotation =
21083 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21084
21085 MockWrite data_writes[] = {
21086 MockWrite(SYNCHRONOUS,
21087 "POST / HTTP/1.1\r\n"
21088 "Host: www.example.org\r\n"
21089 "Connection: keep-alive\r\n"
21090 "Content-Length: 0\r\n\r\n"),
21091 };
21092
Steven Valdez1c1859172019-04-10 15:33:2821093 MockRead data_reads[] = {
21094 MockRead("HTTP/1.1 200 OK\r\n"),
21095 MockRead("Content-Length: 1\r\n\r\n"),
21096 MockRead(SYNCHRONOUS, "1"),
21097 };
21098
21099 StaticSocketDataProvider data(data_reads, data_writes);
21100 session_deps_.socket_factory->AddSocketDataProvider(&data);
21101 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521102 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821103 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521104 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821105 session_deps_.enable_early_data = true;
21106 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21107
21108 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21109
21110 TestCompletionCallback callback;
21111 auto trans =
21112 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21113
David Benjaminbae08ba2019-10-18 21:06:1521114 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821115 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21116 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21117
21118 rv = callback.WaitForResult();
21119 EXPECT_THAT(rv, IsOk());
21120
21121 const HttpResponseInfo* response = trans->GetResponseInfo();
21122 ASSERT_TRUE(response);
21123 ASSERT_TRUE(response->headers);
21124 EXPECT_EQ(200, response->headers->response_code());
21125 EXPECT_EQ(1, response->headers->GetContentLength());
21126
21127 // Check that the Write didn't get called before ConfirmHandshake completed.
21128 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21129
David Benjaminbae08ba2019-10-18 21:06:1521130 // The handshake time should include the time it took to run Connect(), but
21131 // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
21132 // assume the connection did not negotiate 0-RTT or the handshake was already
21133 // confirmed.
21134 LoadTimingInfo load_timing_info;
21135 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21136 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21137 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21138 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
21139 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
21140
Steven Valdez1c1859172019-04-10 15:33:2821141 trans.reset();
21142
Matt Menke433de6d2020-03-04 00:24:1121143 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821144}
21145
21146TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
21147 HttpRequestInfo request;
21148 request.method = "POST";
21149 request.url = GURL("https://www.example.org/");
21150 request.traffic_annotation =
21151 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21152
21153 MockWrite data_writes[] = {
21154 MockWrite(ASYNC,
21155 "POST / HTTP/1.1\r\n"
21156 "Host: www.example.org\r\n"
21157 "Connection: keep-alive\r\n"
21158 "Content-Length: 0\r\n\r\n"),
21159 };
21160
Steven Valdez1c1859172019-04-10 15:33:2821161 MockRead data_reads[] = {
21162 MockRead("HTTP/1.1 200 OK\r\n"),
21163 MockRead("Content-Length: 1\r\n\r\n"),
21164 MockRead(SYNCHRONOUS, "1"),
21165 };
21166
21167 StaticSocketDataProvider data(data_reads, data_writes);
21168 session_deps_.socket_factory->AddSocketDataProvider(&data);
21169 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21170 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
21171 session_deps_.enable_early_data = true;
21172 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21173
21174 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21175
21176 TestCompletionCallback callback;
21177 auto trans =
21178 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21179
21180 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21181 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21182
21183 rv = callback.WaitForResult();
21184 EXPECT_THAT(rv, IsOk());
21185
21186 const HttpResponseInfo* response = trans->GetResponseInfo();
21187 ASSERT_TRUE(response);
21188 ASSERT_TRUE(response->headers);
21189 EXPECT_EQ(200, response->headers->response_code());
21190 EXPECT_EQ(1, response->headers->GetContentLength());
21191
21192 // Check that the Write didn't get called before ConfirmHandshake completed.
21193 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21194
21195 trans.reset();
21196
Matt Menke433de6d2020-03-04 00:24:1121197 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821198}
21199
21200TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
David Benjaminbae08ba2019-10-18 21:06:1521201 static const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
Steven Valdez1c1859172019-04-10 15:33:2821202 HttpRequestInfo request;
21203 request.method = "POST";
21204 request.url = GURL("https://www.example.org/");
21205 request.traffic_annotation =
21206 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21207
21208 MockWrite data_writes[] = {
21209 MockWrite(SYNCHRONOUS,
21210 "POST / HTTP/1.1\r\n"
21211 "Host: www.example.org\r\n"
21212 "Connection: keep-alive\r\n"
21213 "Content-Length: 0\r\n\r\n"),
21214 };
21215
Steven Valdez1c1859172019-04-10 15:33:2821216 MockRead data_reads[] = {
21217 MockRead("HTTP/1.1 200 OK\r\n"),
21218 MockRead("Content-Length: 1\r\n\r\n"),
21219 MockRead(SYNCHRONOUS, "1"),
21220 };
21221
21222 StaticSocketDataProvider data(data_reads, data_writes);
21223 session_deps_.socket_factory->AddSocketDataProvider(&data);
21224 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
David Benjaminbae08ba2019-10-18 21:06:1521225 ssl.connect_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821226 ssl.confirm = MockConfirm(ASYNC, OK);
David Benjaminbae08ba2019-10-18 21:06:1521227 ssl.confirm_callback = FastForwardByCallback(kDelay);
Steven Valdez1c1859172019-04-10 15:33:2821228 session_deps_.enable_early_data = true;
21229 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21230
21231 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21232
21233 TestCompletionCallback callback;
21234 auto trans =
21235 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21236
David Benjaminbae08ba2019-10-18 21:06:1521237 base::TimeTicks start_time = base::TimeTicks::Now();
Steven Valdez1c1859172019-04-10 15:33:2821238 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21239 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21240
21241 rv = callback.WaitForResult();
21242 EXPECT_THAT(rv, IsOk());
21243
21244 const HttpResponseInfo* response = trans->GetResponseInfo();
21245 ASSERT_TRUE(response);
21246 ASSERT_TRUE(response->headers);
21247 EXPECT_EQ(200, response->headers->response_code());
21248 EXPECT_EQ(1, response->headers->GetContentLength());
21249
21250 // Check that the Write didn't get called before ConfirmHandshake completed.
21251 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21252
David Benjaminbae08ba2019-10-18 21:06:1521253 // The handshake time should include the time it took to run Connect() and
21254 // ConfirmHandshake().
21255 LoadTimingInfo load_timing_info;
21256 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
21257 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
21258 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
21259 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
21260 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
21261 start_time + 2 * kDelay);
21262
Steven Valdez1c1859172019-04-10 15:33:2821263 trans.reset();
21264
Matt Menke433de6d2020-03-04 00:24:1121265 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821266}
21267
21268TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
21269 HttpRequestInfo request;
21270 request.method = "POST";
21271 request.url = GURL("https://www.example.org/");
21272 request.traffic_annotation =
21273 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21274
21275 MockWrite data_writes[] = {
21276 MockWrite(ASYNC,
21277 "POST / HTTP/1.1\r\n"
21278 "Host: www.example.org\r\n"
21279 "Connection: keep-alive\r\n"
21280 "Content-Length: 0\r\n\r\n"),
21281 };
21282
Steven Valdez1c1859172019-04-10 15:33:2821283 MockRead data_reads[] = {
21284 MockRead("HTTP/1.1 200 OK\r\n"),
21285 MockRead("Content-Length: 1\r\n\r\n"),
21286 MockRead(SYNCHRONOUS, "1"),
21287 };
21288
21289 StaticSocketDataProvider data(data_reads, data_writes);
21290 session_deps_.socket_factory->AddSocketDataProvider(&data);
21291 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21292 ssl.confirm = MockConfirm(ASYNC, OK);
21293 session_deps_.enable_early_data = true;
21294 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21295
21296 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21297
21298 TestCompletionCallback callback;
21299 auto trans =
21300 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21301
21302 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21303 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21304
21305 rv = callback.WaitForResult();
21306 EXPECT_THAT(rv, IsOk());
21307
21308 const HttpResponseInfo* response = trans->GetResponseInfo();
21309 ASSERT_TRUE(response);
21310 ASSERT_TRUE(response->headers);
21311 EXPECT_EQ(200, response->headers->response_code());
21312 EXPECT_EQ(1, response->headers->GetContentLength());
21313
21314 // Check that the Write didn't get called before ConfirmHandshake completed.
21315 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21316
21317 trans.reset();
21318
Matt Menke433de6d2020-03-04 00:24:1121319 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821320}
21321
David Benjaminfb976932019-05-15 13:39:1521322// 0-RTT rejects are handled at HttpNetworkTransaction.
21323TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
21324 enum class RejectType {
21325 kRead,
21326 kWrite,
21327 kConfirm,
21328 };
21329
21330 for (RejectType type :
21331 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
21332 SCOPED_TRACE(static_cast<int>(type));
21333 for (Error reject_error :
21334 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
21335 SCOPED_TRACE(reject_error);
21336 session_deps_.socket_factory =
21337 std::make_unique<MockClientSocketFactory>();
21338
21339 HttpRequestInfo request;
21340 request.method = type == RejectType::kConfirm ? "POST" : "GET";
21341 request.url = GURL("https://www.example.org/");
21342 request.traffic_annotation =
21343 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21344
21345 // The first request fails.
21346 std::vector<MockWrite> data1_writes;
21347 std::vector<MockRead> data1_reads;
21348 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
21349 switch (type) {
21350 case RejectType::kRead:
21351 data1_writes.emplace_back(
21352 "GET / HTTP/1.1\r\n"
21353 "Host: www.example.org\r\n"
21354 "Connection: keep-alive\r\n\r\n");
21355 data1_reads.emplace_back(ASYNC, reject_error);
21356 // Cause ConfirmHandshake to hang (it should not be called).
21357 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21358 break;
21359 case RejectType::kWrite:
21360 data1_writes.emplace_back(ASYNC, reject_error);
21361 // Cause ConfirmHandshake to hang (it should not be called).
21362 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
21363 break;
21364 case RejectType::kConfirm:
21365 // The request never gets far enough to read or write.
21366 ssl1.confirm = MockConfirm(ASYNC, reject_error);
21367 break;
21368 }
21369
21370 StaticSocketDataProvider data1(data1_reads, data1_writes);
21371 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21372 session_deps_.enable_early_data = true;
21373 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21374
21375 // The retry succeeds.
21376 //
21377 // TODO(https://crbug.com/950705): If |reject_error| is
21378 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
21379 MockWrite data2_writes[] = {
21380 request.method == "POST"
21381 ? MockWrite("POST / HTTP/1.1\r\n"
21382 "Host: www.example.org\r\n"
21383 "Connection: keep-alive\r\n"
21384 "Content-Length: 0\r\n\r\n")
21385 : MockWrite("GET / HTTP/1.1\r\n"
21386 "Host: www.example.org\r\n"
21387 "Connection: keep-alive\r\n\r\n"),
21388 };
21389
21390 MockRead data2_reads[] = {
21391 MockRead("HTTP/1.1 200 OK\r\n"),
21392 MockRead("Content-Length: 1\r\n\r\n"),
21393 MockRead(SYNCHRONOUS, "1"),
21394 };
21395
21396 StaticSocketDataProvider data2(data2_reads, data2_writes);
21397 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21398 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
21399 ssl2.confirm = MockConfirm(ASYNC, OK);
21400 session_deps_.enable_early_data = true;
21401 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21402
21403 std::unique_ptr<HttpNetworkSession> session(
21404 CreateSession(&session_deps_));
21405
21406 TestCompletionCallback callback;
21407 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21408 session.get());
21409
21410 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21411 NetLogWithSource())),
21412 IsOk());
21413
21414 const HttpResponseInfo* response = trans->GetResponseInfo();
21415 ASSERT_TRUE(response);
21416 ASSERT_TRUE(response->headers);
21417 EXPECT_EQ(200, response->headers->response_code());
21418 EXPECT_EQ(1, response->headers->GetContentLength());
21419 }
21420 }
21421}
21422
Steven Valdez1c1859172019-04-10 15:33:2821423TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
21424 HttpRequestInfo request;
21425 request.method = "POST";
21426 request.url = GURL("https://www.example.org/");
21427 request.traffic_annotation =
21428 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21429
21430 MockWrite data_writes[] = {
21431 MockWrite("POST / HTTP/1.1\r\n"
21432 "Host: www.example.org\r\n"
21433 "Connection: keep-alive\r\n"
21434 "Content-Length: 0\r\n\r\n"),
21435 };
21436
Steven Valdez1c1859172019-04-10 15:33:2821437 MockRead data_reads[] = {
21438 MockRead("HTTP/1.1 200 OK\r\n"),
21439 MockRead("Content-Length: 1\r\n\r\n"),
21440 MockRead(SYNCHRONOUS, "1"),
21441 };
21442
21443 StaticSocketDataProvider data(data_reads, data_writes);
21444 session_deps_.socket_factory->AddSocketDataProvider(&data);
21445 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21446 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
21447 session_deps_.enable_early_data = true;
21448 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21449
21450 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21451
21452 TestCompletionCallback callback;
21453 auto trans =
21454 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21455
21456 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21457 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21458
21459 rv = callback.WaitForResult();
21460 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21461
21462 // Check that the Write didn't get called before ConfirmHandshake completed.
21463 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21464
21465 trans.reset();
21466
Matt Menke433de6d2020-03-04 00:24:1121467 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821468}
21469
21470TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
21471 HttpRequestInfo request;
21472 request.method = "POST";
21473 request.url = GURL("https://www.example.org/");
21474 request.traffic_annotation =
21475 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21476
21477 MockWrite data_writes[] = {
21478 MockWrite("POST / HTTP/1.1\r\n"
21479 "Host: www.example.org\r\n"
21480 "Connection: keep-alive\r\n"
21481 "Content-Length: 0\r\n\r\n"),
21482 };
21483
Steven Valdez1c1859172019-04-10 15:33:2821484 MockRead data_reads[] = {
21485 MockRead("HTTP/1.1 200 OK\r\n"),
21486 MockRead("Content-Length: 1\r\n\r\n"),
21487 MockRead(SYNCHRONOUS, "1"),
21488 };
21489
21490 StaticSocketDataProvider data(data_reads, data_writes);
21491 session_deps_.socket_factory->AddSocketDataProvider(&data);
21492 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
21493 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
21494 session_deps_.enable_early_data = true;
21495 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21496
21497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21498
21499 TestCompletionCallback callback;
21500 auto trans =
21501 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21502
21503 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21504 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21505
21506 rv = callback.WaitForResult();
21507 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
21508
21509 // Check that the Write didn't get called before ConfirmHandshake completed.
21510 ASSERT_FALSE(ssl.WriteBeforeConfirm());
21511
21512 trans.reset();
21513
Matt Menke433de6d2020-03-04 00:24:1121514 session->CloseAllConnections(ERR_FAILED, "Very good reason");
Steven Valdez1c1859172019-04-10 15:33:2821515}
21516
David Benjamin2eb827f2019-04-29 18:31:0421517// Test the proxy and origin server each requesting both TLS client certificates
21518// and HTTP auth. This is a regression test for https://crbug.com/946406.
21519TEST_F(HttpNetworkTransactionTest, AuthEverything) {
21520 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621521 session_deps_.proxy_resolution_service =
21522 ConfiguredProxyResolutionService::CreateFixed(
21523 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421524
21525 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21526 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21527
21528 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21529 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21530 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21531 ASSERT_TRUE(identity_proxy);
21532
21533 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21534 cert_request_info_origin->host_and_port =
21535 HostPortPair("www.example.org", 443);
21536
21537 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21538 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21539 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21540 ASSERT_TRUE(identity_origin);
21541
21542 HttpRequestInfo request;
21543 request.method = "GET";
21544 request.url = GURL("https://www.example.org/");
21545 request.traffic_annotation =
21546 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21547
David Benjamin7ebab032019-04-30 21:51:3021548 // First, the client connects to the proxy, which requests a client
21549 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421550 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21551 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21552 ssl_proxy1.expected_send_client_cert = false;
21553 StaticSocketDataProvider data1;
21554 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021555 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421556
David Benjamin7ebab032019-04-30 21:51:3021557 // The client responds with a certificate on a new connection. The handshake
21558 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421559 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21560 ssl_proxy2.expected_send_client_cert = true;
21561 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021562 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421563 std::vector<MockWrite> mock_writes2;
21564 std::vector<MockRead> mock_reads2;
21565 mock_writes2.emplace_back(
21566 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21567 "Host: www.example.org:443\r\n"
21568 "Proxy-Connection: keep-alive\r\n\r\n");
21569 mock_reads2.emplace_back(
21570 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21571 "Content-Length: 0\r\n"
21572 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021573 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0421574 mock_writes2.emplace_back(
21575 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21576 "Host: www.example.org:443\r\n"
21577 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021578 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421579 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21580 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21581 // The origin requests client certificates.
21582 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21583 ssl_origin2.cert_request_info = cert_request_info_origin.get();
21584 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21585 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21587 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0421588
David Benjamin7ebab032019-04-30 21:51:3021589 // The client responds to the origin client certificate request on a new
21590 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421591 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21592 ssl_proxy3.expected_send_client_cert = true;
21593 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21594 std::vector<MockWrite> mock_writes3;
21595 std::vector<MockRead> mock_reads3;
21596 mock_writes3.emplace_back(
21597 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21598 "Host: www.example.org:443\r\n"
21599 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021600 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421601 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21602 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21603 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
21604 ssl_origin3.expected_send_client_cert = true;
21605 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021606 // The client sends the origin HTTP request, which results in another HTTP
21607 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0421608 mock_writes3.emplace_back(
21609 "GET / HTTP/1.1\r\n"
21610 "Host: www.example.org\r\n"
21611 "Connection: keep-alive\r\n\r\n");
21612 mock_reads3.emplace_back(
21613 "HTTP/1.1 401 Unauthorized\r\n"
21614 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21615 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3021616 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421617 mock_writes3.emplace_back(
21618 "GET / HTTP/1.1\r\n"
21619 "Host: www.example.org\r\n"
21620 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021621 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421622 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21623 mock_reads3.emplace_back(
21624 "HTTP/1.1 200 OK\r\n"
21625 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4121626 // The client makes another request. This should reuse the socket with all
21627 // credentials cached.
21628 mock_writes3.emplace_back(
21629 "GET / HTTP/1.1\r\n"
21630 "Host: www.example.org\r\n"
21631 "Connection: keep-alive\r\n"
21632 // Authenticate as user:pass.
21633 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21634 mock_reads3.emplace_back(
21635 "HTTP/1.1 200 OK\r\n"
21636 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0421637 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21638 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021639 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21640 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421641
21642 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21643
21644 // Start the request.
21645 TestCompletionCallback callback;
21646 auto trans =
21647 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21648 int rv = callback.GetResult(
21649 trans->Start(&request, callback.callback(), NetLogWithSource()));
21650
21651 // Handle the proxy client certificate challenge.
21652 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21653 SSLCertRequestInfo* cert_request_info =
21654 trans->GetResponseInfo()->cert_request_info.get();
21655 ASSERT_TRUE(cert_request_info);
21656 EXPECT_TRUE(cert_request_info->is_proxy);
21657 EXPECT_EQ(cert_request_info->host_and_port,
21658 cert_request_info_proxy->host_and_port);
21659 rv = callback.GetResult(trans->RestartWithCertificate(
21660 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21661 callback.callback()));
21662
21663 // Handle the proxy HTTP auth challenge.
21664 ASSERT_THAT(rv, IsOk());
21665 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21666 EXPECT_TRUE(
21667 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21668 rv = callback.GetResult(trans->RestartWithAuth(
21669 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21670 callback.callback()));
21671
21672 // Handle the origin client certificate challenge.
21673 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21674 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21675 ASSERT_TRUE(cert_request_info);
21676 EXPECT_FALSE(cert_request_info->is_proxy);
21677 EXPECT_EQ(cert_request_info->host_and_port,
21678 cert_request_info_origin->host_and_port);
21679 rv = callback.GetResult(trans->RestartWithCertificate(
21680 identity_origin->certificate(), identity_origin->ssl_private_key(),
21681 callback.callback()));
21682
21683 // Handle the origin HTTP auth challenge.
21684 ASSERT_THAT(rv, IsOk());
21685 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21686 EXPECT_TRUE(
21687 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21688 rv = callback.GetResult(trans->RestartWithAuth(
21689 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21690 callback.callback()));
21691
21692 // The request completes.
21693 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021694 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121695
21696 // Make a second request. This time all credentials are cached.
21697 trans =
21698 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21699 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21700 NetLogWithSource())),
21701 IsOk());
21702 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0421703}
21704
21705// Test the proxy and origin server each requesting both TLS client certificates
21706// and HTTP auth and each HTTP auth closing the connection. This is a regression
21707// test for https://crbug.com/946406.
21708TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
21709 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621710 session_deps_.proxy_resolution_service =
21711 ConfiguredProxyResolutionService::CreateFixed(
21712 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin2eb827f2019-04-29 18:31:0421713
21714 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
21715 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
21716
21717 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
21718 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21719 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21720 ASSERT_TRUE(identity_proxy);
21721
21722 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21723 cert_request_info_origin->host_and_port =
21724 HostPortPair("www.example.org", 443);
21725
21726 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21727 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21728 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21729 ASSERT_TRUE(identity_origin);
21730
21731 HttpRequestInfo request;
21732 request.method = "GET";
21733 request.url = GURL("https://www.example.org/");
21734 request.traffic_annotation =
21735 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21736
David Benjamin7ebab032019-04-30 21:51:3021737 // First, the client connects to the proxy, which requests a client
21738 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0421739 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21740 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
21741 ssl_proxy1.expected_send_client_cert = false;
21742 StaticSocketDataProvider data1;
21743 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3021744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0421745
David Benjamin7ebab032019-04-30 21:51:3021746 // The client responds with a certificate on a new connection. The handshake
21747 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421748 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21749 ssl_proxy2.expected_send_client_cert = true;
21750 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3021751 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0421752 std::vector<MockWrite> mock_writes2;
21753 std::vector<MockRead> mock_reads2;
21754 mock_writes2.emplace_back(
21755 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21756 "Host: www.example.org:443\r\n"
21757 "Proxy-Connection: keep-alive\r\n\r\n");
21758 mock_reads2.emplace_back(
21759 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21760 "Content-Length: 0\r\n"
21761 "Proxy-Connection: close\r\n"
21762 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21763 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
21764 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3021765 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0421766
David Benjamin7ebab032019-04-30 21:51:3021767 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0421768 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
21769 ssl_proxy3.expected_send_client_cert = true;
21770 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
21771 std::vector<MockWrite> mock_writes3;
21772 std::vector<MockRead> mock_reads3;
21773 mock_writes3.emplace_back(
21774 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21775 "Host: www.example.org:443\r\n"
21776 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021777 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421778 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21779 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21780 // The origin requests client certificates.
21781 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21782 ssl_origin3.cert_request_info = cert_request_info_origin.get();
21783 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
21784 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3021785 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
21786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0421787
David Benjamin7ebab032019-04-30 21:51:3021788 // The client responds to the origin client certificate request on a new
21789 // connection.
David Benjamin2eb827f2019-04-29 18:31:0421790 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
21791 ssl_proxy4.expected_send_client_cert = true;
21792 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
21793 std::vector<MockWrite> mock_writes4;
21794 std::vector<MockRead> mock_reads4;
21795 mock_writes4.emplace_back(
21796 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21797 "Host: www.example.org:443\r\n"
21798 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021799 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421800 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21801 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21802 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
21803 ssl_origin4.expected_send_client_cert = true;
21804 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3021805 // The client sends the origin HTTP request, which results in another HTTP
21806 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0421807 mock_writes4.emplace_back(
21808 "GET / HTTP/1.1\r\n"
21809 "Host: www.example.org\r\n"
21810 "Connection: keep-alive\r\n\r\n");
21811 mock_reads4.emplace_back(
21812 "HTTP/1.1 401 Unauthorized\r\n"
21813 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
21814 "Connection: close\r\n"
21815 "Content-Length: 0\r\n\r\n");
21816 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
21817 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3021818 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
21819 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0421820
David Benjamin7ebab032019-04-30 21:51:3021821 // The client retries with credentials on a new connection, and the request
21822 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0421823 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
21824 ssl_proxy5.expected_send_client_cert = true;
21825 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
21826 std::vector<MockWrite> mock_writes5;
21827 std::vector<MockRead> mock_reads5;
21828 mock_writes5.emplace_back(
21829 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21830 "Host: www.example.org:443\r\n"
21831 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021832 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0421833 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21834 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21835 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
21836 ssl_origin5.expected_send_client_cert = true;
21837 ssl_origin5.expected_client_cert = identity_origin->certificate();
21838 mock_writes5.emplace_back(
21839 "GET / HTTP/1.1\r\n"
21840 "Host: www.example.org\r\n"
21841 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3021842 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0421843 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21844 mock_reads5.emplace_back(
21845 "HTTP/1.1 200 OK\r\n"
21846 "Connection: close\r\n"
21847 "Content-Length: 0\r\n\r\n");
21848 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
21849 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3021850 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
21851 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0421852
David Benjaminbac8dff2019-08-07 01:30:4121853 // The client makes a second request. This needs yet another connection, but
21854 // all credentials are cached.
21855 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
21856 ssl_proxy6.expected_send_client_cert = true;
21857 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
21858 std::vector<MockWrite> mock_writes6;
21859 std::vector<MockRead> mock_reads6;
21860 mock_writes6.emplace_back(
21861 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21862 "Host: www.example.org:443\r\n"
21863 "Proxy-Connection: keep-alive\r\n"
21864 // Authenticate as proxyuser:proxypass.
21865 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21866 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21867 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
21868 ssl_origin6.expected_send_client_cert = true;
21869 ssl_origin6.expected_client_cert = identity_origin->certificate();
21870 mock_writes6.emplace_back(
21871 "GET / HTTP/1.1\r\n"
21872 "Host: www.example.org\r\n"
21873 "Connection: keep-alive\r\n"
21874 // Authenticate as user:pass.
21875 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
21876 mock_reads6.emplace_back(
21877 "HTTP/1.1 200 OK\r\n"
21878 "Connection: close\r\n"
21879 "Content-Length: 0\r\n\r\n");
21880 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
21881 session_deps_.socket_factory->AddSocketDataProvider(&data6);
21882 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
21883 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
21884
David Benjamin2eb827f2019-04-29 18:31:0421885 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21886
21887 // Start the request.
21888 TestCompletionCallback callback;
21889 auto trans =
21890 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21891 int rv = callback.GetResult(
21892 trans->Start(&request, callback.callback(), NetLogWithSource()));
21893
21894 // Handle the proxy client certificate challenge.
21895 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21896 SSLCertRequestInfo* cert_request_info =
21897 trans->GetResponseInfo()->cert_request_info.get();
21898 ASSERT_TRUE(cert_request_info);
21899 EXPECT_TRUE(cert_request_info->is_proxy);
21900 EXPECT_EQ(cert_request_info->host_and_port,
21901 cert_request_info_proxy->host_and_port);
21902 rv = callback.GetResult(trans->RestartWithCertificate(
21903 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
21904 callback.callback()));
21905
21906 // Handle the proxy HTTP auth challenge.
21907 ASSERT_THAT(rv, IsOk());
21908 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
21909 EXPECT_TRUE(
21910 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
21911 rv = callback.GetResult(trans->RestartWithAuth(
21912 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
21913 callback.callback()));
21914
21915 // Handle the origin client certificate challenge.
21916 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
21917 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
21918 ASSERT_TRUE(cert_request_info);
21919 EXPECT_FALSE(cert_request_info->is_proxy);
21920 EXPECT_EQ(cert_request_info->host_and_port,
21921 cert_request_info_origin->host_and_port);
21922 rv = callback.GetResult(trans->RestartWithCertificate(
21923 identity_origin->certificate(), identity_origin->ssl_private_key(),
21924 callback.callback()));
21925
21926 // Handle the origin HTTP auth challenge.
21927 ASSERT_THAT(rv, IsOk());
21928 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
21929 EXPECT_TRUE(
21930 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
21931 rv = callback.GetResult(trans->RestartWithAuth(
21932 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
21933 callback.callback()));
21934
21935 // The request completes.
21936 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3021937 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4121938
21939 // Make a second request. This time all credentials are cached.
21940 trans =
21941 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21942 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
21943 NetLogWithSource())),
21944 IsOk());
21945 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3021946}
21947
21948// Test the proxy requesting HTTP auth and the server requesting TLS client
21949// certificates. This is a regression test for https://crbug.com/946406.
21950TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
21951 // Note these hosts must match the CheckBasic*Auth() functions.
Nicolas Arciniegad2013f92020-02-07 23:00:5621952 session_deps_.proxy_resolution_service =
21953 ConfiguredProxyResolutionService::CreateFixed(
21954 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin7ebab032019-04-30 21:51:3021955
21956 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
21957 cert_request_info_origin->host_and_port =
21958 HostPortPair("www.example.org", 443);
21959
21960 std::unique_ptr<FakeClientCertIdentity> identity_origin =
21961 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21962 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
21963 ASSERT_TRUE(identity_origin);
21964
21965 HttpRequestInfo request;
21966 request.method = "GET";
21967 request.url = GURL("https://www.example.org/");
21968 request.traffic_annotation =
21969 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21970
21971 // The client connects to the proxy. The handshake succeeds.
21972 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21973 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
21974 std::vector<MockWrite> mock_writes1;
21975 std::vector<MockRead> mock_reads1;
21976 mock_writes1.emplace_back(
21977 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21978 "Host: www.example.org:443\r\n"
21979 "Proxy-Connection: keep-alive\r\n\r\n");
21980 mock_reads1.emplace_back(
21981 "HTTP/1.1 407 Proxy Authentication Required\r\n"
21982 "Content-Length: 0\r\n"
21983 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
21984 // The client retries with credentials, and the request finally succeeds.
21985 mock_writes1.emplace_back(
21986 "CONNECT www.example.org:443 HTTP/1.1\r\n"
21987 "Host: www.example.org:443\r\n"
21988 "Proxy-Connection: keep-alive\r\n"
21989 // Authenticate as proxyuser:proxypass.
21990 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
21991 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
21992 // The origin requests client certificates.
21993 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
21994 ssl_origin1.cert_request_info = cert_request_info_origin.get();
21995 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
21996 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21997 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21998 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21999
22000 // The client responds to the origin client certificate request on a new
22001 // connection.
22002 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22003 std::vector<MockWrite> mock_writes2;
22004 std::vector<MockRead> mock_reads2;
22005 mock_writes2.emplace_back(
22006 "CONNECT www.example.org:443 HTTP/1.1\r\n"
22007 "Host: www.example.org:443\r\n"
22008 "Proxy-Connection: keep-alive\r\n"
22009 // Authenticate as proxyuser:proxypass.
22010 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
22011 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
22012 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
22013 ssl_origin2.expected_send_client_cert = true;
22014 ssl_origin2.expected_client_cert = identity_origin->certificate();
22015 // The client sends the origin HTTP request, which succeeds.
22016 mock_writes2.emplace_back(
22017 "GET / HTTP/1.1\r\n"
22018 "Host: www.example.org\r\n"
22019 "Connection: keep-alive\r\n\r\n");
22020 mock_reads2.emplace_back(
22021 "HTTP/1.1 200 OK\r\n"
22022 "Content-Length: 0\r\n\r\n");
22023 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
22024 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22025 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22026 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
22027
22028 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22029
22030 // Start the request.
22031 TestCompletionCallback callback;
22032 auto trans =
22033 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22034 int rv = callback.GetResult(
22035 trans->Start(&request, callback.callback(), NetLogWithSource()));
22036
22037 // Handle the proxy HTTP auth challenge.
22038 ASSERT_THAT(rv, IsOk());
22039 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
22040 EXPECT_TRUE(
22041 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
22042 rv = callback.GetResult(trans->RestartWithAuth(
22043 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
22044 callback.callback()));
22045
22046 // Handle the origin client certificate challenge.
22047 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22048 SSLCertRequestInfo* cert_request_info =
22049 trans->GetResponseInfo()->cert_request_info.get();
22050 ASSERT_TRUE(cert_request_info);
22051 EXPECT_FALSE(cert_request_info->is_proxy);
22052 EXPECT_EQ(cert_request_info->host_and_port,
22053 cert_request_info_origin->host_and_port);
22054 rv = callback.GetResult(trans->RestartWithCertificate(
22055 identity_origin->certificate(), identity_origin->ssl_private_key(),
22056 callback.callback()));
22057
22058 // The request completes.
22059 ASSERT_THAT(rv, IsOk());
22060 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0422061}
22062
David Benjamin6e673a82019-04-30 22:52:5822063// Test that socket reuse works with client certificates.
22064TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
22065 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
22066 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
22067
22068 std::unique_ptr<FakeClientCertIdentity> identity =
22069 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
22070 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
22071 ASSERT_TRUE(identity);
22072
22073 HttpRequestInfo request1;
22074 request1.method = "GET";
22075 request1.url = GURL("https://www.example.org/a");
22076 request1.traffic_annotation =
22077 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22078
22079 HttpRequestInfo request2;
22080 request2.method = "GET";
22081 request2.url = GURL("https://www.example.org/b");
22082 request2.traffic_annotation =
22083 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22084
22085 // The first connection results in a client certificate request.
22086 StaticSocketDataProvider data1;
22087 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22088 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
22089 ssl1.cert_request_info = cert_request_info.get();
22090 ssl1.expected_send_client_cert = false;
22091 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22092
22093 // The second connection succeeds and is usable for both requests.
22094 MockWrite mock_writes[] = {
22095 MockWrite("GET /a HTTP/1.1\r\n"
22096 "Host: www.example.org\r\n"
22097 "Connection: keep-alive\r\n\r\n"),
22098 MockWrite("GET /b HTTP/1.1\r\n"
22099 "Host: www.example.org\r\n"
22100 "Connection: keep-alive\r\n\r\n"),
22101 };
22102 MockRead mock_reads[] = {
22103 MockRead("HTTP/1.1 200 OK\r\n"
22104 "Content-Length: 0\r\n\r\n"),
22105 MockRead("HTTP/1.1 200 OK\r\n"
22106 "Content-Length: 0\r\n\r\n"),
22107 };
22108 StaticSocketDataProvider data2(mock_reads, mock_writes);
22109 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22110 SSLSocketDataProvider ssl2(ASYNC, OK);
22111 ssl2.expected_send_client_cert = true;
22112 ssl2.expected_client_cert = identity->certificate();
22113 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22114
22115 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22116
22117 // Start the first request. It succeeds after providing client certificates.
22118 TestCompletionCallback callback;
22119 auto trans =
22120 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22121 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
22122 NetLogWithSource())),
22123 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22124
22125 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
22126 ASSERT_TRUE(info);
22127 EXPECT_FALSE(info->is_proxy);
22128 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
22129
22130 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
22131 identity->certificate(), identity->ssl_private_key(),
22132 callback.callback())),
22133 IsOk());
22134 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
22135
22136 // Make the second request. It completes without requesting client
22137 // certificates.
22138 trans =
22139 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22140 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
22141 NetLogWithSource())),
22142 IsOk());
22143 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
22144}
22145
Matt Menke166443c2019-05-24 18:45:5922146// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
22147// sequence with two different NetworkIsolationKeys, the first and last have the
22148// same key, the second a different one. Checks that the requests are
22149// partitioned across sockets as expected.
22150TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2722151 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22152 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22153 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
22154 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5922155
22156 for (bool partition_connections : {false, true}) {
22157 SCOPED_TRACE(partition_connections);
22158
22159 base::test::ScopedFeatureList feature_list;
22160 if (partition_connections) {
22161 feature_list.InitAndEnableFeature(
22162 features::kPartitionConnectionsByNetworkIsolationKey);
22163 } else {
22164 feature_list.InitAndDisableFeature(
22165 features::kPartitionConnectionsByNetworkIsolationKey);
22166 }
22167
22168 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22169
22170 // Reads and writes for the unpartitioned case, where only one socket is
22171 // used.
22172
22173 const MockWrite kUnpartitionedWrites[] = {
22174 MockWrite("GET /1 HTTP/1.1\r\n"
22175 "Host: foo.test\r\n"
22176 "Connection: keep-alive\r\n\r\n"),
22177 MockWrite("GET /2 HTTP/1.1\r\n"
22178 "Host: foo.test\r\n"
22179 "Connection: keep-alive\r\n\r\n"),
22180 MockWrite("GET /3 HTTP/1.1\r\n"
22181 "Host: foo.test\r\n"
22182 "Connection: keep-alive\r\n\r\n"),
22183 };
22184
22185 const MockRead kUnpartitionedReads[] = {
22186 MockRead("HTTP/1.1 200 OK\r\n"
22187 "Connection: keep-alive\r\n"
22188 "Content-Length: 1\r\n\r\n"
22189 "1"),
22190 MockRead("HTTP/1.1 200 OK\r\n"
22191 "Connection: keep-alive\r\n"
22192 "Content-Length: 1\r\n\r\n"
22193 "2"),
22194 MockRead("HTTP/1.1 200 OK\r\n"
22195 "Connection: keep-alive\r\n"
22196 "Content-Length: 1\r\n\r\n"
22197 "3"),
22198 };
22199
22200 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
22201 kUnpartitionedWrites);
22202
22203 // Reads and writes for the partitioned case, where two sockets are used.
22204
22205 const MockWrite kPartitionedWrites1[] = {
22206 MockWrite("GET /1 HTTP/1.1\r\n"
22207 "Host: foo.test\r\n"
22208 "Connection: keep-alive\r\n\r\n"),
22209 MockWrite("GET /3 HTTP/1.1\r\n"
22210 "Host: foo.test\r\n"
22211 "Connection: keep-alive\r\n\r\n"),
22212 };
22213
22214 const MockRead kPartitionedReads1[] = {
22215 MockRead("HTTP/1.1 200 OK\r\n"
22216 "Connection: keep-alive\r\n"
22217 "Content-Length: 1\r\n\r\n"
22218 "1"),
22219 MockRead("HTTP/1.1 200 OK\r\n"
22220 "Connection: keep-alive\r\n"
22221 "Content-Length: 1\r\n\r\n"
22222 "3"),
22223 };
22224
22225 const MockWrite kPartitionedWrites2[] = {
22226 MockWrite("GET /2 HTTP/1.1\r\n"
22227 "Host: foo.test\r\n"
22228 "Connection: keep-alive\r\n\r\n"),
22229 };
22230
22231 const MockRead kPartitionedReads2[] = {
22232 MockRead("HTTP/1.1 200 OK\r\n"
22233 "Connection: keep-alive\r\n"
22234 "Content-Length: 1\r\n\r\n"
22235 "2"),
22236 };
22237
22238 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
22239 kPartitionedWrites1);
22240 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
22241 kPartitionedWrites2);
22242
22243 if (partition_connections) {
22244 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22245 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22246 } else {
22247 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
22248 }
22249
22250 TestCompletionCallback callback;
22251 HttpRequestInfo request1;
22252 request1.method = "GET";
22253 request1.url = GURL("http://foo.test/1");
22254 request1.traffic_annotation =
22255 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22256 request1.network_isolation_key = network_isolation_key1;
22257 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22258 session.get());
22259 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22260 EXPECT_THAT(callback.GetResult(rv), IsOk());
22261 std::string response_data1;
22262 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22263 EXPECT_EQ("1", response_data1);
22264 trans1.reset();
22265
22266 HttpRequestInfo request2;
22267 request2.method = "GET";
22268 request2.url = GURL("http://foo.test/2");
22269 request2.traffic_annotation =
22270 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22271 request2.network_isolation_key = network_isolation_key2;
22272 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22273 session.get());
22274 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22275 EXPECT_THAT(callback.GetResult(rv), IsOk());
22276 std::string response_data2;
22277 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22278 EXPECT_EQ("2", response_data2);
22279 trans2.reset();
22280
22281 HttpRequestInfo request3;
22282 request3.method = "GET";
22283 request3.url = GURL("http://foo.test/3");
22284 request3.traffic_annotation =
22285 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22286 request3.network_isolation_key = network_isolation_key1;
22287 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
22288 session.get());
22289 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22290 EXPECT_THAT(callback.GetResult(rv), IsOk());
22291 std::string response_data3;
22292 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22293 EXPECT_EQ("3", response_data3);
22294 trans3.reset();
22295 }
22296}
22297
Matt Menkeae58eeb2019-05-24 21:09:5022298TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2722299 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22300 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22301 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
22302 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5022303
22304 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
22305 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
22306 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
22307 // the same way as the HTTP over H2 proxy case.
22308 for (bool use_proxy : {false, true}) {
22309 SCOPED_TRACE(use_proxy);
22310 if (use_proxy) {
22311 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622312 ConfiguredProxyResolutionService::CreateFixedFromPacResult(
Matt Menkeae58eeb2019-05-24 21:09:5022313 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
22314 } else {
22315 session_deps_.proxy_resolution_service =
Nicolas Arciniegad2013f92020-02-07 23:00:5622316 ConfiguredProxyResolutionService::CreateDirect();
Matt Menkeae58eeb2019-05-24 21:09:5022317 }
22318 const char* url1 = nullptr;
22319 const char* url2 = nullptr;
22320 const char* url3 = nullptr;
22321 if (use_proxy) {
22322 url1 = "http://foo.test/1";
22323 url2 = "http://foo.test/2";
22324 url3 = "http://foo.test/3";
22325 } else {
22326 url1 = "https://foo.test/1";
22327 url2 = "https://foo.test/2";
22328 url3 = "https://foo.test/3";
22329 }
22330
22331 for (bool partition_connections : {false, true}) {
22332 SCOPED_TRACE(partition_connections);
22333
22334 base::test::ScopedFeatureList feature_list;
22335 if (partition_connections) {
22336 feature_list.InitAndEnableFeature(
22337 features::kPartitionConnectionsByNetworkIsolationKey);
22338 } else {
22339 feature_list.InitAndDisableFeature(
22340 features::kPartitionConnectionsByNetworkIsolationKey);
22341 }
22342
22343 std::unique_ptr<HttpNetworkSession> session(
22344 CreateSession(&session_deps_));
22345
22346 // Reads and writes for the unpartitioned case, where only one socket is
22347 // used.
22348
22349 SpdyTestUtil spdy_util;
22350 spdy::SpdySerializedFrame unpartitioned_req1(
22351 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
22352 spdy::SpdySerializedFrame unpartitioned_response1(
22353 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
22354 spdy::SpdySerializedFrame unpartitioned_body1(
22355 spdy_util.ConstructSpdyDataFrame(1, "1", true));
22356 spdy_util.UpdateWithStreamDestruction(1);
22357
22358 spdy::SpdySerializedFrame unpartitioned_req2(
22359 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
22360 spdy::SpdySerializedFrame unpartitioned_response2(
22361 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
22362 spdy::SpdySerializedFrame unpartitioned_body2(
22363 spdy_util.ConstructSpdyDataFrame(3, "2", true));
22364 spdy_util.UpdateWithStreamDestruction(3);
22365
22366 spdy::SpdySerializedFrame unpartitioned_req3(
22367 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
22368 spdy::SpdySerializedFrame unpartitioned_response3(
22369 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
22370 spdy::SpdySerializedFrame unpartitioned_body3(
22371 spdy_util.ConstructSpdyDataFrame(5, "3", true));
22372
22373 const MockWrite kUnpartitionedWrites[] = {
22374 CreateMockWrite(unpartitioned_req1, 0),
22375 CreateMockWrite(unpartitioned_req2, 3),
22376 CreateMockWrite(unpartitioned_req3, 6),
22377 };
22378
22379 const MockRead kUnpartitionedReads[] = {
22380 CreateMockRead(unpartitioned_response1, 1),
22381 CreateMockRead(unpartitioned_body1, 2),
22382 CreateMockRead(unpartitioned_response2, 4),
22383 CreateMockRead(unpartitioned_body2, 5),
22384 CreateMockRead(unpartitioned_response3, 7),
22385 CreateMockRead(unpartitioned_body3, 8),
22386 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
22387 };
22388
22389 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
22390 kUnpartitionedWrites);
22391
22392 // Reads and writes for the partitioned case, where two sockets are used.
22393
22394 SpdyTestUtil spdy_util2;
22395 spdy::SpdySerializedFrame partitioned_req1(
22396 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
22397 spdy::SpdySerializedFrame partitioned_response1(
22398 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
22399 spdy::SpdySerializedFrame partitioned_body1(
22400 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
22401 spdy_util2.UpdateWithStreamDestruction(1);
22402
22403 spdy::SpdySerializedFrame partitioned_req3(
22404 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
22405 spdy::SpdySerializedFrame partitioned_response3(
22406 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
22407 spdy::SpdySerializedFrame partitioned_body3(
22408 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
22409
22410 const MockWrite kPartitionedWrites1[] = {
22411 CreateMockWrite(partitioned_req1, 0),
22412 CreateMockWrite(partitioned_req3, 3),
22413 };
22414
22415 const MockRead kPartitionedReads1[] = {
22416 CreateMockRead(partitioned_response1, 1),
22417 CreateMockRead(partitioned_body1, 2),
22418 CreateMockRead(partitioned_response3, 4),
22419 CreateMockRead(partitioned_body3, 5),
22420 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
22421 };
22422
22423 SpdyTestUtil spdy_util3;
22424 spdy::SpdySerializedFrame partitioned_req2(
22425 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
22426 spdy::SpdySerializedFrame partitioned_response2(
22427 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
22428 spdy::SpdySerializedFrame partitioned_body2(
22429 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
22430
22431 const MockWrite kPartitionedWrites2[] = {
22432 CreateMockWrite(partitioned_req2, 0),
22433 };
22434
22435 const MockRead kPartitionedReads2[] = {
22436 CreateMockRead(partitioned_response2, 1),
22437 CreateMockRead(partitioned_body2, 2),
22438 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
22439 };
22440
22441 SequencedSocketData partitioned_data1(kPartitionedReads1,
22442 kPartitionedWrites1);
22443 SequencedSocketData partitioned_data2(kPartitionedReads2,
22444 kPartitionedWrites2);
22445
22446 // No need to segment SSLDataProviders by whether or not partitioning is
22447 // enabled.
22448 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22449 ssl_data1.next_proto = kProtoHTTP2;
22450 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22451 ssl_data2.next_proto = kProtoHTTP2;
22452
22453 if (partition_connections) {
22454 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
22455 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22456 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
22457 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22458 } else {
22459 session_deps_.socket_factory->AddSocketDataProvider(
22460 &unpartitioned_data);
22461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22462 }
22463
22464 TestCompletionCallback callback;
22465 HttpRequestInfo request1;
22466 request1.method = "GET";
22467 request1.url = GURL(url1);
22468 request1.traffic_annotation =
22469 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22470 request1.network_isolation_key = network_isolation_key1;
22471 auto trans1 =
22472 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22473 int rv =
22474 trans1->Start(&request1, callback.callback(), NetLogWithSource());
22475 EXPECT_THAT(callback.GetResult(rv), IsOk());
22476 std::string response_data1;
22477 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22478 EXPECT_EQ("1", response_data1);
22479 trans1.reset();
22480
22481 HttpRequestInfo request2;
22482 request2.method = "GET";
22483 request2.url = GURL(url2);
22484 request2.traffic_annotation =
22485 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22486 request2.network_isolation_key = network_isolation_key2;
22487 auto trans2 =
22488 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22489 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22490 EXPECT_THAT(callback.GetResult(rv), IsOk());
22491 std::string response_data2;
22492 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22493 EXPECT_EQ("2", response_data2);
22494 trans2.reset();
22495
22496 HttpRequestInfo request3;
22497 request3.method = "GET";
22498 request3.url = GURL(url3);
22499 request3.traffic_annotation =
22500 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22501 request3.network_isolation_key = network_isolation_key1;
22502 auto trans3 =
22503 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
22504 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22505 EXPECT_THAT(callback.GetResult(rv), IsOk());
22506 std::string response_data3;
22507 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22508 EXPECT_EQ("3", response_data3);
22509 trans3.reset();
22510 }
22511 }
22512}
22513
Matt Menke7281f872019-06-25 19:29:2522514// Preconnect two sockets with different NetworkIsolationKeys when
22515// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
22516// request and make sure the correct socket is used. Loops three times,
22517// expecting to use the first preconnect, second preconnect, and neither.
22518TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
22519 base::test::ScopedFeatureList feature_list;
22520 feature_list.InitAndEnableFeature(
22521 features::kPartitionConnectionsByNetworkIsolationKey);
22522
22523 enum class TestCase {
22524 kUseFirstPreconnect,
22525 kUseSecondPreconnect,
22526 kDontUsePreconnect,
22527 };
22528
Shivani Sharma8ae506c2019-07-21 21:08:2722529 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22530 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22531 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
22532 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
22533 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
22534 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2522535
22536 // Test that only preconnects with
22537 for (TestCase test_case :
22538 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
22539 TestCase::kDontUsePreconnect}) {
22540 SpdySessionDependencies session_deps;
22541 // Make DNS lookups completely synchronously, so preconnects complete
22542 // immediately.
22543 session_deps.host_resolver->set_synchronous_mode(true);
22544
22545 const MockWrite kMockWrites[] = {
22546 MockWrite(ASYNC, 0,
22547 "GET / HTTP/1.1\r\n"
22548 "Host: www.foo.com\r\n"
22549 "Connection: keep-alive\r\n\r\n"),
22550 };
22551
22552 const MockRead kMockReads[] = {
22553 MockRead(ASYNC, 1,
22554 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
22555 "hello"),
22556 };
22557
22558 // Used for the socket that will actually be used, which may or may not be
22559 // one of the preconnects
22560 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
22561 kMockReads, kMockWrites);
22562
22563 // Used for the preconnects that won't actually be used.
22564 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
22565 base::span<const MockRead>(),
22566 base::span<const MockWrite>());
22567 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
22568 base::span<const MockRead>(),
22569 base::span<const MockWrite>());
22570
22571 NetworkIsolationKey network_isolation_key_for_request;
22572
22573 switch (test_case) {
22574 case TestCase::kUseFirstPreconnect:
22575 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22576 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22577 network_isolation_key_for_request = preconnect1_isolation_key;
22578 break;
22579 case TestCase::kUseSecondPreconnect:
22580 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22581 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22582 network_isolation_key_for_request = preconnect2_isolation_key;
22583 break;
22584 case TestCase::kDontUsePreconnect:
22585 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
22586 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
22587 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
22588 network_isolation_key_for_request = not_preconnected_isolation_key;
22589 break;
22590 }
22591
22592 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
22593
22594 // Preconnect sockets.
22595 HttpRequestInfo request;
22596 request.method = "GET";
22597 request.url = GURL("http://www.foo.com/");
22598 request.traffic_annotation =
22599 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22600
22601 request.network_isolation_key = preconnect1_isolation_key;
22602 session->http_stream_factory()->PreconnectStreams(1, request);
22603
22604 request.network_isolation_key = preconnect2_isolation_key;
22605 session->http_stream_factory()->PreconnectStreams(1, request);
22606
22607 request.network_isolation_key = network_isolation_key_for_request;
22608
22609 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22610
22611 // Make the request.
22612 TestCompletionCallback callback;
22613
22614 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22615
22616 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22617 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22618
22619 rv = callback.WaitForResult();
22620 EXPECT_THAT(rv, IsOk());
22621
22622 const HttpResponseInfo* response = trans.GetResponseInfo();
22623 ASSERT_TRUE(response);
22624 ASSERT_TRUE(response->headers);
22625 EXPECT_EQ(200, response->headers->response_code());
22626
22627 std::string response_data;
22628 rv = ReadTransaction(&trans, &response_data);
22629 EXPECT_THAT(rv, IsOk());
22630 EXPECT_EQ("hello", response_data);
22631
22632 if (test_case != TestCase::kDontUsePreconnect) {
22633 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
22634 } else {
22635 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
22636 }
22637 }
22638}
22639
David Benjamin6f2da652019-06-26 23:36:3522640// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22641// cache is isolated.
22642TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
22643 base::test::ScopedFeatureList feature_list;
22644 feature_list.InitWithFeatures(
22645 {features::kPartitionConnectionsByNetworkIsolationKey,
22646 features::kPartitionSSLSessionsByNetworkIsolationKey},
22647 {});
22648
Shivani Sharma8ae506c2019-07-21 21:08:2722649 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22650 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22651 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22652 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522653 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22654
22655 // The server always sends Connection: close, so each request goes over a
22656 // distinct socket.
22657
22658 const MockWrite kWrites1[] = {
22659 MockWrite("GET /1 HTTP/1.1\r\n"
22660 "Host: foo.test\r\n"
22661 "Connection: keep-alive\r\n\r\n")};
22662
22663 const MockRead kReads1[] = {
22664 MockRead("HTTP/1.1 200 OK\r\n"
22665 "Connection: close\r\n"
22666 "Content-Length: 1\r\n\r\n"
22667 "1")};
22668
22669 const MockWrite kWrites2[] = {
22670 MockWrite("GET /2 HTTP/1.1\r\n"
22671 "Host: foo.test\r\n"
22672 "Connection: keep-alive\r\n\r\n")};
22673
22674 const MockRead kReads2[] = {
22675 MockRead("HTTP/1.1 200 OK\r\n"
22676 "Connection: close\r\n"
22677 "Content-Length: 1\r\n\r\n"
22678 "2")};
22679
22680 const MockWrite kWrites3[] = {
22681 MockWrite("GET /3 HTTP/1.1\r\n"
22682 "Host: foo.test\r\n"
22683 "Connection: keep-alive\r\n\r\n")};
22684
22685 const MockRead kReads3[] = {
22686 MockRead("HTTP/1.1 200 OK\r\n"
22687 "Connection: close\r\n"
22688 "Content-Length: 1\r\n\r\n"
22689 "3")};
22690
22691 StaticSocketDataProvider data1(kReads1, kWrites1);
22692 StaticSocketDataProvider data2(kReads2, kWrites2);
22693 StaticSocketDataProvider data3(kReads3, kWrites3);
22694 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22695 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22696 session_deps_.socket_factory->AddSocketDataProvider(&data3);
22697
22698 SSLSocketDataProvider ssl_data1(ASYNC, OK);
22699 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
22700 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
22701 SSLSocketDataProvider ssl_data2(ASYNC, OK);
22702 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
22703 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
22704 SSLSocketDataProvider ssl_data3(ASYNC, OK);
22705 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
22706 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
22707 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
22708 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
22709 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
22710
22711 TestCompletionCallback callback;
22712 HttpRequestInfo request1;
22713 request1.method = "GET";
22714 request1.url = GURL("https://foo.test/1");
22715 request1.traffic_annotation =
22716 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22717 request1.network_isolation_key = kNetworkIsolationKey1;
22718 auto trans1 =
22719 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22720 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22721 EXPECT_THAT(callback.GetResult(rv), IsOk());
22722 std::string response_data1;
22723 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22724 EXPECT_EQ("1", response_data1);
22725 trans1.reset();
22726
22727 HttpRequestInfo request2;
22728 request2.method = "GET";
22729 request2.url = GURL("https://foo.test/2");
22730 request2.traffic_annotation =
22731 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22732 request2.network_isolation_key = kNetworkIsolationKey2;
22733 auto trans2 =
22734 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22735 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22736 EXPECT_THAT(callback.GetResult(rv), IsOk());
22737 std::string response_data2;
22738 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22739 EXPECT_EQ("2", response_data2);
22740 trans2.reset();
22741
22742 HttpRequestInfo request3;
22743 request3.method = "GET";
22744 request3.url = GURL("https://foo.test/3");
22745 request3.traffic_annotation =
22746 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22747 request3.network_isolation_key = kNetworkIsolationKey1;
22748 auto trans3 =
22749 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22750 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22751 EXPECT_THAT(callback.GetResult(rv), IsOk());
22752 std::string response_data3;
22753 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22754 EXPECT_EQ("3", response_data3);
22755 trans3.reset();
22756}
22757
22758// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
22759// cache is isolated, for both origins and proxies.
22760TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
22761 base::test::ScopedFeatureList feature_list;
22762 feature_list.InitWithFeatures(
22763 {features::kPartitionConnectionsByNetworkIsolationKey,
22764 features::kPartitionSSLSessionsByNetworkIsolationKey},
22765 {});
22766
Nicolas Arciniegad2013f92020-02-07 23:00:5622767 session_deps_.proxy_resolution_service =
22768 ConfiguredProxyResolutionService::CreateFixed(
22769 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
David Benjamin6f2da652019-06-26 23:36:3522770
Shivani Sharma8ae506c2019-07-21 21:08:2722771 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
22772 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
22773 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
22774 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3522775 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22776
22777 // Make both a tunneled and non-tunneled request.
22778 HttpRequestInfo request1;
22779 request1.method = "GET";
22780 request1.url = GURL("https://foo.test/1");
22781 request1.traffic_annotation =
22782 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22783 request1.network_isolation_key = kNetworkIsolationKey1;
22784
22785 HttpRequestInfo request2;
22786 request2.method = "GET";
22787 request2.url = GURL("http://foo.test/2");
22788 request2.traffic_annotation =
22789 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22790 request2.network_isolation_key = kNetworkIsolationKey2;
22791
22792 const MockWrite kWrites1[] = {
22793 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
22794 "Host: foo.test:443\r\n"
22795 "Proxy-Connection: keep-alive\r\n\r\n"),
22796 MockWrite("GET /1 HTTP/1.1\r\n"
22797 "Host: foo.test\r\n"
22798 "Connection: keep-alive\r\n\r\n")};
22799
22800 const MockRead kReads1[] = {
22801 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
22802 MockRead("HTTP/1.1 200 OK\r\n"
22803 "Connection: close\r\n"
22804 "Content-Length: 1\r\n\r\n"
22805 "1")};
22806
22807 const MockWrite kWrites2[] = {
22808 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
22809 "Host: foo.test\r\n"
22810 "Proxy-Connection: keep-alive\r\n\r\n")};
22811
22812 const MockRead kReads2[] = {
22813 MockRead("HTTP/1.1 200 OK\r\n"
22814 "Connection: close\r\n"
22815 "Content-Length: 1\r\n\r\n"
22816 "2")};
22817
22818 StaticSocketDataProvider data1(kReads1, kWrites1);
22819 StaticSocketDataProvider data2(kReads2, kWrites2);
22820 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22821 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22822 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22823
22824 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
22825 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
22826 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
22827 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
22828 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
22829 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
22830 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
22831 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
22832 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
22833 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
22834 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
22835 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
22836
22837 TestCompletionCallback callback;
22838 auto trans1 =
22839 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22840 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22841 EXPECT_THAT(callback.GetResult(rv), IsOk());
22842 std::string response_data1;
22843 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22844 EXPECT_EQ("1", response_data1);
22845 trans1.reset();
22846
22847 auto trans2 =
22848 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22849 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22850 EXPECT_THAT(callback.GetResult(rv), IsOk());
22851 std::string response_data2;
22852 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22853 EXPECT_EQ("2", response_data2);
22854 trans2.reset();
22855}
22856
David Benjaminef2f2a5a2019-07-16 19:21:3122857// Test that SSLConfig changes from SSLConfigService are picked up even when
22858// there are live sockets.
22859TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
David Benjamin151ec6b2019-08-02 19:38:5222860 SSLContextConfig ssl_context_config;
22861 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22862 auto ssl_config_service =
22863 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122864 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22865
22866 session_deps_.ssl_config_service = std::move(ssl_config_service);
22867
22868 // Make three requests. Between the second and third, the SSL config will
22869 // change.
22870 HttpRequestInfo request1;
22871 request1.method = "GET";
22872 request1.url = GURL("https://foo.test/1");
22873 request1.traffic_annotation =
22874 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22875
22876 HttpRequestInfo request2;
22877 request2.method = "GET";
22878 request2.url = GURL("https://foo.test/2");
22879 request2.traffic_annotation =
22880 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22881
22882 HttpRequestInfo request3;
22883 request3.method = "GET";
22884 request3.url = GURL("https://foo.test/3");
22885 request3.traffic_annotation =
22886 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22887
22888 const MockWrite kWrites1[] = {
22889 MockWrite("GET /1 HTTP/1.1\r\n"
22890 "Host: foo.test\r\n"
22891 "Connection: keep-alive\r\n\r\n"),
22892 MockWrite("GET /2 HTTP/1.1\r\n"
22893 "Host: foo.test\r\n"
22894 "Connection: keep-alive\r\n\r\n"),
22895 };
22896
22897 const MockRead kReads1[] = {
22898 MockRead("HTTP/1.1 200 OK\r\n"
22899 "Connection: keep-alive\r\n"
22900 "Content-Length: 1\r\n\r\n"
22901 "1"),
22902 MockRead("HTTP/1.1 200 OK\r\n"
22903 "Connection: keep-alive\r\n"
22904 "Content-Length: 1\r\n\r\n"
22905 "2"),
22906 };
22907
22908 // The third request goes on a different socket because the SSL config has
22909 // changed.
22910 const MockWrite kWrites2[] = {
22911 MockWrite("GET /3 HTTP/1.1\r\n"
22912 "Host: foo.test\r\n"
22913 "Connection: keep-alive\r\n\r\n")};
22914
22915 const MockRead kReads2[] = {
22916 MockRead("HTTP/1.1 200 OK\r\n"
22917 "Connection: keep-alive\r\n"
22918 "Content-Length: 1\r\n\r\n"
22919 "3")};
22920
22921 StaticSocketDataProvider data1(kReads1, kWrites1);
22922 StaticSocketDataProvider data2(kReads2, kWrites2);
22923 session_deps_.socket_factory->AddSocketDataProvider(&data1);
22924 session_deps_.socket_factory->AddSocketDataProvider(&data2);
22925
22926 SSLSocketDataProvider ssl1(ASYNC, OK);
22927 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22928 SSLSocketDataProvider ssl2(ASYNC, OK);
22929 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22930 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
22931 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
22932
22933 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22934
22935 TestCompletionCallback callback;
22936 auto trans1 =
22937 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22938 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22939 EXPECT_THAT(callback.GetResult(rv), IsOk());
22940 std::string response_data1;
22941 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
22942 EXPECT_EQ("1", response_data1);
22943 trans1.reset();
22944
22945 auto trans2 =
22946 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22947 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
22948 EXPECT_THAT(callback.GetResult(rv), IsOk());
22949 std::string response_data2;
22950 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
22951 EXPECT_EQ("2", response_data2);
22952 trans2.reset();
22953
David Benjamin151ec6b2019-08-02 19:38:5222954 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22955 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122956
22957 auto trans3 =
22958 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22959 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
22960 EXPECT_THAT(callback.GetResult(rv), IsOk());
22961 std::string response_data3;
22962 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
22963 EXPECT_EQ("3", response_data3);
22964 trans3.reset();
22965}
22966
22967TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5222968 SSLContextConfig ssl_context_config;
22969 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22970 auto ssl_config_service =
22971 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122972 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
22973
22974 session_deps_.ssl_config_service = std::move(ssl_config_service);
22975
22976 HttpRequestInfo request;
22977 request.method = "GET";
22978 request.url = GURL("https://foo.test/1");
22979 request.traffic_annotation =
22980 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22981
22982 // Make a socket which never connects.
22983 StaticSocketDataProvider data({}, {});
22984 session_deps_.socket_factory->AddSocketDataProvider(&data);
22985 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
22986 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
22987 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
22988
22989 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22990
22991 TestCompletionCallback callback;
22992 auto trans =
22993 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22994 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
22995 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22996
David Benjamin151ec6b2019-08-02 19:38:5222997 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
22998 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3122999
23000 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
23001}
23002
David Benjaminbac8dff2019-08-07 01:30:4123003// Test that HttpNetworkTransaction correctly handles existing sockets when the
23004// server requests a client certificate post-handshake (via a TLS
23005// renegotiation). This is a regression test for https://crbug.com/829184.
23006TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
23007 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
23008 TRAFFIC_ANNOTATION_FOR_TESTS);
23009
23010 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
23011 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
23012
23013 std::unique_ptr<FakeClientCertIdentity> identity =
23014 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
23015 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
23016 ASSERT_TRUE(identity);
23017
23018 // This test will make several requests so that, when the client certificate
23019 // request comes in, we have a socket in use, an idle socket, and a socket for
23020 // an unrelated host.
23021 //
23022 // First, two long-lived requests which do not complete until after the client
23023 // certificate request. This arranges for sockets to be in use during the
23024 // request. They should not be interrupted.
23025 HttpRequestInfo request_long_lived;
23026 request_long_lived.method = "GET";
23027 request_long_lived.url = GURL("https://foo.test/long-lived");
23028 request_long_lived.traffic_annotation = kTrafficAnnotation;
23029
23030 HttpRequestInfo request_long_lived_bar;
23031 request_long_lived_bar.method = "GET";
23032 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
23033 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
23034
23035 // Next, make a request that needs client certificates.
23036 HttpRequestInfo request_auth;
23037 request_auth.method = "GET";
23038 request_auth.url = GURL("https://foo.test/auth");
23039 request_auth.traffic_annotation = kTrafficAnnotation;
23040
23041 // Before responding to the challenge, make a request to an unauthenticated
23042 // endpoint. This will result in an idle socket when the client certificate
23043 // challenge is resolved.
23044 HttpRequestInfo request_unauth;
23045 request_unauth.method = "GET";
23046 request_unauth.url = GURL("https://foo.test/unauth");
23047 request_unauth.traffic_annotation = kTrafficAnnotation;
23048
23049 // After all the preceding requests complete, end with two additional requests
23050 // to ensure pre-authentication foo.test sockets are not used and bar.test
23051 // sockets are unaffected.
23052 HttpRequestInfo request_post_auth;
23053 request_post_auth.method = "GET";
23054 request_post_auth.url = GURL("https://foo.test/post-auth");
23055 request_post_auth.traffic_annotation = kTrafficAnnotation;
23056
23057 HttpRequestInfo request_post_auth_bar;
23058 request_post_auth_bar.method = "GET";
23059 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
23060 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
23061
23062 // The sockets for /long-lived and /unauth complete their request but are
23063 // not allocated for /post-auth or /retry because SSL state has since changed.
23064 const MockWrite kLongLivedWrites[] = {
23065 MockWrite(ASYNC, 0,
23066 "GET /long-lived HTTP/1.1\r\n"
23067 "Host: foo.test\r\n"
23068 "Connection: keep-alive\r\n\r\n"),
23069 };
23070 const MockRead kLongLivedReads[] = {
23071 // Pause so /long-lived completes after the client presents client
23072 // certificates.
23073 MockRead(ASYNC, ERR_IO_PENDING, 1),
23074 MockRead(ASYNC, 2,
23075 "HTTP/1.1 200 OK\r\n"
23076 "Connection: keep-alive\r\n"
23077 "Content-Length: 10\r\n\r\n"
23078 "long-lived"),
23079 };
23080 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
23081 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
23082 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
23083 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
23084
23085 // Requests for bar.test should be unaffected by foo.test and get allocated
23086 // a single socket.
23087 const MockWrite kBarWrites[] = {
23088 MockWrite(ASYNC, 0,
23089 "GET /long-lived HTTP/1.1\r\n"
23090 "Host: bar.test\r\n"
23091 "Connection: keep-alive\r\n\r\n"),
23092 MockWrite(ASYNC, 3,
23093 "GET /post-auth HTTP/1.1\r\n"
23094 "Host: bar.test\r\n"
23095 "Connection: keep-alive\r\n\r\n"),
23096 };
23097 const MockRead kBarReads[] = {
23098 // Pause on /long-lived so it completes after foo.test's authentication.
23099 MockRead(ASYNC, ERR_IO_PENDING, 1),
23100 MockRead(ASYNC, 2,
23101 "HTTP/1.1 200 OK\r\n"
23102 "Connection: keep-alive\r\n"
23103 "Content-Length: 10\r\n\r\n"
23104 "long-lived"),
23105 MockRead(ASYNC, 4,
23106 "HTTP/1.1 200 OK\r\n"
23107 "Connection: keep-alive\r\n"
23108 "Content-Length: 9\r\n\r\n"
23109 "post-auth"),
23110 };
23111 SequencedSocketData data_bar(kBarReads, kBarWrites);
23112 SSLSocketDataProvider ssl_bar(ASYNC, OK);
23113 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
23114 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
23115
23116 // Requesting /auth results in a post-handshake client certificate challenge.
23117 const MockWrite kAuthWrites[] = {
23118 MockWrite(ASYNC, 0,
23119 "GET /auth HTTP/1.1\r\n"
23120 "Host: foo.test\r\n"
23121 "Connection: keep-alive\r\n\r\n"),
23122 };
23123 const MockRead kAuthReads[] = {
23124 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
23125 };
23126 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
23127 SSLSocketDataProvider ssl_auth(ASYNC, OK);
23128 ssl_auth.cert_request_info = cert_request_info.get();
23129 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
23130 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
23131
23132 // Requesting /unauth completes.
23133 const MockWrite kUnauthWrites[] = {
23134 MockWrite(ASYNC, 0,
23135 "GET /unauth HTTP/1.1\r\n"
23136 "Host: foo.test\r\n"
23137 "Connection: keep-alive\r\n\r\n"),
23138 };
23139 const MockRead kUnauthReads[] = {
23140 MockRead(ASYNC, 1,
23141 "HTTP/1.1 200 OK\r\n"
23142 "Connection: keep-alive\r\n"
23143 "Content-Length: 6\r\n\r\n"
23144 "unauth"),
23145 };
23146 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
23147 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
23148 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
23149 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
23150
23151 // When the client certificate is selected, /auth is retried on a new
23152 // connection. In particular, it should not be retried on |data_unauth|,
23153 // which would not honor the new client certificate configuration.
23154 const MockWrite kRetryWrites[] = {
23155 MockWrite(ASYNC, 0,
23156 "GET /auth HTTP/1.1\r\n"
23157 "Host: foo.test\r\n"
23158 "Connection: keep-alive\r\n\r\n"),
23159 };
23160 const MockRead kRetryReads[] = {
23161 MockRead(ASYNC, 1,
23162 "HTTP/1.1 200 OK\r\n"
23163 // Close the connection so we test that /post-auth is not
23164 // allocated to |data_unauth| or |data_long_lived|.
23165 "Connection: close\r\n"
23166 "Content-Length: 4\r\n\r\n"
23167 "auth"),
23168 };
23169 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
23170 SSLSocketDataProvider ssl_retry(ASYNC, OK);
23171 ssl_retry.expected_send_client_cert = true;
23172 ssl_retry.expected_client_cert = identity->certificate();
23173 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
23174 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
23175
23176 // /post-auth gets its own socket.
23177 const MockWrite kPostAuthWrites[] = {
23178 MockWrite(ASYNC, 0,
23179 "GET /post-auth HTTP/1.1\r\n"
23180 "Host: foo.test\r\n"
23181 "Connection: keep-alive\r\n\r\n"),
23182 };
23183 const MockRead kPostAuthReads[] = {
23184 MockRead(ASYNC, 1,
23185 "HTTP/1.1 200 OK\r\n"
23186 "Connection: keep-alive\r\n"
23187 "Content-Length: 9\r\n\r\n"
23188 "post-auth"),
23189 };
23190 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
23191 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
23192 ssl_post_auth.expected_send_client_cert = true;
23193 ssl_post_auth.expected_client_cert = identity->certificate();
23194 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
23195 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
23196
23197 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
23198
23199 // Start the two long-lived requests.
23200 TestCompletionCallback callback_long_lived;
23201 auto trans_long_lived =
23202 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23203 int rv = trans_long_lived->Start(
23204 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
23205 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
23206 data_long_lived.RunUntilPaused();
23207
23208 TestCompletionCallback callback_long_lived_bar;
23209 auto trans_long_lived_bar =
23210 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23211 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
23212 callback_long_lived_bar.callback(),
23213 NetLogWithSource());
23214 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
23215 data_bar.RunUntilPaused();
23216
23217 // Request /auth. This gives a client certificate challenge.
23218 TestCompletionCallback callback_auth;
23219 auto trans_auth =
23220 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23221 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
23222 NetLogWithSource());
23223 EXPECT_THAT(callback_auth.GetResult(rv),
23224 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
23225
23226 // Make an unauthenticated request. This completes.
23227 TestCompletionCallback callback_unauth;
23228 auto trans_unauth =
23229 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23230 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
23231 NetLogWithSource());
23232 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
23233 std::string response_unauth;
23234 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
23235 EXPECT_EQ("unauth", response_unauth);
23236 trans_unauth.reset();
23237
23238 // Complete the authenticated request.
23239 rv = trans_auth->RestartWithCertificate(identity->certificate(),
23240 identity->ssl_private_key(),
23241 callback_auth.callback());
23242 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
23243 std::string response_auth;
23244 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
23245 EXPECT_EQ("auth", response_auth);
23246 trans_auth.reset();
23247
23248 // Complete the long-lived requests.
23249 data_long_lived.Resume();
23250 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
23251 std::string response_long_lived;
23252 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
23253 IsOk());
23254 EXPECT_EQ("long-lived", response_long_lived);
23255 trans_long_lived.reset();
23256
23257 data_bar.Resume();
23258 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
23259 std::string response_long_lived_bar;
23260 EXPECT_THAT(
23261 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
23262 IsOk());
23263 EXPECT_EQ("long-lived", response_long_lived_bar);
23264 trans_long_lived_bar.reset();
23265
23266 // Run the post-authentication requests.
23267 TestCompletionCallback callback_post_auth;
23268 auto trans_post_auth =
23269 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23270 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
23271 NetLogWithSource());
23272 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
23273 std::string response_post_auth;
23274 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
23275 IsOk());
23276 EXPECT_EQ("post-auth", response_post_auth);
23277 trans_post_auth.reset();
23278
23279 TestCompletionCallback callback_post_auth_bar;
23280 auto trans_post_auth_bar =
23281 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23282 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
23283 callback_post_auth_bar.callback(),
23284 NetLogWithSource());
23285 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
23286 std::string response_post_auth_bar;
23287 EXPECT_THAT(
23288 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
23289 IsOk());
23290 EXPECT_EQ("post-auth", response_post_auth_bar);
23291 trans_post_auth_bar.reset();
23292}
23293
[email protected]89ceba9a2009-03-21 03:46:0623294} // namespace net